forked from OSchip/llvm-project
Don't create dynamic relocations when its known what the got points to.
llvm-svn: 249485
This commit is contained in:
parent
dcfba33481
commit
a662738e02
|
@ -14,6 +14,7 @@
|
|||
|
||||
using namespace llvm;
|
||||
using namespace llvm::object;
|
||||
using namespace llvm::support::endian;
|
||||
using namespace llvm::ELF;
|
||||
|
||||
using namespace lld;
|
||||
|
@ -29,10 +30,11 @@ OutputSectionBase<Is64Bits>::OutputSectionBase(StringRef Name, uint32_t sh_type,
|
|||
}
|
||||
|
||||
template <class ELFT>
|
||||
GotSection<ELFT>::GotSection()
|
||||
GotSection<ELFT>::GotSection(const OutputSection<ELFT> &BssSec)
|
||||
: OutputSectionBase<ELFT::Is64Bits>(".got", llvm::ELF::SHT_PROGBITS,
|
||||
llvm::ELF::SHF_ALLOC |
|
||||
llvm::ELF::SHF_WRITE) {
|
||||
llvm::ELF::SHF_WRITE),
|
||||
BssSec(BssSec) {
|
||||
this->Header.sh_addralign = this->getAddrSize();
|
||||
}
|
||||
|
||||
|
@ -47,6 +49,16 @@ GotSection<ELFT>::getEntryAddr(const SymbolBody &B) const {
|
|||
return this->getVA() + B.getGotIndex() * this->getAddrSize();
|
||||
}
|
||||
|
||||
template <class ELFT> void GotSection<ELFT>::writeTo(uint8_t *Buf) {
|
||||
for (const SymbolBody *B : Entries) {
|
||||
if (canBePreempted(B))
|
||||
continue; // The dynamic linker will take care of it.
|
||||
uintX_t VA = getSymVA(*B, BssSec);
|
||||
write<uintX_t, ELFT::TargetEndianness, sizeof(uintX_t)>(Buf, VA);
|
||||
Buf += sizeof(uintX_t);
|
||||
}
|
||||
}
|
||||
|
||||
template <class ELFT>
|
||||
PltSection<ELFT>::PltSection(const GotSection<ELFT> &GotSec)
|
||||
: OutputSectionBase<ELFT::Is64Bits>(".plt", llvm::ELF::SHT_PROGBITS,
|
||||
|
@ -399,6 +411,16 @@ lld::elf2::getLocalSymVA(const typename ELFFile<ELFT>::Elf_Sym *Sym,
|
|||
return Out->getVA() + Section->getOutputSectionOff() + Sym->st_value;
|
||||
}
|
||||
|
||||
bool lld::elf2::canBePreempted(const SymbolBody *Body) {
|
||||
if (!Body)
|
||||
return false;
|
||||
if (Body->isShared() || Body->isUndefined())
|
||||
return true;
|
||||
if (!Config->Shared)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class ELFT> void OutputSection<ELFT>::writeTo(uint8_t *Buf) {
|
||||
for (InputSection<ELFT> *C : Sections)
|
||||
C->writeTo(Buf, BssSec, PltSec, GotSec);
|
||||
|
|
|
@ -40,7 +40,7 @@ template <class ELFT>
|
|||
typename llvm::object::ELFFile<ELFT>::uintX_t
|
||||
getLocalSymVA(const typename llvm::object::ELFFile<ELFT>::Elf_Sym *Sym,
|
||||
const ObjectFile<ELFT> &File);
|
||||
|
||||
bool canBePreempted(const SymbolBody *Body);
|
||||
template <class ELFT> bool includeInSymtab(const SymbolBody &B);
|
||||
|
||||
bool includeInDynamicSymtab(const SymbolBody &B);
|
||||
|
@ -103,17 +103,18 @@ class GotSection final : public OutputSectionBase<ELFT::Is64Bits> {
|
|||
typedef typename Base::uintX_t uintX_t;
|
||||
|
||||
public:
|
||||
GotSection();
|
||||
GotSection(const OutputSection<ELFT> &BssSec);
|
||||
void finalize() override {
|
||||
this->Header.sh_size = Entries.size() * this->getAddrSize();
|
||||
}
|
||||
void writeTo(uint8_t *Buf) override {}
|
||||
void writeTo(uint8_t *Buf) override;
|
||||
void addEntry(SymbolBody *Sym);
|
||||
bool empty() const { return Entries.empty(); }
|
||||
uintX_t getEntryAddr(const SymbolBody &B) const;
|
||||
|
||||
private:
|
||||
std::vector<const SymbolBody *> Entries;
|
||||
const OutputSection<ELFT> &BssSec;
|
||||
};
|
||||
|
||||
template <class ELFT>
|
||||
|
|
|
@ -85,7 +85,7 @@ public:
|
|||
Writer(SymbolTable *T)
|
||||
: SymTabSec(*T, StrTabSec, BssSec), DynSymSec(*T, DynStrSec, BssSec),
|
||||
RelaDynSec(DynSymSec, GotSec, BssSec, T->shouldUseRela()),
|
||||
PltSec(GotSec), HashSec(DynSymSec),
|
||||
GotSec(BssSec), PltSec(GotSec), HashSec(DynSymSec),
|
||||
DynamicSec(*T, HashSec, RelaDynSec, BssSec),
|
||||
BssSec(PltSec, GotSec, BssSec, ".bss", SHT_NOBITS,
|
||||
SHF_ALLOC | SHF_WRITE) {}
|
||||
|
@ -230,18 +230,14 @@ void Writer<ELFT>::scanRelocs(
|
|||
if (Body->isInGot())
|
||||
continue;
|
||||
GotSec.addEntry(Body);
|
||||
Body->setUsedInDynamicReloc();
|
||||
RelaDynSec.addReloc({C, RI});
|
||||
continue;
|
||||
}
|
||||
if (Body->isShared()) {
|
||||
Body->setUsedInDynamicReloc();
|
||||
RelaDynSec.addReloc({C, RI});
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (Config->Shared && !Target->isRelRelative(Type))
|
||||
if (canBePreempted(Body)) {
|
||||
Body->setUsedInDynamicReloc();
|
||||
RelaDynSec.addReloc({C, RI});
|
||||
} else if (Config->Shared && !Target->isRelRelative(Type)) {
|
||||
RelaDynSec.addReloc({C, RI});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,40 @@
|
|||
// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o
|
||||
// RUN: lld -flavor gnu2 %t.o -o %t
|
||||
// RUN: llvm-readobj -s -r -section-data %t | FileCheck %s
|
||||
// RUN: llvm-objdump -d %t | FileCheck --check-prefix=DISASM %s
|
||||
|
||||
.globl _start
|
||||
_start:
|
||||
call foo@gotpcrel
|
||||
|
||||
.global foo
|
||||
foo:
|
||||
nop
|
||||
|
||||
// 0x12000 - 0x11000 - 5 = 4091
|
||||
// DISASM: _start:
|
||||
// DISASM-NEXT: 11000: {{.*}} callq 4091
|
||||
|
||||
// DISASM: foo:
|
||||
// DISASM-NEXT: 11005: {{.*}} 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: 0x12000
|
||||
// CHECK-NEXT: Offset:
|
||||
// CHECK-NEXT: Size: 8
|
||||
// CHECK-NEXT: Link: 0
|
||||
// CHECK-NEXT: Info: 0
|
||||
// CHECK-NEXT: AddressAlignment: 8
|
||||
// CHECK-NEXT: EntrySize: 0
|
||||
// CHECK-NEXT: SectionData (
|
||||
// 0x11005 in little endian
|
||||
// CHECK-NEXT: 0000: 05100100 00000000 |........|
|
||||
// CHECK-NEXT: )
|
||||
|
||||
// CHECK: Relocations [
|
||||
// CHECK-NEXT: ]
|
Loading…
Reference in New Issue