aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/kernel/module.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/kernel/module.c')
-rw-r--r--arch/arm/kernel/module.c55
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
273static 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
286extern void fixup_pv_table(const void *, unsigned long);
287extern void fixup_smp(const void *, unsigned long);
288
271int module_finalize(const Elf32_Ehdr *hdr, const Elf_Shdr *sechdrs, 289int 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