diff options
-rw-r--r-- | lld/ELF/InputSection.cpp | 2 | ||||
-rw-r--r-- | lld/ELF/Target.cpp | 14 | ||||
-rw-r--r-- | lld/ELF/Target.h | 2 | ||||
-rw-r--r-- | lld/test/elf2/relocation.s | 11 |
4 files changed, 24 insertions, 5 deletions
diff --git a/lld/ELF/InputSection.cpp b/lld/ELF/InputSection.cpp index eabfeb15d68..d1236fd1a58 100644 --- a/lld/ELF/InputSection.cpp +++ b/lld/ELF/InputSection.cpp @@ -51,7 +51,7 @@ void InputSection<ELFT>::relocate( uintX_t SymVA = getSymVA<ELFT>(Body); if (Target->relocNeedsPlt(Type, Body)) { SymVA = Out<ELFT>::Plt->getEntryAddr(Body); - Type = Target->getPCRelReloc(); + Type = Target->getPLTRefReloc(Type); } else if (Target->relocNeedsGot(Type, Body)) { SymVA = Out<ELFT>::Got->getEntryAddr(Body); Type = Target->getGotRefReloc(); diff --git a/lld/ELF/Target.cpp b/lld/ELF/Target.cpp index 4ae54b4b4c8..21c731ebcbd 100644 --- a/lld/ELF/Target.cpp +++ b/lld/ELF/Target.cpp @@ -59,6 +59,8 @@ TargetInfo *createTarget() { TargetInfo::~TargetInfo() {} +unsigned TargetInfo::getPLTRefReloc(unsigned Type) const { return PCRelReloc; } + bool TargetInfo::relocPointsToGot(uint32_t Type) const { return false; } bool TargetInfo::isRelRelative(uint32_t Type) const { return true; } @@ -144,10 +146,22 @@ bool X86_64TargetInfo::relocNeedsGot(uint32_t Type, const SymbolBody &S) const { return Type == R_X86_64_GOTPCREL || relocNeedsPlt(Type, S); } +unsigned X86_64TargetInfo::getPLTRefReloc(unsigned Type) const { + switch (Type) { + case R_X86_64_32: + return R_X86_64_32; + case R_X86_64_PC32: + case R_X86_64_PLT32: + return R_X86_64_PC32; + } + llvm_unreachable("Unexpected relocation"); +} + bool X86_64TargetInfo::relocNeedsPlt(uint32_t Type, const SymbolBody &S) const { switch (Type) { default: return false; + case R_X86_64_32: case R_X86_64_PC32: // This relocation is defined to have a value of (S + A - P). // The problems start when a non PIC program calls a function in a shared diff --git a/lld/ELF/Target.h b/lld/ELF/Target.h index d4f059312c5..4a371e1002a 100644 --- a/lld/ELF/Target.h +++ b/lld/ELF/Target.h @@ -26,6 +26,7 @@ public: unsigned getGotRefReloc() const { return GotRefReloc; } unsigned getRelativeReloc() const { return RelativeReloc; } unsigned getPltEntrySize() const { return PltEntrySize; } + virtual unsigned getPLTRefReloc(unsigned Type) const; virtual void writePltEntry(uint8_t *Buf, uint64_t GotEntryAddr, uint64_t PltEntryAddr) const = 0; virtual bool isRelRelative(uint32_t Type) const; @@ -63,6 +64,7 @@ public: class X86_64TargetInfo final : public TargetInfo { public: X86_64TargetInfo(); + unsigned getPLTRefReloc(unsigned Type) const override; void writePltEntry(uint8_t *Buf, uint64_t GotEntryAddr, uint64_t PltEntryAddr) const override; bool relocNeedsGot(uint32_t Type, const SymbolBody &S) const override; diff --git a/lld/test/elf2/relocation.s b/lld/test/elf2/relocation.s index 84b8d8c91aa..c916eed0e5a 100644 --- a/lld/test/elf2/relocation.s +++ b/lld/test/elf2/relocation.s @@ -12,8 +12,8 @@ // SEC-NEXT: SHF_ALLOC // SEC-NEXT: SHF_EXECINSTR // SEC-NEXT: ] -// SEC-NEXT: Address: 0x11020 -// SEC-NEXT: Offset: 0x1020 +// SEC-NEXT: Address: 0x11030 +// SEC-NEXT: Offset: 0x1030 // SEC-NEXT: Size: 8 // SEC: Name: .got @@ -75,10 +75,13 @@ R_X86_64_32S: .global R_X86_64_PC32 R_X86_64_PC32: call bar -// 0x11020 - (0x11017 + 5) = 4 + movl $bar, %eax +// 0x11030 - (0x11017 + 5) = 20 +// 0x11030 = 69680 // CHECK: Disassembly of section .R_X86_64_PC32: // CHECK-NEXT: R_X86_64_PC32: -// CHECK-NEXT: 11017: e8 04 00 00 00 callq 4 +// CHECK-NEXT: 11017: {{.*}} callq 20 +// CHECK-NEXT: 1101c: {{.*}} movl $69680, %eax .section .R_X86_64_64,"a",@progbits .global R_X86_64_64 |