diff options
author | Rusty Russell <rusty@rustcorp.com.au> | 2014-03-18 05:29:26 -0400 |
---|---|---|
committer | Anton Blanchard <anton@samba.org> | 2014-04-22 20:05:29 -0400 |
commit | 4edebbeae3085e71f75584b6582495459e2e6cb2 (patch) | |
tree | bd272a73d1150e63bf3a1e86489f81d267dabbc7 /arch/powerpc/kernel/module_64.c | |
parent | 71ec7c55ed91e2352c00d51d171fccaa7cef5a00 (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.c | 29 |
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 | ||
199 | static 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 | |||
199 | int module_frob_arch_sections(Elf64_Ehdr *hdr, | 217 | int 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 |