aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/kernel/module_64.c
diff options
context:
space:
mode:
authorRusty Russell <rusty@rustcorp.com.au>2014-03-18 05:29:26 -0400
committerAnton Blanchard <anton@samba.org>2014-04-22 20:05:29 -0400
commit4edebbeae3085e71f75584b6582495459e2e6cb2 (patch)
treebd272a73d1150e63bf3a1e86489f81d267dabbc7 /arch/powerpc/kernel/module_64.c
parent71ec7c55ed91e2352c00d51d171fccaa7cef5a00 (diff)
powerpc: Fix up TOC. for modules.
The kernel resolved the '.TOC.' to a fake symbol, so we need to fix it up to point to our .toc section plus 0x8000. Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Diffstat (limited to 'arch/powerpc/kernel/module_64.c')
-rw-r--r--arch/powerpc/kernel/module_64.c29
1 files changed, 29 insertions, 0 deletions
diff --git a/arch/powerpc/kernel/module_64.c b/arch/powerpc/kernel/module_64.c
index a8694d462079..f6544d7071d6 100644
--- a/arch/powerpc/kernel/module_64.c
+++ b/arch/powerpc/kernel/module_64.c
@@ -196,6 +196,24 @@ static void dedotify(Elf64_Sym *syms, unsigned int numsyms, char *strtab)
196 } 196 }
197} 197}
198 198
199static Elf64_Sym *find_dot_toc(Elf64_Shdr *sechdrs,
200 const char *strtab,
201 unsigned int symindex)
202{
203 unsigned int i, numsyms;
204 Elf64_Sym *syms;
205
206 syms = (Elf64_Sym *)sechdrs[symindex].sh_addr;
207 numsyms = sechdrs[symindex].sh_size / sizeof(Elf64_Sym);
208
209 for (i = 1; i < numsyms; i++) {
210 if (syms[i].st_shndx == SHN_UNDEF
211 && strcmp(strtab + syms[i].st_name, ".TOC.") == 0)
212 return &syms[i];
213 }
214 return NULL;
215}
216
199int module_frob_arch_sections(Elf64_Ehdr *hdr, 217int module_frob_arch_sections(Elf64_Ehdr *hdr,
200 Elf64_Shdr *sechdrs, 218 Elf64_Shdr *sechdrs,
201 char *secstrings, 219 char *secstrings,
@@ -337,6 +355,17 @@ int apply_relocate_add(Elf64_Shdr *sechdrs,
337 355
338 DEBUGP("Applying ADD relocate section %u to %u\n", relsec, 356 DEBUGP("Applying ADD relocate section %u to %u\n", relsec,
339 sechdrs[relsec].sh_info); 357 sechdrs[relsec].sh_info);
358
359 /* First time we're called, we can fix up .TOC. */
360 if (!me->arch.toc_fixed) {
361 sym = find_dot_toc(sechdrs, strtab, symindex);
362 /* It's theoretically possible that a module doesn't want a
363 * .TOC. so don't fail it just for that. */
364 if (sym)
365 sym->st_value = my_r2(sechdrs, me);
366 me->arch.toc_fixed = true;
367 }
368
340 for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rela); i++) { 369 for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rela); i++) {
341 /* This is where to make the change */ 370 /* This is where to make the change */
342 location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr 371 location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr