From: Paul Mundt Date: Sun, 11 Oct 2009 23:50:07 +0000 (+0900) Subject: Merge branch 'sh/dwarf-unwinder' X-Git-Tag: v2.6.33-rc1~63^2~62^2~92 X-Git-Url: http://git.cascardo.info/?p=cascardo%2Flinux.git;a=commitdiff_plain;h=8ec006c58775869175edee3d23f4525b6df2935a Merge branch 'sh/dwarf-unwinder' Conflicts: arch/sh/kernel/dwarf.c --- 8ec006c58775869175edee3d23f4525b6df2935a diff --cc arch/sh/kernel/dwarf.c index 03b3616c80a5,f242cd120cf1..c274039e9c8d --- a/arch/sh/kernel/dwarf.c +++ b/arch/sh/kernel/dwarf.c @@@ -957,6 -954,92 +953,95 @@@ int dwarf_parse_section(char *eh_frame_ printk(KERN_INFO "DWARF unwinder initialised: read %u CIEs, %u FDEs\n", c_entries, f_entries); + return 0; + + out: + return err; + } + + /** + * dwarf_module_unload - remove FDE/CIEs associated with @mod + * @mod: the module that is being unloaded + * + * Remove any FDEs and CIEs from the global lists that came from + * @mod's .eh_frame section because @mod is being unloaded. + */ + void dwarf_module_unload(struct module *mod) + { + struct dwarf_fde *fde; + struct dwarf_cie *cie; + unsigned long flags; + + spin_lock_irqsave(&dwarf_cie_lock, flags); + + again_cie: + list_for_each_entry(cie, &dwarf_cie_list, link) { + if (cie->mod == mod) + break; + } + + if (&cie->link != &dwarf_cie_list) { + list_del(&cie->link); + kfree(cie); + goto again_cie; + } + + spin_unlock_irqrestore(&dwarf_cie_lock, flags); + + spin_lock_irqsave(&dwarf_fde_lock, flags); + + again_fde: + list_for_each_entry(fde, &dwarf_fde_list, link) { + if (fde->mod == mod) + break; + } + + if (&fde->link != &dwarf_fde_list) { + list_del(&fde->link); + kfree(fde); + goto again_fde; + } + + spin_unlock_irqrestore(&dwarf_fde_lock, flags); + } + + /** + * dwarf_unwinder_init - initialise the dwarf unwinder + * + * Build the data structures describing the .dwarf_frame section to + * make it easier to lookup CIE and FDE entries. Because the + * .eh_frame section is packed as tightly as possible it is not + * easy to lookup the FDE for a given PC, so we build a list of FDE + * and CIE entries that make it easier. + */ + static int __init dwarf_unwinder_init(void) + { + int err; + INIT_LIST_HEAD(&dwarf_cie_list); + INIT_LIST_HEAD(&dwarf_fde_list); + + dwarf_frame_cachep = kmem_cache_create("dwarf_frames", - sizeof(struct dwarf_frame), 0, SLAB_PANIC, NULL); ++ sizeof(struct dwarf_frame), 0, ++ SLAB_PANIC | SLAB_HWCACHE_ALIGN | SLAB_NOTRACK, NULL); ++ + dwarf_reg_cachep = kmem_cache_create("dwarf_regs", - sizeof(struct dwarf_reg), 0, SLAB_PANIC, NULL); ++ sizeof(struct dwarf_reg), 0, ++ SLAB_PANIC | SLAB_HWCACHE_ALIGN | SLAB_NOTRACK, NULL); + + dwarf_frame_pool = mempool_create(DWARF_FRAME_MIN_REQ, + mempool_alloc_slab, + mempool_free_slab, + dwarf_frame_cachep); + + dwarf_reg_pool = mempool_create(DWARF_REG_MIN_REQ, + mempool_alloc_slab, + mempool_free_slab, + dwarf_reg_cachep); + + err = dwarf_parse_section(__start_eh_frame, __stop_eh_frame, NULL); + if (err) + goto out; + err = unwinder_register(&dwarf_unwinder); if (err) goto out;