diff options
| -rw-r--r-- | lld/ELF/InputSection.cpp | 3 | ||||
| -rw-r--r-- | lld/ELF/Target.cpp | 6 | ||||
| -rw-r--r-- | lld/ELF/Target.h | 2 | ||||
| -rw-r--r-- | lld/test/elf2/relocation-i686.s | 27 |
4 files changed, 37 insertions, 1 deletions
diff --git a/lld/ELF/InputSection.cpp b/lld/ELF/InputSection.cpp index 91b35faae0f..e7c2e7dfd9f 100644 --- a/lld/ELF/InputSection.cpp +++ b/lld/ELF/InputSection.cpp @@ -57,6 +57,9 @@ void InputSection<ELFT>::relocate( } else if (Target->relocNeedsGot(Type)) { SymVA = GotSec.getEntryAddr(Body); Type = Target->getPCRelReloc(); + } else if (Target->relocPointsToGot(Type)) { + SymVA = GotSec.getVA(); + Type = Target->getPCRelReloc(); } } diff --git a/lld/ELF/Target.cpp b/lld/ELF/Target.cpp index 493b8e77179..97c8b8e9dc1 100644 --- a/lld/ELF/Target.cpp +++ b/lld/ELF/Target.cpp @@ -27,6 +27,8 @@ std::unique_ptr<TargetInfo> Target; TargetInfo::~TargetInfo() {} +bool TargetInfo::relocPointsToGot(uint32_t Type) const { return false; } + X86TargetInfo::X86TargetInfo() { PCRelReloc = R_386_PC32; GotReloc = R_386_GLOB_DAT; @@ -57,6 +59,10 @@ bool X86TargetInfo::relocNeedsGot(uint32_t Type) const { } } +bool X86TargetInfo::relocPointsToGot(uint32_t Type) const { + return Type == R_386_GOTPC; +} + bool X86TargetInfo::relocNeedsPlt(uint32_t Type) const { switch (Type) { default: diff --git a/lld/ELF/Target.h b/lld/ELF/Target.h index 1a87381e16e..2241f934398 100644 --- a/lld/ELF/Target.h +++ b/lld/ELF/Target.h @@ -26,6 +26,7 @@ public: virtual void writePltEntry(uint8_t *Buf, uint64_t GotEntryAddr, uint64_t PltEntryAddr) const = 0; virtual bool relocNeedsGot(uint32_t Type) const = 0; + virtual bool relocPointsToGot(uint32_t Type) const; virtual bool relocNeedsPlt(uint32_t Type) const = 0; virtual void relocateOne(uint8_t *Buf, const void *RelP, uint32_t Type, uint64_t BaseAddr, uint64_t SymVA) const = 0; @@ -44,6 +45,7 @@ public: void writePltEntry(uint8_t *Buf, uint64_t GotEntryAddr, uint64_t PltEntryAddr) const override; bool relocNeedsGot(uint32_t Type) const override; + bool relocPointsToGot(uint32_t Type) const override; bool relocNeedsPlt(uint32_t Type) const override; void relocateOne(uint8_t *Buf, const void *RelP, uint32_t Type, uint64_t BaseAddr, uint64_t SymVA) const override; diff --git a/lld/test/elf2/relocation-i686.s b/lld/test/elf2/relocation-i686.s index 6648f1ac79f..3e068f6f59c 100644 --- a/lld/test/elf2/relocation-i686.s +++ b/lld/test/elf2/relocation-i686.s @@ -1,5 +1,8 @@ // RUN: llvm-mc -filetype=obj -triple=i686-pc-linux %s -o %t -// RUN: lld -flavor gnu2 %t -o %t2 +// RUN: llvm-mc -filetype=obj -triple=i686-unknown-linux %p/Inputs/shared.s -o %t2.o +// RUN: lld -flavor gnu2 -shared %t2.o -o %t2.so +// RUN: lld -flavor gnu2 %t %t2.so -o %t2 +// RUN: llvm-readobj -s %t2 | FileCheck --check-prefix=ADDR %s // RUN: llvm-objdump -d %t2 | FileCheck %s // REQUIRES: x86 @@ -32,3 +35,25 @@ R_386_PC32_2: // CHECK: R_386_PC32_2: // CHECK-NEXT: 1100e: 90 nop + +// Create a .got +movl bar@GOT, %eax + + +// ADDR: Name: .got (14) +// ADDR-NEXT: Type: SHT_PROGBITS +// ADDR-NEXT: Flags [ +// ADDR-NEXT: SHF_ALLOC +// ADDR-NEXT: SHF_WRITE +// ADDR-NEXT: ] +// ADDR-NEXT: Address: 0x15000 + +.section .R_386_GOTPC,"ax",@progbits +R_386_GOTPC: + movl $_GLOBAL_OFFSET_TABLE_, %eax + +// 0x15000 - 0x11014 = 16364 + +// CHECK: Disassembly of section .R_386_GOTPC: +// CHECK-NEXT: R_386_GOTPC: +// CHECK-NEXT: 11014: {{.*}} movl $16364, %eax |

