Commit 4edebbea authored by Rusty Russell's avatar Rusty Russell Committed by Anton Blanchard

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: default avatarRusty Russell <rusty@rustcorp.com.au>
parent 71ec7c55
...@@ -35,6 +35,7 @@ struct mod_arch_specific { ...@@ -35,6 +35,7 @@ struct mod_arch_specific {
#ifdef __powerpc64__ #ifdef __powerpc64__
unsigned int stubs_section; /* Index of stubs section in module */ unsigned int stubs_section; /* Index of stubs section in module */
unsigned int toc_section; /* What section is the TOC? */ unsigned int toc_section; /* What section is the TOC? */
bool toc_fixed; /* Have we fixed up .TOC.? */
#ifdef CONFIG_DYNAMIC_FTRACE #ifdef CONFIG_DYNAMIC_FTRACE
unsigned long toc; unsigned long toc;
unsigned long tramp; unsigned long tramp;
......
...@@ -196,6 +196,24 @@ static void dedotify(Elf64_Sym *syms, unsigned int numsyms, char *strtab) ...@@ -196,6 +196,24 @@ static void dedotify(Elf64_Sym *syms, unsigned int numsyms, char *strtab)
} }
} }
static Elf64_Sym *find_dot_toc(Elf64_Shdr *sechdrs,
const char *strtab,
unsigned int symindex)
{
unsigned int i, numsyms;
Elf64_Sym *syms;
syms = (Elf64_Sym *)sechdrs[symindex].sh_addr;
numsyms = sechdrs[symindex].sh_size / sizeof(Elf64_Sym);
for (i = 1; i < numsyms; i++) {
if (syms[i].st_shndx == SHN_UNDEF
&& strcmp(strtab + syms[i].st_name, ".TOC.") == 0)
return &syms[i];
}
return NULL;
}
int module_frob_arch_sections(Elf64_Ehdr *hdr, int module_frob_arch_sections(Elf64_Ehdr *hdr,
Elf64_Shdr *sechdrs, Elf64_Shdr *sechdrs,
char *secstrings, char *secstrings,
...@@ -337,6 +355,17 @@ int apply_relocate_add(Elf64_Shdr *sechdrs, ...@@ -337,6 +355,17 @@ int apply_relocate_add(Elf64_Shdr *sechdrs,
DEBUGP("Applying ADD relocate section %u to %u\n", relsec, DEBUGP("Applying ADD relocate section %u to %u\n", relsec,
sechdrs[relsec].sh_info); sechdrs[relsec].sh_info);
/* First time we're called, we can fix up .TOC. */
if (!me->arch.toc_fixed) {
sym = find_dot_toc(sechdrs, strtab, symindex);
/* It's theoretically possible that a module doesn't want a
* .TOC. so don't fail it just for that. */
if (sym)
sym->st_value = my_r2(sechdrs, me);
me->arch.toc_fixed = true;
}
for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rela); i++) { for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rela); i++) {
/* This is where to make the change */ /* This is where to make the change */
location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment