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