diff --git a/lld/ELF/Arch/X86_64.cpp b/lld/ELF/Arch/X86_64.cpp --- a/lld/ELF/Arch/X86_64.cpp +++ b/lld/ELF/Arch/X86_64.cpp @@ -356,6 +356,8 @@ return R_GOT_PC; case R_X86_64_GOTOFF64: return R_GOTPLTREL; + case R_X86_64_PLTOFF64: + return R_PLT_GOTPLT; case R_X86_64_GOTPC32: case R_X86_64_GOTPC64: return R_GOTPLTONLY_PC; @@ -718,6 +720,7 @@ case R_X86_64_GOT64: case R_X86_64_GOTOFF64: case R_X86_64_GOTPC64: + case R_X86_64_PLTOFF64: case R_X86_64_IRELATIVE: case R_X86_64_RELATIVE: return read64le(buf); @@ -779,6 +782,7 @@ case R_X86_64_GOT64: case R_X86_64_GOTOFF64: case R_X86_64_GOTPC64: + case R_X86_64_PLTOFF64: write64le(loc, val); break; default: diff --git a/lld/ELF/InputSection.cpp b/lld/ELF/InputSection.cpp --- a/lld/ELF/InputSection.cpp +++ b/lld/ELF/InputSection.cpp @@ -795,6 +795,8 @@ case R_PLT_PC: case R_PPC64_CALL_PLT: return sym.getPltVA() + a - p; + case R_PLT_GOTPLT: + return sym.getPltVA() + a - in.gotPlt->getVA(); case R_PPC32_PLTREL: // R_PPC_PLTREL24 uses the addend (usually 0 or 0x8000) to indicate r30 // stores _GLOBAL_OFFSET_TABLE_ or .got2+0x8000. The addend is ignored for diff --git a/lld/ELF/Relocations.h b/lld/ELF/Relocations.h --- a/lld/ELF/Relocations.h +++ b/lld/ELF/Relocations.h @@ -45,6 +45,7 @@ R_PC, R_PLT, R_PLT_PC, + R_PLT_GOTPLT, R_RELAX_GOT_PC, R_RELAX_GOT_PC_NOPIC, R_RELAX_TLS_GD_TO_IE, diff --git a/lld/ELF/Relocations.cpp b/lld/ELF/Relocations.cpp --- a/lld/ELF/Relocations.cpp +++ b/lld/ELF/Relocations.cpp @@ -188,7 +188,8 @@ // Returns true if Expr refers a PLT entry. static bool needsPlt(RelExpr expr) { - return oneof(expr); + return oneof( + expr); } // Returns true if Expr refers a GOT entry. Note that this function @@ -224,11 +225,10 @@ R_MIPS_GOT_LOCAL_PAGE, R_MIPS_GOTREL, R_MIPS_GOT_OFF, R_MIPS_GOT_OFF32, R_MIPS_GOT_GP_PC, R_MIPS_TLSGD, R_AARCH64_GOT_PAGE_PC, R_GOT_PC, R_GOTONLY_PC, R_GOTPLTONLY_PC, - R_PLT_PC, R_TLSGD_GOT, R_TLSGD_GOTPLT, R_TLSGD_PC, R_PPC32_PLTREL, - R_PPC64_CALL_PLT, R_PPC64_RELAX_TOC, R_RISCV_ADD, R_TLSDESC_CALL, - R_TLSDESC_PC, R_AARCH64_TLSDESC_PAGE, R_TLSLD_HINT, R_TLSIE_HINT, - R_AARCH64_GOT_PAGE>( - e)) + R_PLT_PC, R_PLT_GOTPLT, R_TLSGD_GOT, R_TLSGD_GOTPLT, R_TLSGD_PC, + R_PPC32_PLTREL, R_PPC64_CALL_PLT, R_PPC64_RELAX_TOC, R_RISCV_ADD, + R_TLSDESC_CALL, R_TLSDESC_PC, R_AARCH64_TLSDESC_PAGE, R_TLSLD_HINT, + R_TLSIE_HINT, R_AARCH64_GOT_PAGE>(e)) return true; // These never do, except if the entire file is position dependent or if @@ -300,6 +300,8 @@ return R_PPC64_CALL; case R_PLT: return R_ABS; + case R_PLT_GOTPLT: + return R_GOTPLTREL; default: return expr; } @@ -1394,8 +1396,9 @@ // If the relocation does not emit a GOT or GOTPLT entry but its computation // uses their addresses, we need GOT or GOTPLT to be created. // - // The 4 types that relative GOTPLT are all x86 and x86-64 specific. - if (oneof(expr)) { + // The 5 types that relative GOTPLT are all x86 and x86-64 specific. + if (oneof(expr)) { in.gotPlt->hasGotPltOffRel = true; } else if (oneof( expr)) { diff --git a/lld/test/ELF/x86-64-reloc-pltoff64.s b/lld/test/ELF/x86-64-reloc-pltoff64.s new file mode 100644 --- /dev/null +++ b/lld/test/ELF/x86-64-reloc-pltoff64.s @@ -0,0 +1,41 @@ +# REQUIRES: x86 +## Test R_X86_64_PLTOFF64 (preemptible: L - GOT + A; non-preemptible: S - GOT + A). + +# RUN: llvm-mc -filetype=obj -triple=x86_64 %s -o %t.o +# RUN: ld.lld %t.o -shared -o %t.so +# RUN: llvm-readelf -S %t.so | FileCheck %s --check-prefix=SEC-SHARED +# RUN: llvm-objdump -d --no-show-raw-insn %t.so | FileCheck %s --check-prefix=SHARED + +# RUN: ld.lld %t.o -o %t +# RUN: llvm-readelf -S %t | FileCheck %s --check-prefix=SEC-PDE +# RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck %s --check-prefix=PDE + +# SEC-SHARED: .got.plt PROGBITS 00000000000033c0 0003c0 000028 + +## foo@plt - .got.plt = 0x12f0 - 0x33c0 = -8400 +## undefweak@plt - .got.plt = 0x1300 - 0x33c0 = -8384 +# SHARED-LABEL: <.text>: +# SHARED-NEXT: movabsq $-8400, %rdx +# SHARED-NEXT: movabsq $-8384, %rdx +# SHARED-LABEL: : +# SHARED-NEXT: 12f0: jmpq {{.*}}(%rip) + +# SEC-PDE: .got.plt PROGBITS 0000000000202170 000170 000018 + +## Avoid PLT since the referenced symbol is non-preemptible. +## foo - .got.plt = 0x20116c - 0x202170 = -4100 +## 0 - .got.plt = 0 - 0x202168 = -2105712 +# PDE-LABEL: <.text>: +# PDE-NEXT: movabsq $-4100, %rdx +# PDE-NEXT: movabsq $-2105712, %rdx +# PDE-LABEL: : +# PDE-NEXT: 20116c: retq + + movabsq $foo@PLTOFF, %rdx + movabsq $undefweak@PLTOFF, %rdx + +.globl foo +foo: + ret + +.weak undefweak