Skip to content

Commit b21ebf2

Browse files
hjl-toolstorvalds
authored andcommitted
x86: Treat R_X86_64_PLT32 as R_X86_64_PC32
On i386, there are 2 types of PLTs, PIC and non-PIC. PIE and shared objects must use PIC PLT. To use PIC PLT, you need to load _GLOBAL_OFFSET_TABLE_ into EBX first. There is no need for that on x86-64 since x86-64 uses PC-relative PLT. On x86-64, for 32-bit PC-relative branches, we can generate PLT32 relocation, instead of PC32 relocation, which can also be used as a marker for 32-bit PC-relative branches. Linker can always reduce PLT32 relocation to PC32 if function is defined locally. Local functions should use PC32 relocation. As far as Linux kernel is concerned, R_X86_64_PLT32 can be treated the same as R_X86_64_PC32 since Linux kernel doesn't use PLT. R_X86_64_PLT32 for 32-bit PC-relative branches has been enabled in binutils master branch which will become binutils 2.31. [ hjl is working on having better documentation on this all, but a few more notes from him: "PLT32 relocation is used as marker for PC-relative branches. Because of EBX, it looks odd to generate PLT32 relocation on i386 when EBX doesn't have GOT. As for symbol resolution, PLT32 and PC32 relocations are almost interchangeable. But when linker sees PLT32 relocation against a protected symbol, it can resolved locally at link-time since it is used on a branch instruction. Linker can't do that for PC32 relocation" but for the kernel use, the two are basically the same, and this commit gets things building and working with the current binutils master - Linus ] Signed-off-by: H.J. Lu <hjl.tools@gmail.com> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
1 parent af3e79d commit b21ebf2

File tree

3 files changed

+5
-0
lines changed

3 files changed

+5
-0
lines changed

arch/x86/kernel/machine_kexec_64.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -542,6 +542,7 @@ int arch_kexec_apply_relocations_add(const Elf64_Ehdr *ehdr,
542542
goto overflow;
543543
break;
544544
case R_X86_64_PC32:
545+
case R_X86_64_PLT32:
545546
value -= (u64)address;
546547
*(u32 *)location = value;
547548
break;

arch/x86/kernel/module.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,7 @@ int apply_relocate_add(Elf64_Shdr *sechdrs,
191191
goto overflow;
192192
break;
193193
case R_X86_64_PC32:
194+
case R_X86_64_PLT32:
194195
if (*(u32 *)loc != 0)
195196
goto invalid_relocation;
196197
val -= (u64)loc;

arch/x86/tools/relocs.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -770,9 +770,12 @@ static int do_reloc64(struct section *sec, Elf_Rel *rel, ElfW(Sym) *sym,
770770
break;
771771

772772
case R_X86_64_PC32:
773+
case R_X86_64_PLT32:
773774
/*
774775
* PC relative relocations don't need to be adjusted unless
775776
* referencing a percpu symbol.
777+
*
778+
* NB: R_X86_64_PLT32 can be treated as R_X86_64_PC32.
776779
*/
777780
if (is_percpu_sym(sym, symname))
778781
add_reloc(&relocs32neg, offset);

0 commit comments

Comments
 (0)