diff options
author | Rafael Espindola <rafael.espindola@gmail.com> | 2015-10-07 00:58:20 +0000 |
---|---|---|
committer | Rafael Espindola <rafael.espindola@gmail.com> | 2015-10-07 00:58:20 +0000 |
commit | 52dca345db0ded0d934a312b6a103a08c8ffc997 (patch) | |
tree | ddac0faa93eac76427b59267d39463d5fd0b4eb1 | |
parent | 187276fa946d322e31bda38a4b958ad9b0f475c6 (diff) | |
download | bcm5719-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.cpp | 50 | ||||
-rw-r--r-- | lld/test/elf2/local-got-shared.s | 35 |
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: ] |