X-Git-Url: http://www.pilppa.org/gitweb/gitweb.cgi?a=blobdiff_plain;f=arch%2Farm%2Fkernel%2Fmodule.c;h=d1731e39b496cc436a79fbb0631f181e166580e7;hb=9759d22c8348343b0da4e25d6150c41712686c14;hp=9f509fd00fda40fab3888c6f6865e843052aedfe;hpb=f0bba9f934517533acbda7329be93f55d5a01c03;p=linux-2.6-omap-h63xx.git diff --git a/arch/arm/kernel/module.c b/arch/arm/kernel/module.c index 9f509fd00fd..d1731e39b49 100644 --- a/arch/arm/kernel/module.c +++ b/arch/arm/kernel/module.c @@ -22,6 +22,7 @@ #include #include +#include #ifdef CONFIG_XIP_KERNEL /* @@ -66,6 +67,24 @@ int module_frob_arch_sections(Elf_Ehdr *hdr, char *secstrings, struct module *mod) { +#ifdef CONFIG_ARM_UNWIND + Elf_Shdr *s, *sechdrs_end = sechdrs + hdr->e_shnum; + + for (s = sechdrs; s < sechdrs_end; s++) { + if (strcmp(".ARM.exidx.init.text", secstrings + s->sh_name) == 0) + mod->arch.unw_sec_init = s; + else if (strcmp(".ARM.exidx.devinit.text", secstrings + s->sh_name) == 0) + mod->arch.unw_sec_devinit = s; + else if (strcmp(".ARM.exidx", secstrings + s->sh_name) == 0) + mod->arch.unw_sec_core = s; + else if (strcmp(".init.text", secstrings + s->sh_name) == 0) + mod->arch.sec_init_text = s; + else if (strcmp(".devinit.text", secstrings + s->sh_name) == 0) + mod->arch.sec_devinit_text = s; + else if (strcmp(".text", secstrings + s->sh_name) == 0) + mod->arch.sec_core_text = s; + } +#endif return 0; } @@ -104,6 +123,10 @@ apply_relocate(Elf32_Shdr *sechdrs, const char *strtab, unsigned int symindex, loc = dstsec->sh_addr + rel->r_offset; switch (ELF32_R_TYPE(rel->r_info)) { + case R_ARM_NONE: + /* ignore */ + break; + case R_ARM_ABS32: *(u32 *)loc += sym->st_value; break; @@ -141,6 +164,11 @@ apply_relocate(Elf32_Shdr *sechdrs, const char *strtab, unsigned int symindex, *(u32 *)loc |= 0x01a0f000; break; + case R_ARM_PREL31: + offset = *(u32 *)loc + sym->st_value - loc; + *(u32 *)loc = offset & 0x7fffffff; + break; + default: printk(KERN_ERR "%s: unknown relocation: %u\n", module->name, ELF32_R_TYPE(rel->r_info)); @@ -159,14 +187,50 @@ apply_relocate_add(Elf32_Shdr *sechdrs, const char *strtab, return -ENOEXEC; } +#ifdef CONFIG_ARM_UNWIND +static void register_unwind_tables(struct module *mod) +{ + if (mod->arch.unw_sec_init && mod->arch.sec_init_text) + mod->arch.unwind_init = + unwind_table_add(mod->arch.unw_sec_init->sh_addr, + mod->arch.unw_sec_init->sh_size, + mod->arch.sec_init_text->sh_addr, + mod->arch.sec_init_text->sh_size); + if (mod->arch.unw_sec_devinit && mod->arch.sec_devinit_text) + mod->arch.unwind_devinit = + unwind_table_add(mod->arch.unw_sec_devinit->sh_addr, + mod->arch.unw_sec_devinit->sh_size, + mod->arch.sec_devinit_text->sh_addr, + mod->arch.sec_devinit_text->sh_size); + if (mod->arch.unw_sec_core && mod->arch.sec_core_text) + mod->arch.unwind_core = + unwind_table_add(mod->arch.unw_sec_core->sh_addr, + mod->arch.unw_sec_core->sh_size, + mod->arch.sec_core_text->sh_addr, + mod->arch.sec_core_text->sh_size); +} + +static void unregister_unwind_tables(struct module *mod) +{ + unwind_table_del(mod->arch.unwind_init); + unwind_table_del(mod->arch.unwind_devinit); + unwind_table_del(mod->arch.unwind_core); +} +#else +static inline void register_unwind_tables(struct module *mod) { } +static inline void unregister_unwind_tables(struct module *mod) { } +#endif + int module_finalize(const Elf32_Ehdr *hdr, const Elf_Shdr *sechdrs, struct module *module) { + register_unwind_tables(module); return 0; } void module_arch_cleanup(struct module *mod) { + unregister_unwind_tables(mod); }