mirror of
https://github.com/torvalds/linux.git
synced 2024-12-19 01:23:20 +00:00
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>
This commit is contained in:
parent
71ec7c55ed
commit
4edebbeae3
@ -35,6 +35,7 @@ struct mod_arch_specific {
|
||||
#ifdef __powerpc64__
|
||||
unsigned int stubs_section; /* Index of stubs section in module */
|
||||
unsigned int toc_section; /* What section is the TOC? */
|
||||
bool toc_fixed; /* Have we fixed up .TOC.? */
|
||||
#ifdef CONFIG_DYNAMIC_FTRACE
|
||||
unsigned long toc;
|
||||
unsigned long tramp;
|
||||
|
@ -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,
|
||||
Elf64_Shdr *sechdrs,
|
||||
char *secstrings,
|
||||
@ -337,6 +355,17 @@ int apply_relocate_add(Elf64_Shdr *sechdrs,
|
||||
|
||||
DEBUGP("Applying ADD relocate section %u to %u\n", relsec,
|
||||
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++) {
|
||||
/* This is where to make the change */
|
||||
location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr
|
||||
|
Loading…
Reference in New Issue
Block a user