Add support for relocating R_X86_64_GOTPCREL.
llvm-svn: 248425
diff --git a/lld/ELF/InputSection.cpp b/lld/ELF/InputSection.cpp
index e8fa4a6..2b57e5f 100644
--- a/lld/ELF/InputSection.cpp
+++ b/lld/ELF/InputSection.cpp
@@ -50,6 +50,7 @@
const SymbolBody *Body = File.getSymbolBody(SymIndex);
if (!Body)
continue;
+ uint32_t OrigType = Type;
switch (Body->kind()) {
case SymbolBody::DefinedRegularKind:
SymVA = getSymVA<ELFT>(cast<DefinedRegular<ELFT>>(Body));
@@ -63,15 +64,12 @@
break;
}
case SymbolBody::SharedKind:
- if (Target->relocNeedsPlt(Type)) {
- SymVA = PltSec.getEntryAddr(*Body);
+ if (Target->relocNeedsPlt(Type))
Type = Target->getPCRelReloc();
- } else if (Target->relocNeedsGot(Type)) {
- SymVA = GotSec.getEntryAddr(*Body);
+ else if (Target->relocNeedsGot(Type))
Type = Target->getPCRelReloc();
- } else {
+ else
continue;
- }
break;
case SymbolBody::UndefinedKind:
assert(Body->isWeak() && "Undefined symbol reached writer");
@@ -80,6 +78,11 @@
case SymbolBody::LazyKind:
llvm_unreachable("Lazy symbol reached writer");
}
+
+ if (Target->relocNeedsPlt(OrigType))
+ SymVA = PltSec.getEntryAddr(*Body);
+ else if (Target->relocNeedsGot(OrigType))
+ SymVA = GotSec.getEntryAddr(*Body);
}
Target->relocateOne(Buf, reinterpret_cast<const void *>(&RI), Type,
diff --git a/lld/ELF/Target.cpp b/lld/ELF/Target.cpp
index ff0ccc4..ea20ced 100644
--- a/lld/ELF/Target.cpp
+++ b/lld/ELF/Target.cpp
@@ -137,6 +137,7 @@
uint8_t *Location = Buf + Offset;
switch (Type) {
case R_X86_64_PC32:
+ case R_X86_64_GOTPCREL:
support::endian::write32le(Location,
SymVA + Rel.r_addend - (BaseAddr + Offset));
break;
diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp
index c8985aa..5946958 100644
--- a/lld/ELF/Writer.cpp
+++ b/lld/ELF/Writer.cpp
@@ -255,9 +255,6 @@
SymbolBody *Body = File.getSymbolBody(SymIndex);
if (!Body)
continue;
- auto *S = dyn_cast<SharedSymbol<ELFT>>(Body);
- if (!S)
- continue;
uint32_t Type = RI.getType(IsMips64EL);
if (Target->relocNeedsPlt(Type)) {
if (Body->isInPlt())
@@ -269,7 +266,9 @@
continue;
GotSec.addEntry(Body);
}
- S->setUsedInDynamicReloc();
+ if (!isa<SharedSymbol<ELFT>>(Body))
+ continue;
+ Body->setUsedInDynamicReloc();
RelaDynSec.addReloc({C, RI});
}
}
@@ -395,11 +394,11 @@
OutputSections.push_back(&DynStrSec);
if (RelaDynSec.hasRelocs())
OutputSections.push_back(&RelaDynSec);
- if (!GotSec.empty())
- OutputSections.push_back(&GotSec);
- if (!PltSec.empty())
- OutputSections.push_back(&PltSec);
}
+ if (!GotSec.empty())
+ OutputSections.push_back(&GotSec);
+ if (!PltSec.empty())
+ OutputSections.push_back(&PltSec);
std::stable_sort(OutputSections.begin(), OutputSections.end(),
compSec<ELFT::Is64Bits>);
diff --git a/lld/test/elf2/relocation.s b/lld/test/elf2/relocation.s
index 5e6b407..5c60fa2 100644
--- a/lld/test/elf2/relocation.s
+++ b/lld/test/elf2/relocation.s
@@ -1,8 +1,23 @@
// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t
// RUN: lld -flavor gnu2 %t -o %t2
+// RUN: llvm-readobj -s %t2 | FileCheck --check-prefix=SEC %s
// RUN: llvm-objdump -s -d %t2 | FileCheck %s
// REQUIRES: x86
+// SEC: Name: .got
+// SEC-NEXT: Type: SHT_PROGBITS
+// SEC-NEXT: Flags [
+// SEC-NEXT: SHF_ALLOC
+// SEC-NEXT: SHF_WRITE
+// SEC-NEXT: ]
+// SEC-NEXT: Address: 0x13000
+// SEC-NEXT: Offset:
+// SEC-NEXT: Size: 8
+// SEC-NEXT: Link: 0
+// SEC-NEXT: Info: 0
+// SEC-NEXT: AddressAlignment: 8
+// SEC-NEXT: EntrySize: 0
+// SEC-NEXT: }
.section .text,"ax",@progbits,unique,1
.global _start
@@ -51,3 +66,13 @@
// CHECK: Contents of section .R_X86_64_64:
// CHECK-NEXT: 12000 00200100 00000000
+
+.section .R_X86_64_GOTPCREL,"a",@progbits
+.global R_X86_64_GOTPCREL
+R_X86_64_GOTPCREL:
+ .long R_X86_64_GOTPCREL@gotpcrel
+
+// 0x13000 - 0x12008 = 4088
+// 4088 = 0xf80f0000 in little endian
+// CHECK: Contents of section .R_X86_64_GOTPCREL
+// CHECK-NEXT: 12008 f80f0000