diff options
author | David Brown <davidb@codeaurora.org> | 2011-03-17 01:13:16 -0400 |
---|---|---|
committer | David Brown <davidb@codeaurora.org> | 2011-03-17 01:13:16 -0400 |
commit | 92c260f755c42337c550d8ac1f8ccd1b32bffb20 (patch) | |
tree | 6d04fefc1adeecabfb2b00c201e0db78fa2b5529 /arch/arm/kernel/module.c | |
parent | 8e76a80960bf06c245160a484d5a363ca6b520bb (diff) | |
parent | 05e34754518b6a90d5c392790c032575fab12d66 (diff) |
Merge remote branch 'rmk/for-linus' into for-linus
* rmk/for-linus: (1557 commits)
ARM: 6806/1: irq: introduce entry and exit functions for chained handlers
ARM: 6781/1: Thumb-2: Work around buggy Thumb-2 short branch relocations in gas
ARM: 6747/1: P2V: Thumb2 support
ARM: 6798/1: aout-core: zero thread debug registers in a.out core dump
ARM: 6796/1: Footbridge: Fix I/O mappings for NOMMU mode
ARM: 6784/1: errata: no automatic Store Buffer drain on Cortex-A9
ARM: 6772/1: errata: possible fault MMU translations following an ASID switch
ARM: 6776/1: mach-ux500: activate fix for errata 753970
ARM: 6794/1: SPEAr: Append UL to device address macros.
ARM: 6793/1: SPEAr: Remove unused *_SIZE macros from spear*.h files
ARM: 6792/1: SPEAr: Replace SIZE macro's with SZ_4K macros
ARM: 6791/1: SPEAr3xx: Declare device structures after shirq code
ARM: 6790/1: SPEAr: Clock Framework: Rename usbd clock and align apb_clk entry
ARM: 6789/1: SPEAr3xx: Rename sdio to sdhci
ARM: 6788/1: SPEAr: Include mach/hardware.h instead of mach/spear.h
ARM: 6787/1: SPEAr: Reorder #includes in .h & .c files.
ARM: 6681/1: SPEAr: add debugfs support to clk API
ARM: 6703/1: SPEAr: update clk API support
ARM: 6679/1: SPEAr: make clk API functions more generic
ARM: 6737/1: SPEAr: formalized timer support
...
Conflicts:
arch/arm/mach-msm/board-msm7x27.c
arch/arm/mach-msm/board-msm7x30.c
arch/arm/mach-msm/board-qsd8x50.c
arch/arm/mach-msm/board-sapphire.c
arch/arm/mach-msm/include/mach/memory.h
Diffstat (limited to 'arch/arm/kernel/module.c')
-rw-r--r-- | arch/arm/kernel/module.c | 55 |
1 files changed, 41 insertions, 14 deletions
diff --git a/arch/arm/kernel/module.c b/arch/arm/kernel/module.c index 2cfe8161b478..fee7c36349eb 100644 --- a/arch/arm/kernel/module.c +++ b/arch/arm/kernel/module.c | |||
@@ -22,6 +22,7 @@ | |||
22 | 22 | ||
23 | #include <asm/pgtable.h> | 23 | #include <asm/pgtable.h> |
24 | #include <asm/sections.h> | 24 | #include <asm/sections.h> |
25 | #include <asm/smp_plat.h> | ||
25 | #include <asm/unwind.h> | 26 | #include <asm/unwind.h> |
26 | 27 | ||
27 | #ifdef CONFIG_XIP_KERNEL | 28 | #ifdef CONFIG_XIP_KERNEL |
@@ -75,6 +76,7 @@ apply_relocate(Elf32_Shdr *sechdrs, const char *strtab, unsigned int symindex, | |||
75 | for (i = 0; i < relsec->sh_size / sizeof(Elf32_Rel); i++, rel++) { | 76 | for (i = 0; i < relsec->sh_size / sizeof(Elf32_Rel); i++, rel++) { |
76 | unsigned long loc; | 77 | unsigned long loc; |
77 | Elf32_Sym *sym; | 78 | Elf32_Sym *sym; |
79 | const char *symname; | ||
78 | s32 offset; | 80 | s32 offset; |
79 | #ifdef CONFIG_THUMB2_KERNEL | 81 | #ifdef CONFIG_THUMB2_KERNEL |
80 | u32 upper, lower, sign, j1, j2; | 82 | u32 upper, lower, sign, j1, j2; |
@@ -82,18 +84,18 @@ apply_relocate(Elf32_Shdr *sechdrs, const char *strtab, unsigned int symindex, | |||
82 | 84 | ||
83 | offset = ELF32_R_SYM(rel->r_info); | 85 | offset = ELF32_R_SYM(rel->r_info); |
84 | if (offset < 0 || offset > (symsec->sh_size / sizeof(Elf32_Sym))) { | 86 | if (offset < 0 || offset > (symsec->sh_size / sizeof(Elf32_Sym))) { |
85 | printk(KERN_ERR "%s: bad relocation, section %d reloc %d\n", | 87 | pr_err("%s: section %u reloc %u: bad relocation sym offset\n", |
86 | module->name, relindex, i); | 88 | module->name, relindex, i); |
87 | return -ENOEXEC; | 89 | return -ENOEXEC; |
88 | } | 90 | } |
89 | 91 | ||
90 | sym = ((Elf32_Sym *)symsec->sh_addr) + offset; | 92 | sym = ((Elf32_Sym *)symsec->sh_addr) + offset; |
93 | symname = strtab + sym->st_name; | ||
91 | 94 | ||
92 | if (rel->r_offset < 0 || rel->r_offset > dstsec->sh_size - sizeof(u32)) { | 95 | if (rel->r_offset < 0 || rel->r_offset > dstsec->sh_size - sizeof(u32)) { |
93 | printk(KERN_ERR "%s: out of bounds relocation, " | 96 | pr_err("%s: section %u reloc %u sym '%s': out of bounds relocation, offset %d size %u\n", |
94 | "section %d reloc %d offset %d size %d\n", | 97 | module->name, relindex, i, symname, |
95 | module->name, relindex, i, rel->r_offset, | 98 | rel->r_offset, dstsec->sh_size); |
96 | dstsec->sh_size); | ||
97 | return -ENOEXEC; | 99 | return -ENOEXEC; |
98 | } | 100 | } |
99 | 101 | ||
@@ -119,10 +121,10 @@ apply_relocate(Elf32_Shdr *sechdrs, const char *strtab, unsigned int symindex, | |||
119 | if (offset & 3 || | 121 | if (offset & 3 || |
120 | offset <= (s32)0xfe000000 || | 122 | offset <= (s32)0xfe000000 || |
121 | offset >= (s32)0x02000000) { | 123 | offset >= (s32)0x02000000) { |
122 | printk(KERN_ERR | 124 | pr_err("%s: section %u reloc %u sym '%s': relocation %u out of range (%#lx -> %#x)\n", |
123 | "%s: relocation out of range, section " | 125 | module->name, relindex, i, symname, |
124 | "%d reloc %d sym '%s'\n", module->name, | 126 | ELF32_R_TYPE(rel->r_info), loc, |
125 | relindex, i, strtab + sym->st_name); | 127 | sym->st_value); |
126 | return -ENOEXEC; | 128 | return -ENOEXEC; |
127 | } | 129 | } |
128 | 130 | ||
@@ -195,10 +197,10 @@ apply_relocate(Elf32_Shdr *sechdrs, const char *strtab, unsigned int symindex, | |||
195 | if (!(offset & 1) || | 197 | if (!(offset & 1) || |
196 | offset <= (s32)0xff000000 || | 198 | offset <= (s32)0xff000000 || |
197 | offset >= (s32)0x01000000) { | 199 | offset >= (s32)0x01000000) { |
198 | printk(KERN_ERR | 200 | pr_err("%s: section %u reloc %u sym '%s': relocation %u out of range (%#lx -> %#x)\n", |
199 | "%s: relocation out of range, section " | 201 | module->name, relindex, i, symname, |
200 | "%d reloc %d sym '%s'\n", module->name, | 202 | ELF32_R_TYPE(rel->r_info), loc, |
201 | relindex, i, strtab + sym->st_name); | 203 | sym->st_value); |
202 | return -ENOEXEC; | 204 | return -ENOEXEC; |
203 | } | 205 | } |
204 | 206 | ||
@@ -268,12 +270,29 @@ struct mod_unwind_map { | |||
268 | const Elf_Shdr *txt_sec; | 270 | const Elf_Shdr *txt_sec; |
269 | }; | 271 | }; |
270 | 272 | ||
273 | static const Elf_Shdr *find_mod_section(const Elf32_Ehdr *hdr, | ||
274 | const Elf_Shdr *sechdrs, const char *name) | ||
275 | { | ||
276 | const Elf_Shdr *s, *se; | ||
277 | const char *secstrs = (void *)hdr + sechdrs[hdr->e_shstrndx].sh_offset; | ||
278 | |||
279 | for (s = sechdrs, se = sechdrs + hdr->e_shnum; s < se; s++) | ||
280 | if (strcmp(name, secstrs + s->sh_name) == 0) | ||
281 | return s; | ||
282 | |||
283 | return NULL; | ||
284 | } | ||
285 | |||
286 | extern void fixup_pv_table(const void *, unsigned long); | ||
287 | extern void fixup_smp(const void *, unsigned long); | ||
288 | |||
271 | int module_finalize(const Elf32_Ehdr *hdr, const Elf_Shdr *sechdrs, | 289 | int module_finalize(const Elf32_Ehdr *hdr, const Elf_Shdr *sechdrs, |
272 | struct module *mod) | 290 | struct module *mod) |
273 | { | 291 | { |
292 | const Elf_Shdr *s = NULL; | ||
274 | #ifdef CONFIG_ARM_UNWIND | 293 | #ifdef CONFIG_ARM_UNWIND |
275 | const char *secstrs = (void *)hdr + sechdrs[hdr->e_shstrndx].sh_offset; | 294 | const char *secstrs = (void *)hdr + sechdrs[hdr->e_shstrndx].sh_offset; |
276 | const Elf_Shdr *s, *sechdrs_end = sechdrs + hdr->e_shnum; | 295 | const Elf_Shdr *sechdrs_end = sechdrs + hdr->e_shnum; |
277 | struct mod_unwind_map maps[ARM_SEC_MAX]; | 296 | struct mod_unwind_map maps[ARM_SEC_MAX]; |
278 | int i; | 297 | int i; |
279 | 298 | ||
@@ -315,6 +334,14 @@ int module_finalize(const Elf32_Ehdr *hdr, const Elf_Shdr *sechdrs, | |||
315 | maps[i].txt_sec->sh_addr, | 334 | maps[i].txt_sec->sh_addr, |
316 | maps[i].txt_sec->sh_size); | 335 | maps[i].txt_sec->sh_size); |
317 | #endif | 336 | #endif |
337 | #ifdef CONFIG_ARM_PATCH_PHYS_VIRT | ||
338 | s = find_mod_section(hdr, sechdrs, ".pv_table"); | ||
339 | if (s) | ||
340 | fixup_pv_table((void *)s->sh_addr, s->sh_size); | ||
341 | #endif | ||
342 | s = find_mod_section(hdr, sechdrs, ".alt.smp.init"); | ||
343 | if (s && !is_smp()) | ||
344 | fixup_smp((void *)s->sh_addr, s->sh_size); | ||
318 | return 0; | 345 | return 0; |
319 | } | 346 | } |
320 | 347 | ||