Create simpler dynamic relocations for local symbols in got.

If the symbol is not preemptable, we can use a R_X86_64_RELATIVE.

llvm-svn: 249496
This commit is contained in:
Rafael Espindola 2015-10-07 00:58:20 +00:00
parent 187276fa94
commit 52dca345db
2 changed files with 59 additions and 26 deletions

View File

@ -104,12 +104,6 @@ RelocationSection<ELFT>::RelocationSection(SymbolTableSection<ELFT> &DynSymSec,
this->Header.sh_addralign = ELFT::Is64Bits ? 8 : 4;
}
static bool isLocalDefinition(const SymbolBody *Body) {
if (!Body)
return true;
return !Body->isShared() && !Body->isUndefined();
}
template <class ELFT> void RelocationSection<ELFT>::writeTo(uint8_t *Buf) {
const unsigned EntrySize = IsRela ? sizeof(Elf_Rela) : sizeof(Elf_Rel);
bool IsMips64EL = Relocs[0].C.getFile()->getObj().isMips64EL();
@ -126,32 +120,36 @@ template <class ELFT> void RelocationSection<ELFT>::writeTo(uint8_t *Buf) {
const ELFFile<ELFT> &Obj = File.getObj();
uint32_t Type = RI.getType(IsMips64EL);
bool CanBePreempted = canBePreempted(Body);
uintX_t Addend = 0;
if (!CanBePreempted) {
if (IsRela) {
if (Body)
Addend += getSymVA(cast<ELFSymbolBody<ELFT>>(*Body), BssSec);
else
Addend += getLocalSymVA(
Obj.getRelocationSymbol(&RI, File.getSymbolTable()), File);
}
P->setSymbolAndType(0, Target->getRelativeReloc(), IsMips64EL);
}
if (Body && Target->relocNeedsGot(Type, *Body)) {
P->r_offset = GotSec.getEntryAddr(*Body);
P->setSymbolAndType(Body->getDynamicSymbolTableIndex(),
Target->getGotReloc(), IsMips64EL);
if (CanBePreempted)
P->setSymbolAndType(Body->getDynamicSymbolTableIndex(),
Target->getGotReloc(), IsMips64EL);
} else {
P->r_offset = RI.r_offset + C.getOutputSectionOff() + Out->getVA();
uintX_t Addend = 0;
if (IsRela)
Addend = static_cast<const Elf_Rela &>(RI).r_addend;
if (!isLocalDefinition(Body)) {
Addend += static_cast<const Elf_Rela &>(RI).r_addend;
P->r_offset = RI.r_offset + C.getOutputSectionOff() + Out->getVA();
if (CanBePreempted)
P->setSymbolAndType(Body->getDynamicSymbolTableIndex(), Type,
IsMips64EL);
} else {
P->setSymbolAndType(0, Target->getRelativeReloc(), IsMips64EL);
if (IsRela) {
if (Body)
Addend += getSymVA(cast<ELFSymbolBody<ELFT>>(*Body), BssSec);
else
Addend += getLocalSymVA(
Obj.getRelocationSymbol(&RI, File.getSymbolTable()), File);
}
}
if (IsRela)
static_cast<Elf_Rela *>(P)->r_addend = Addend;
}
if (IsRela)
static_cast<Elf_Rela *>(P)->r_addend = Addend;
}
}
@ -418,7 +416,7 @@ bool lld::elf2::canBePreempted(const SymbolBody *Body) {
return true;
if (!Config->Shared)
return false;
return true;
return Body->getMostConstrainingVisibility() == STV_DEFAULT;
}
template <class ELFT> void OutputSection<ELFT>::writeTo(uint8_t *Buf) {

View File

@ -0,0 +1,35 @@
// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o
// RUN: ld.lld2 %t.o -o %t -shared
// RUN: llvm-readobj -s -r %t | FileCheck %s
// RUN: llvm-objdump -d %t | FileCheck --check-prefix=DISASM %s
bar:
call foo@gotpcrel
.hidden foo
.global foo
foo:
nop
// 0x3090 - 0x2000 - 5 = 4235
// DISASM: bar:
// DISASM-NEXT: 2000: {{.*}} callq 4235
// DISASM: foo:
// DISASM-NEXT: 2005: {{.*}} nop
// CHECK: Name: .got
// CHECK-NEXT: Type: SHT_PROGBITS
// CHECK-NEXT: Flags [
// CHECK-NEXT: SHF_ALLOC
// CHECK-NEXT: SHF_WRITE
// CHECK-NEXT: ]
// CHECK-NEXT: Address: 0x3090
// CHECK-NEXT: Offset:
// CHECK-NEXT: Size: 8
// CHECK: Relocations [
// CHECK-NEXT: Section ({{.*}}) .rela.dyn {
// CHECK-NEXT: 0x3090 R_X86_64_RELATIVE - 0x2005
// CHECK-NEXT: }
// CHECK-NEXT: ]