Add support for relocating R_X86_64_GOTPCREL.

llvm-svn: 248425
This commit is contained in:
Rafael Espindola 2015-09-23 20:08:25 +00:00
parent 5c3f9d516d
commit cdfecffd80
4 changed files with 42 additions and 14 deletions

View File

@ -50,6 +50,7 @@ void InputSection<ELFT>::relocate(
const SymbolBody *Body = File.getSymbolBody(SymIndex); const SymbolBody *Body = File.getSymbolBody(SymIndex);
if (!Body) if (!Body)
continue; continue;
uint32_t OrigType = Type;
switch (Body->kind()) { switch (Body->kind()) {
case SymbolBody::DefinedRegularKind: case SymbolBody::DefinedRegularKind:
SymVA = getSymVA<ELFT>(cast<DefinedRegular<ELFT>>(Body)); SymVA = getSymVA<ELFT>(cast<DefinedRegular<ELFT>>(Body));
@ -63,15 +64,12 @@ void InputSection<ELFT>::relocate(
break; break;
} }
case SymbolBody::SharedKind: case SymbolBody::SharedKind:
if (Target->relocNeedsPlt(Type)) { if (Target->relocNeedsPlt(Type))
SymVA = PltSec.getEntryAddr(*Body);
Type = Target->getPCRelReloc(); Type = Target->getPCRelReloc();
} else if (Target->relocNeedsGot(Type)) { else if (Target->relocNeedsGot(Type))
SymVA = GotSec.getEntryAddr(*Body);
Type = Target->getPCRelReloc(); Type = Target->getPCRelReloc();
} else { else
continue; continue;
}
break; break;
case SymbolBody::UndefinedKind: case SymbolBody::UndefinedKind:
assert(Body->isWeak() && "Undefined symbol reached writer"); assert(Body->isWeak() && "Undefined symbol reached writer");
@ -80,6 +78,11 @@ void InputSection<ELFT>::relocate(
case SymbolBody::LazyKind: case SymbolBody::LazyKind:
llvm_unreachable("Lazy symbol reached writer"); 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, Target->relocateOne(Buf, reinterpret_cast<const void *>(&RI), Type,

View File

@ -137,6 +137,7 @@ void X86_64TargetInfo::relocateOne(uint8_t *Buf, const void *RelP,
uint8_t *Location = Buf + Offset; uint8_t *Location = Buf + Offset;
switch (Type) { switch (Type) {
case R_X86_64_PC32: case R_X86_64_PC32:
case R_X86_64_GOTPCREL:
support::endian::write32le(Location, support::endian::write32le(Location,
SymVA + Rel.r_addend - (BaseAddr + Offset)); SymVA + Rel.r_addend - (BaseAddr + Offset));
break; break;

View File

@ -255,9 +255,6 @@ void Writer<ELFT>::scanRelocs(
SymbolBody *Body = File.getSymbolBody(SymIndex); SymbolBody *Body = File.getSymbolBody(SymIndex);
if (!Body) if (!Body)
continue; continue;
auto *S = dyn_cast<SharedSymbol<ELFT>>(Body);
if (!S)
continue;
uint32_t Type = RI.getType(IsMips64EL); uint32_t Type = RI.getType(IsMips64EL);
if (Target->relocNeedsPlt(Type)) { if (Target->relocNeedsPlt(Type)) {
if (Body->isInPlt()) if (Body->isInPlt())
@ -269,7 +266,9 @@ void Writer<ELFT>::scanRelocs(
continue; continue;
GotSec.addEntry(Body); GotSec.addEntry(Body);
} }
S->setUsedInDynamicReloc(); if (!isa<SharedSymbol<ELFT>>(Body))
continue;
Body->setUsedInDynamicReloc();
RelaDynSec.addReloc({C, RI}); RelaDynSec.addReloc({C, RI});
} }
} }
@ -395,11 +394,11 @@ template <class ELFT> void Writer<ELFT>::createSections() {
OutputSections.push_back(&DynStrSec); OutputSections.push_back(&DynStrSec);
if (RelaDynSec.hasRelocs()) if (RelaDynSec.hasRelocs())
OutputSections.push_back(&RelaDynSec); 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(), std::stable_sort(OutputSections.begin(), OutputSections.end(),
compSec<ELFT::Is64Bits>); compSec<ELFT::Is64Bits>);

View File

@ -1,8 +1,23 @@
// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t // RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t
// RUN: lld -flavor gnu2 %t -o %t2 // 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 // RUN: llvm-objdump -s -d %t2 | FileCheck %s
// REQUIRES: x86 // 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 .section .text,"ax",@progbits,unique,1
.global _start .global _start
@ -51,3 +66,13 @@ R_X86_64_64:
// CHECK: Contents of section .R_X86_64_64: // CHECK: Contents of section .R_X86_64_64:
// CHECK-NEXT: 12000 00200100 00000000 // 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