forked from OSchip/llvm-project
[ELF][MIPS] Move MIPS GOT header generation to the GotSection
MIPS is the only target requires GOT header. We already have MIPS specific code in the `GotSection` class, so move MIPS GOT header generation there and delete redundant stuff like `GotHeaderEntriesNum` field and `writeGotHeader` method. Differential Revision: http://reviews.llvm.org/D19465 llvm-svn: 267460
This commit is contained in:
parent
d60d96ffae
commit
1ef1bf87dc
|
@ -146,7 +146,7 @@ template <class ELFT> void GotSection<ELFT>::addEntry(SymbolBody &Sym) {
|
|||
template <class ELFT> bool GotSection<ELFT>::addDynTlsEntry(SymbolBody &Sym) {
|
||||
if (Sym.hasGlobalDynIndex())
|
||||
return false;
|
||||
Sym.GlobalDynIndex = Target->GotHeaderEntriesNum + Entries.size();
|
||||
Sym.GlobalDynIndex = Entries.size();
|
||||
// Global Dynamic TLS entries take two GOT slots.
|
||||
Entries.push_back(&Sym);
|
||||
Entries.push_back(nullptr);
|
||||
|
@ -175,7 +175,9 @@ GotSection<ELFT>::getMipsLocalPageOffset(uintX_t EntryValue) {
|
|||
template <class ELFT>
|
||||
typename GotSection<ELFT>::uintX_t
|
||||
GotSection<ELFT>::getMipsLocalEntryOffset(uintX_t EntryValue) {
|
||||
size_t NewIndex = Target->GotHeaderEntriesNum + MipsLocalGotPos.size();
|
||||
// Take into account MIPS GOT header.
|
||||
// See comment in the GotSection::writeTo.
|
||||
size_t NewIndex = MipsLocalGotPos.size() + 2;
|
||||
auto P = MipsLocalGotPos.insert(std::make_pair(EntryValue, NewIndex));
|
||||
assert(!P.second || MipsLocalGotPos.size() <= MipsLocalEntries);
|
||||
return P.first->second * sizeof(uintX_t) - MipsGPOffset;
|
||||
|
@ -200,10 +202,14 @@ const SymbolBody *GotSection<ELFT>::getMipsFirstGlobalEntry() const {
|
|||
|
||||
template <class ELFT>
|
||||
unsigned GotSection<ELFT>::getMipsLocalEntriesNum() const {
|
||||
return Target->GotHeaderEntriesNum + MipsLocalEntries;
|
||||
return MipsLocalEntries;
|
||||
}
|
||||
|
||||
template <class ELFT> void GotSection<ELFT>::finalize() {
|
||||
if (Config->EMachine == EM_MIPS)
|
||||
// Take into account MIPS GOT header.
|
||||
// See comment in the GotSection::writeTo.
|
||||
MipsLocalEntries += 2;
|
||||
for (const OutputSectionBase<ELFT> *OutSec : MipsOutSections) {
|
||||
// Calculate an upper bound of MIPS GOT entries required to store page
|
||||
// addresses of local symbols. We assume the worst case - each 64kb
|
||||
|
@ -212,18 +218,32 @@ template <class ELFT> void GotSection<ELFT>::finalize() {
|
|||
// in the GOT entry is calculated as (value + 0x8000) & ~0xffff.
|
||||
MipsLocalEntries += (OutSec->getSize() + 0x8000 + 0xfffe) / 0xffff;
|
||||
}
|
||||
this->Header.sh_size =
|
||||
(Target->GotHeaderEntriesNum + MipsLocalEntries + Entries.size()) *
|
||||
sizeof(uintX_t);
|
||||
this->Header.sh_size = (MipsLocalEntries + Entries.size()) * sizeof(uintX_t);
|
||||
}
|
||||
|
||||
template <class ELFT> void GotSection<ELFT>::writeTo(uint8_t *Buf) {
|
||||
Target->writeGotHeader(Buf);
|
||||
if (Config->EMachine == EM_MIPS) {
|
||||
// Set the MSB of the second GOT slot. This is not required by any
|
||||
// MIPS ABI documentation, though.
|
||||
//
|
||||
// There is a comment in glibc saying that "The MSB of got[1] of a
|
||||
// gnu object is set to identify gnu objects," and in GNU gold it
|
||||
// says "the second entry will be used by some runtime loaders".
|
||||
// But how this field is being used is unclear.
|
||||
//
|
||||
// We are not really willing to mimic other linkers behaviors
|
||||
// without understanding why they do that, but because all files
|
||||
// generated by GNU tools have this special GOT value, and because
|
||||
// we've been doing this for years, it is probably a safe bet to
|
||||
// keep doing this for now. We really need to revisit this to see
|
||||
// if we had to do this.
|
||||
auto *P = reinterpret_cast<typename ELFT::Off *>(Buf);
|
||||
P[1] = uintX_t(1) << (ELFT::Is64Bits ? 63 : 31);
|
||||
}
|
||||
for (std::pair<uintX_t, size_t> &L : MipsLocalGotPos) {
|
||||
uint8_t *Entry = Buf + L.second * sizeof(uintX_t);
|
||||
write<uintX_t, ELFT::TargetEndianness, sizeof(uintX_t)>(Entry, L.first);
|
||||
}
|
||||
Buf += Target->GotHeaderEntriesNum * sizeof(uintX_t);
|
||||
Buf += MipsLocalEntries * sizeof(uintX_t);
|
||||
for (const SymbolBody *B : Entries) {
|
||||
uint8_t *Entry = Buf;
|
||||
|
|
|
@ -179,7 +179,6 @@ public:
|
|||
void writePltZero(uint8_t *Buf) const override;
|
||||
void writePlt(uint8_t *Buf, uint64_t GotEntryAddr, uint64_t PltEntryAddr,
|
||||
int32_t Index, unsigned RelOff) const override;
|
||||
void writeGotHeader(uint8_t *Buf) const override;
|
||||
void writeThunk(uint8_t *Buf, uint64_t S) const override;
|
||||
bool needsThunk(uint32_t Type, const InputFile &File,
|
||||
const SymbolBody &S) const override;
|
||||
|
@ -1294,7 +1293,6 @@ RelExpr AMDGPUTargetInfo::getRelExpr(uint32_t Type, const SymbolBody &S) const {
|
|||
}
|
||||
|
||||
template <class ELFT> MipsTargetInfo<ELFT>::MipsTargetInfo() {
|
||||
GotHeaderEntriesNum = 2;
|
||||
GotPltHeaderEntriesNum = 2;
|
||||
PageSize = 65536;
|
||||
PltEntrySize = 16;
|
||||
|
@ -1352,29 +1350,6 @@ uint32_t MipsTargetInfo<ELFT>::getDynRel(uint32_t Type) const {
|
|||
return R_MIPS_32;
|
||||
}
|
||||
|
||||
template <class ELFT>
|
||||
void MipsTargetInfo<ELFT>::writeGotHeader(uint8_t *Buf) const {
|
||||
typedef typename ELFT::Off Elf_Off;
|
||||
typedef typename ELFT::uint uintX_t;
|
||||
|
||||
// Set the MSB of the second GOT slot. This is not required by any
|
||||
// MIPS ABI documentation, though.
|
||||
//
|
||||
// There is a comment in glibc saying that "The MSB of got[1] of a
|
||||
// gnu object is set to identify gnu objects," and in GNU gold it
|
||||
// says "the second entry will be used by some runtime loaders".
|
||||
// But how this field is being used is unclear.
|
||||
//
|
||||
// We are not really willing to mimic other linkers behaviors
|
||||
// without understanding why they do that, but because all files
|
||||
// generated by GNU tools have this special GOT value, and because
|
||||
// we've been doing this for years, it is probably a safe bet to
|
||||
// keep doing this for now. We really need to revisit this to see
|
||||
// if we had to do this.
|
||||
auto *P = reinterpret_cast<Elf_Off *>(Buf);
|
||||
P[1] = uintX_t(1) << (ELFT::Is64Bits ? 63 : 31);
|
||||
}
|
||||
|
||||
template <class ELFT>
|
||||
void MipsTargetInfo<ELFT>::writeGotPlt(uint8_t *Buf, uint64_t Plt) const {
|
||||
write32<ELFT::TargetEndianness>(Buf, Out<ELFT>::Plt->getVA());
|
||||
|
|
|
@ -29,7 +29,6 @@ public:
|
|||
virtual bool isTlsGlobalDynamicRel(uint32_t Type) const;
|
||||
virtual uint32_t getDynRel(uint32_t Type) const { return Type; }
|
||||
virtual uint32_t getTlsGotRel(uint32_t Type) const { return TlsGotRel; }
|
||||
virtual void writeGotHeader(uint8_t *Buf) const {}
|
||||
virtual void writeGotPltHeader(uint8_t *Buf) const {}
|
||||
virtual void writeGotPlt(uint8_t *Buf, uint64_t Plt) const {};
|
||||
virtual uint64_t getImplicitAddend(const uint8_t *Buf, uint32_t Type) const;
|
||||
|
@ -85,7 +84,6 @@ public:
|
|||
uint32_t TlsOffsetRel;
|
||||
unsigned PltEntrySize = 8;
|
||||
unsigned PltZeroSize = 0;
|
||||
unsigned GotHeaderEntriesNum = 0;
|
||||
unsigned GotPltHeaderEntriesNum = 3;
|
||||
uint32_t ThunkSize = 0;
|
||||
bool UseLazyBinding = false;
|
||||
|
|
Loading…
Reference in New Issue