aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sh/kernel/module.c
diff options
context:
space:
mode:
authorMatt Fleming <matt@console-pimps.org>2009-10-09 18:20:54 -0400
committerMatt Fleming <matt@console-pimps.org>2009-10-11 11:41:44 -0400
commita6a2f2ad67506090e332f440457553c0ec011d68 (patch)
treecfe974784b68cc3c09ed76e449a31d536b2b4589 /arch/sh/kernel/module.c
parentc153a58e715e16ffcd6c4b3da7fc6b4a556bf917 (diff)
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 <matt@console-pimps.org>
Diffstat (limited to 'arch/sh/kernel/module.c')
-rw-r--r--arch/sh/kernel/module.c32
1 files changed, 32 insertions, 0 deletions
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 @@
32#include <linux/string.h> 32#include <linux/string.h>
33#include <linux/kernel.h> 33#include <linux/kernel.h>
34#include <asm/unaligned.h> 34#include <asm/unaligned.h>
35#include <asm/dwarf.h>
35 36
36void *module_alloc(unsigned long size) 37void *module_alloc(unsigned long size)
37{ 38{
@@ -145,10 +146,41 @@ int module_finalize(const Elf_Ehdr *hdr,
145 const Elf_Shdr *sechdrs, 146 const Elf_Shdr *sechdrs,
146 struct module *me) 147 struct module *me)
147{ 148{
149#ifdef CONFIG_DWARF_UNWINDER
150 unsigned int i, err;
151 unsigned long start, end;
152 char *secstrings = (void *)hdr + sechdrs[hdr->e_shstrndx].sh_offset;
153
154 start = end = 0;
155
156 for (i = 1; i < hdr->e_shnum; i++) {
157 /* Alloc bit cleared means "ignore it." */
158 if ((sechdrs[i].sh_flags & SHF_ALLOC)
159 && !strcmp(secstrings+sechdrs[i].sh_name, ".eh_frame")) {
160 start = sechdrs[i].sh_addr;
161 end = start + sechdrs[i].sh_size;
162 break;
163 }
164 }
165
166 /* Did we find the .eh_frame section? */
167 if (i != hdr->e_shnum) {
168 err = dwarf_parse_section((char *)start, (char *)end, me);
169 if (err)
170 printk(KERN_WARNING "%s: failed to parse DWARF info\n",
171 me->name);
172 }
173
174#endif /* CONFIG_DWARF_UNWINDER */
175
148 return module_bug_finalize(hdr, sechdrs, me); 176 return module_bug_finalize(hdr, sechdrs, me);
149} 177}
150 178
151void module_arch_cleanup(struct module *mod) 179void module_arch_cleanup(struct module *mod)
152{ 180{
153 module_bug_cleanup(mod); 181 module_bug_cleanup(mod);
182
183#ifdef CONFIG_DWARF_UNWINDER
184 dwarf_module_unload(mod);
185#endif /* CONFIG_DWARF_UNWINDER */
154} 186}