summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lld/ELF/InputSection.cpp2
-rw-r--r--lld/ELF/Target.cpp14
-rw-r--r--lld/ELF/Target.h2
-rw-r--r--lld/test/elf2/relocation.s11
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
OpenPOWER on IntegriCloud