aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arc/kernel/module.c
diff options
context:
space:
mode:
authorVineet Gupta <vgupta@synopsys.com>2013-01-22 06:33:19 -0500
committerVineet Gupta <vgupta@synopsys.com>2013-02-15 12:46:03 -0500
commit854a0d95056c265d96cb449bc97bc5ef9bbed835 (patch)
tree798c834ae188bd570b861a47765fce8ed633f85a /arch/arc/kernel/module.c
parent41195d236e84458bebd4fdc218610a92231ac791 (diff)
ARC: DWARF2 .debug_frame based stack unwinder
-Originally written by Rajeshwar Ranga -Derived off of generic unwinder in 2.6.19 and adapted to ARC Signed-off-by: Vineet Gupta <vgupta@synopsys.com> Cc: Rajeshwar Ranga <rajeshwar.ranga@gmail.com>
Diffstat (limited to 'arch/arc/kernel/module.c')
-rw-r--r--arch/arc/kernel/module.c58
1 files changed, 58 insertions, 0 deletions
diff --git a/arch/arc/kernel/module.c b/arch/arc/kernel/module.c
index a1bb70d6e97d..cdd359352c0a 100644
--- a/arch/arc/kernel/module.c
+++ b/arch/arc/kernel/module.c
@@ -14,6 +14,7 @@
14#include <linux/slab.h> 14#include <linux/slab.h>
15#include <linux/fs.h> 15#include <linux/fs.h>
16#include <linux/string.h> 16#include <linux/string.h>
17#include <asm/unwind.h>
17 18
18static inline void arc_write_me(unsigned short *addr, unsigned long value) 19static inline void arc_write_me(unsigned short *addr, unsigned long value)
19{ 20{
@@ -21,6 +22,42 @@ static inline void arc_write_me(unsigned short *addr, unsigned long value)
21 *(addr + 1) = (value & 0xffff); 22 *(addr + 1) = (value & 0xffff);
22} 23}
23 24
25/* ARC specific section quirks - before relocation loop in generic loader
26 *
27 * For dwarf unwinding out of modules, this needs to
28 * 1. Ensure the .debug_frame is allocatable (ARC Linker bug: despite
29 * -fasynchronous-unwind-tables it doesn't).
30 * 2. Since we are iterating thru sec hdr tbl anyways, make a note of
31 * the exact section index, for later use.
32 */
33int module_frob_arch_sections(Elf_Ehdr *hdr, Elf_Shdr *sechdrs,
34 char *secstr, struct module *mod)
35{
36#ifdef CONFIG_ARC_DW2_UNWIND
37 int i;
38
39 mod->arch.unw_sec_idx = 0;
40 mod->arch.unw_info = NULL;
41
42 for (i = 1; i < hdr->e_shnum; i++) {
43 if (strcmp(secstr+sechdrs[i].sh_name, ".debug_frame") == 0) {
44 sechdrs[i].sh_flags |= SHF_ALLOC;
45 mod->arch.unw_sec_idx = i;
46 break;
47 }
48 }
49#endif
50 return 0;
51}
52
53void module_arch_cleanup(struct module *mod)
54{
55#ifdef CONFIG_ARC_DW2_UNWIND
56 if (mod->arch.unw_info)
57 unwind_remove_table(mod->arch.unw_info, 0);
58#endif
59}
60
24int apply_relocate_add(Elf32_Shdr *sechdrs, 61int apply_relocate_add(Elf32_Shdr *sechdrs,
25 const char *strtab, 62 const char *strtab,
26 unsigned int symindex, /* sec index for sym tbl */ 63 unsigned int symindex, /* sec index for sym tbl */
@@ -85,3 +122,24 @@ relo_err:
85 return -ENOEXEC; 122 return -ENOEXEC;
86 123
87} 124}
125
126/* Just before lift off: After sections have been relocated, we add the
127 * dwarf section to unwinder table pool
128 * This couldn't be done in module_frob_arch_sections() because
129 * relocations had not been applied by then
130 */
131int module_finalize(const Elf32_Ehdr *hdr, const Elf_Shdr *sechdrs,
132 struct module *mod)
133{
134#ifdef CONFIG_ARC_DW2_UNWIND
135 void *unw;
136 int unwsec = mod->arch.unw_sec_idx;
137
138 if (unwsec) {
139 unw = unwind_add_table(mod, (void *)sechdrs[unwsec].sh_addr,
140 sechdrs[unwsec].sh_size);
141 mod->arch.unw_info = unw;
142 }
143#endif
144 return 0;
145}