From a6a2f2ad67506090e332f440457553c0ec011d68 Mon Sep 17 00:00:00 2001 From: Matt Fleming Date: Fri, 9 Oct 2009 23:20:54 +0100 Subject: sh: Teach the DWARF unwinder about modules Pass a module's .eh_frame section to the DWARF unwinder at module load time so that the section's FDEs and CIEs can be registered with the DWARF unwinder. This allows us to unwind the stack through module code when generating backtraces. Signed-off-by: Matt Fleming --- arch/sh/kernel/module.c | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) (limited to 'arch/sh/kernel/module.c') diff --git a/arch/sh/kernel/module.c b/arch/sh/kernel/module.c index c2efdcde266f..d297a148d16c 100644 --- a/arch/sh/kernel/module.c +++ b/arch/sh/kernel/module.c @@ -32,6 +32,7 @@ #include #include #include +#include void *module_alloc(unsigned long size) { @@ -145,10 +146,41 @@ int module_finalize(const Elf_Ehdr *hdr, const Elf_Shdr *sechdrs, struct module *me) { +#ifdef CONFIG_DWARF_UNWINDER + unsigned int i, err; + unsigned long start, end; + char *secstrings = (void *)hdr + sechdrs[hdr->e_shstrndx].sh_offset; + + start = end = 0; + + for (i = 1; i < hdr->e_shnum; i++) { + /* Alloc bit cleared means "ignore it." */ + if ((sechdrs[i].sh_flags & SHF_ALLOC) + && !strcmp(secstrings+sechdrs[i].sh_name, ".eh_frame")) { + start = sechdrs[i].sh_addr; + end = start + sechdrs[i].sh_size; + break; + } + } + + /* Did we find the .eh_frame section? */ + if (i != hdr->e_shnum) { + err = dwarf_parse_section((char *)start, (char *)end, me); + if (err) + printk(KERN_WARNING "%s: failed to parse DWARF info\n", + me->name); + } + +#endif /* CONFIG_DWARF_UNWINDER */ + return module_bug_finalize(hdr, sechdrs, me); } void module_arch_cleanup(struct module *mod) { module_bug_cleanup(mod); + +#ifdef CONFIG_DWARF_UNWINDER + dwarf_module_unload(mod); +#endif /* CONFIG_DWARF_UNWINDER */ } -- cgit v1.2.3