summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRafael Espindola <rafael.espindola@gmail.com>2015-10-07 00:58:20 +0000
committerRafael Espindola <rafael.espindola@gmail.com>2015-10-07 00:58:20 +0000
commit52dca345db0ded0d934a312b6a103a08c8ffc997 (patch)
treeddac0faa93eac76427b59267d39463d5fd0b4eb1
parent187276fa946d322e31bda38a4b958ad9b0f475c6 (diff)
downloadbcm5719-llvm-52dca345db0ded0d934a312b6a103a08c8ffc997.tar.gz
bcm5719-llvm-52dca345db0ded0d934a312b6a103a08c8ffc997.zip
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
-rw-r--r--lld/ELF/OutputSections.cpp50
-rw-r--r--lld/test/elf2/local-got-shared.s35
2 files changed, 59 insertions, 26 deletions
diff --git a/lld/ELF/OutputSections.cpp b/lld/ELF/OutputSections.cpp
index 2056d1966b9..1bc6e6bd99d 100644
--- a/lld/ELF/OutputSections.cpp
+++ b/lld/ELF/OutputSections.cpp
@@ -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) {
diff --git a/lld/test/elf2/local-got-shared.s b/lld/test/elf2/local-got-shared.s
new file mode 100644
index 00000000000..c3e3791b038
--- /dev/null
+++ b/lld/test/elf2/local-got-shared.s
@@ -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: ]
OpenPOWER on IntegriCloud