diff options
author | Simon Atanasyan <simon@atanasyan.com> | 2016-11-17 21:49:14 +0000 |
---|---|---|
committer | Simon Atanasyan <simon@atanasyan.com> | 2016-11-17 21:49:14 +0000 |
commit | b8bfec686f5408b10d111eef3afc77a1b964bab3 (patch) | |
tree | 557e509367fdc1cad569d013df8de3b7c9c6a398 | |
parent | cfadb2293f3b386263ab601af588f2a955a3dc92 (diff) | |
download | llvm-b8bfec686f5408b10d111eef3afc77a1b964bab3.zip llvm-b8bfec686f5408b10d111eef3afc77a1b964bab3.tar.gz llvm-b8bfec686f5408b10d111eef3afc77a1b964bab3.tar.bz2 |
[ELF][MIPS] Remove 'mips' word from MipsGotSection fields and methods names. NFC
Also add new comments with MIPS GOT description.
llvm-svn: 287264
-rw-r--r-- | lld/ELF/InputSection.cpp | 8 | ||||
-rw-r--r-- | lld/ELF/SyntheticSections.cpp | 94 | ||||
-rw-r--r-- | lld/ELF/SyntheticSections.h | 92 |
3 files changed, 118 insertions, 76 deletions
diff --git a/lld/ELF/InputSection.cpp b/lld/ELF/InputSection.cpp index 7cec93d..d48e787 100644 --- a/lld/ELF/InputSection.cpp +++ b/lld/ELF/InputSection.cpp @@ -382,21 +382,21 @@ static typename ELFT::uint getSymVA(uint32_t Type, typename ELFT::uint A, // If relocation against MIPS local symbol requires GOT entry, this entry // should be initialized by 'page address'. This address is high 16-bits // of sum the symbol's value and the addend. - return In<ELFT>::MipsGot->getMipsLocalPageOffset(Body.getVA<ELFT>(A)); + return In<ELFT>::MipsGot->getPageEntryOffset(Body.getVA<ELFT>(A)); case R_MIPS_GOT_OFF: case R_MIPS_GOT_OFF32: // In case of MIPS if a GOT relocation has non-zero addend this addend // should be applied to the GOT entry content not to the GOT entry offset. // That is why we use separate expression type. - return In<ELFT>::MipsGot->getMipsGotOffset(Body, A); + return In<ELFT>::MipsGot->getBodyEntryOffset(Body, A); case R_MIPS_GOTREL: return Body.getVA<ELFT>(A) - In<ELFT>::MipsGot->getVA() - MipsGPOffset; case R_MIPS_TLSGD: return In<ELFT>::MipsGot->getGlobalDynOffset(Body) + - In<ELFT>::MipsGot->getMipsTlsOffset() - MipsGPOffset; + In<ELFT>::MipsGot->getTlsOffset() - MipsGPOffset; case R_MIPS_TLSLD: return In<ELFT>::MipsGot->getTlsIndexOff() + - In<ELFT>::MipsGot->getMipsTlsOffset() - MipsGPOffset; + In<ELFT>::MipsGot->getTlsOffset() - MipsGPOffset; case R_PPC_OPD: { uint64_t SymVA = Body.getVA<ELFT>(A); // If we have an undefined weak symbol, we might get here with a symbol diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp index e6b86f6..413a76e 100644 --- a/lld/ELF/SyntheticSections.cpp +++ b/lld/ELF/SyntheticSections.cpp @@ -443,22 +443,22 @@ void MipsGotSection<ELFT>::addEntry(SymbolBody &Sym, uintX_t Addend, // method calculate number of "pages" required to cover all saved output // section and allocate appropriate number of GOT entries. auto *OutSec = cast<DefinedRegular<ELFT>>(&Sym)->Section->OutSec; - MipsOutSections.insert(OutSec); + OutSections.insert(OutSec); return; } if (Sym.isTls()) { // GOT entries created for MIPS TLS relocations behave like // almost GOT entries from other ABIs. They go to the end // of the global offset table. - Sym.GotIndex = Entries.size(); - Entries.push_back(&Sym); + Sym.GotIndex = TlsEntries.size(); + TlsEntries.push_back(&Sym); return; } - auto AddEntry = [&](SymbolBody &S, uintX_t A, MipsGotEntries &Items) { + auto AddEntry = [&](SymbolBody &S, uintX_t A, GotEntries &Items) { if (S.isInGot() && !A) return; size_t NewIndex = Items.size(); - if (!MipsGotMap.insert({{&S, A}, NewIndex}).second) + if (!EntryIndexMap.insert({{&S, A}, NewIndex}).second) return; Items.emplace_back(&S, A); if (!A) @@ -466,26 +466,26 @@ void MipsGotSection<ELFT>::addEntry(SymbolBody &Sym, uintX_t Addend, }; if (Sym.isPreemptible()) { // Ignore addends for preemptible symbols. They got single GOT entry anyway. - AddEntry(Sym, 0, MipsGlobal); + AddEntry(Sym, 0, GlobalEntries); Sym.IsInGlobalMipsGot = true; } else if (Expr == R_MIPS_GOT_OFF32) { - AddEntry(Sym, Addend, MipsLocal32); + AddEntry(Sym, Addend, LocalEntries32); Sym.Is32BitMipsGot = true; } else { // Hold local GOT entries accessed via a 16-bit index separately. // That allows to write them in the beginning of the GOT and keep // their indexes as less as possible to escape relocation's overflow. - AddEntry(Sym, Addend, MipsLocal); + AddEntry(Sym, Addend, LocalEntries); } } template <class ELFT> bool MipsGotSection<ELFT>::addDynTlsEntry(SymbolBody &Sym) { if (Sym.GlobalDynIndex != -1U) return false; - Sym.GlobalDynIndex = Entries.size(); + Sym.GlobalDynIndex = TlsEntries.size(); // Global Dynamic TLS entries take two GOT slots. - Entries.push_back(nullptr); - Entries.push_back(&Sym); + TlsEntries.push_back(nullptr); + TlsEntries.push_back(&Sym); return true; } @@ -494,54 +494,56 @@ template <class ELFT> bool MipsGotSection<ELFT>::addDynTlsEntry(SymbolBody &Sym) template <class ELFT> bool MipsGotSection<ELFT>::addTlsIndex() { if (TlsIndexOff != uint32_t(-1)) return false; - TlsIndexOff = Entries.size() * sizeof(uintX_t); - Entries.push_back(nullptr); - Entries.push_back(nullptr); + TlsIndexOff = TlsEntries.size() * sizeof(uintX_t); + TlsEntries.push_back(nullptr); + TlsEntries.push_back(nullptr); return true; } template <class ELFT> typename MipsGotSection<ELFT>::uintX_t -MipsGotSection<ELFT>::getMipsLocalPageOffset(uintX_t EntryValue) { +MipsGotSection<ELFT>::getPageEntryOffset(uintX_t EntryValue) { // Initialize the entry by the %hi(EntryValue) expression // but without right-shifting. EntryValue = (EntryValue + 0x8000) & ~0xffff; // Take into account MIPS GOT header. // See comment in the MipsGotSection::writeTo. - size_t NewIndex = MipsLocalGotPos.size() + 2; - auto P = MipsLocalGotPos.insert(std::make_pair(EntryValue, NewIndex)); - assert(!P.second || MipsLocalGotPos.size() <= MipsPageEntries); + size_t NewIndex = PageIndexMap.size() + 2; + auto P = PageIndexMap.insert(std::make_pair(EntryValue, NewIndex)); + assert(!P.second || PageIndexMap.size() <= PageEntriesNum); return (uintX_t)P.first->second * sizeof(uintX_t) - MipsGPOffset; } template <class ELFT> typename MipsGotSection<ELFT>::uintX_t -MipsGotSection<ELFT>::getMipsGotOffset(const SymbolBody &B, uintX_t Addend) const { +MipsGotSection<ELFT>::getBodyEntryOffset(const SymbolBody &B, + uintX_t Addend) const { // Calculate offset of the GOT entries block: TLS, global, local. uintX_t GotBlockOff; if (B.isTls()) - GotBlockOff = getMipsTlsOffset(); + GotBlockOff = getTlsOffset(); else if (B.IsInGlobalMipsGot) - GotBlockOff = getMipsLocalEntriesNum() * sizeof(uintX_t); + GotBlockOff = getLocalEntriesNum() * sizeof(uintX_t); else if (B.Is32BitMipsGot) - GotBlockOff = (MipsPageEntries + MipsLocal.size()) * sizeof(uintX_t); + GotBlockOff = (PageEntriesNum + LocalEntries.size()) * sizeof(uintX_t); else - GotBlockOff = MipsPageEntries * sizeof(uintX_t); + GotBlockOff = PageEntriesNum * sizeof(uintX_t); // Calculate index of the GOT entry in the block. uintX_t GotIndex; if (B.isInGot()) GotIndex = B.GotIndex; else { - auto It = MipsGotMap.find({&B, Addend}); - assert(It != MipsGotMap.end()); + auto It = EntryIndexMap.find({&B, Addend}); + assert(It != EntryIndexMap.end()); GotIndex = It->second; } return GotBlockOff + GotIndex * sizeof(uintX_t) - MipsGPOffset; } template <class ELFT> -typename MipsGotSection<ELFT>::uintX_t MipsGotSection<ELFT>::getMipsTlsOffset() const { - return (getMipsLocalEntriesNum() + MipsGlobal.size()) * sizeof(uintX_t); +typename MipsGotSection<ELFT>::uintX_t +MipsGotSection<ELFT>::getTlsOffset() const { + return (getLocalEntriesNum() + GlobalEntries.size()) * sizeof(uintX_t); } template <class ELFT> @@ -551,29 +553,29 @@ MipsGotSection<ELFT>::getGlobalDynOffset(const SymbolBody &B) const { } template <class ELFT> -const SymbolBody *MipsGotSection<ELFT>::getMipsFirstGlobalEntry() const { - return MipsGlobal.empty() ? nullptr : MipsGlobal.front().first; +const SymbolBody *MipsGotSection<ELFT>::getFirstGlobalEntry() const { + return GlobalEntries.empty() ? nullptr : GlobalEntries.front().first; } template <class ELFT> -unsigned MipsGotSection<ELFT>::getMipsLocalEntriesNum() const { - return MipsPageEntries + MipsLocal.size() + MipsLocal32.size(); +unsigned MipsGotSection<ELFT>::getLocalEntriesNum() const { + return PageEntriesNum + LocalEntries.size() + LocalEntries32.size(); } template <class ELFT> void MipsGotSection<ELFT>::finalize() { - size_t EntriesNum = Entries.size(); + size_t EntriesNum = TlsEntries.size(); // Take into account MIPS GOT header. // See comment in the MipsGotSection::writeTo. - MipsPageEntries += 2; - for (const OutputSectionBase *OutSec : MipsOutSections) { + PageEntriesNum += 2; + for (const OutputSectionBase *OutSec : OutSections) { // Calculate an upper bound of MIPS GOT entries required to store page // addresses of local symbols. We assume the worst case - each 64kb // page of the output section has at least one GOT relocation against it. // Add 0x8000 to the section's size because the page address stored // in the GOT entry is calculated as (value + 0x8000) & ~0xffff. - MipsPageEntries += (OutSec->Size + 0x8000 + 0xfffe) / 0xffff; + PageEntriesNum += (OutSec->Size + 0x8000 + 0xfffe) / 0xffff; } - EntriesNum += getMipsLocalEntriesNum() + MipsGlobal.size(); + EntriesNum += getLocalEntriesNum() + GlobalEntries.size(); Size = EntriesNum * sizeof(uintX_t); } @@ -601,21 +603,21 @@ template <class ELFT> void MipsGotSection<ELFT>::writeTo(uint8_t *Buf) { auto *P = reinterpret_cast<typename ELFT::Off *>(Buf); P[1] = uintX_t(1) << (ELFT::Is64Bits ? 63 : 31); // Write 'page address' entries to the local part of the GOT. - for (std::pair<uintX_t, size_t> &L : MipsLocalGotPos) { + for (std::pair<uintX_t, size_t> &L : PageIndexMap) { uint8_t *Entry = Buf + L.second * sizeof(uintX_t); writeUint<ELFT>(Entry, L.first); } - Buf += MipsPageEntries * sizeof(uintX_t); - auto AddEntry = [&](const MipsGotEntry &SA) { + Buf += PageEntriesNum * sizeof(uintX_t); + auto AddEntry = [&](const GotEntry &SA) { uint8_t *Entry = Buf; Buf += sizeof(uintX_t); const SymbolBody *Body = SA.first; uintX_t VA = Body->template getVA<ELFT>(SA.second); writeUint<ELFT>(Entry, VA); }; - std::for_each(std::begin(MipsLocal), std::end(MipsLocal), AddEntry); - std::for_each(std::begin(MipsLocal32), std::end(MipsLocal32), AddEntry); - std::for_each(std::begin(MipsGlobal), std::end(MipsGlobal), AddEntry); + std::for_each(std::begin(LocalEntries), std::end(LocalEntries), AddEntry); + std::for_each(std::begin(LocalEntries32), std::end(LocalEntries32), AddEntry); + std::for_each(std::begin(GlobalEntries), std::end(GlobalEntries), AddEntry); // Initialize TLS-related GOT entries. If the entry has a corresponding // dynamic relocations, leave it initialized by zero. Write down adjusted // TLS symbol's values otherwise. To calculate the adjustments use offsets @@ -623,7 +625,7 @@ template <class ELFT> void MipsGotSection<ELFT>::writeTo(uint8_t *Buf) { // https://www.linux-mips.org/wiki/NPTL if (TlsIndexOff != -1U && !Config->Pic) writeUint<ELFT>(Buf + TlsIndexOff, 1); - for (const SymbolBody *B : Entries) { + for (const SymbolBody *B : TlsEntries) { if (!B || B->isPreemptible()) continue; uintX_t VA = B->getVA<ELFT>(); @@ -832,8 +834,8 @@ template <class ELFT> void DynamicSection<ELFT>::finalize() { add({DT_MIPS_FLAGS, RHF_NOTPOT}); add({DT_MIPS_BASE_ADDRESS, Config->ImageBase}); add({DT_MIPS_SYMTABNO, In<ELFT>::DynSymTab->getNumSymbols()}); - add({DT_MIPS_LOCAL_GOTNO, In<ELFT>::MipsGot->getMipsLocalEntriesNum()}); - if (const SymbolBody *B = In<ELFT>::MipsGot->getMipsFirstGlobalEntry()) + add({DT_MIPS_LOCAL_GOTNO, In<ELFT>::MipsGot->getLocalEntriesNum()}); + if (const SymbolBody *B = In<ELFT>::MipsGot->getFirstGlobalEntry()) add({DT_MIPS_GOTSYM, B->DynsymIndex}); else add({DT_MIPS_GOTSYM, In<ELFT>::DynSymTab->getNumSymbols()}); @@ -933,7 +935,7 @@ template <class ELFT> void RelocationSection<ELFT>::writeTo(uint8_t *Buf) { // Dynamic relocation against MIPS GOT section make deal TLS entries // allocated in the end of the GOT. We need to adjust the offset to take // in account 'local' and 'global' GOT entries. - P->r_offset += In<ELFT>::MipsGot->getMipsTlsOffset(); + P->r_offset += In<ELFT>::MipsGot->getTlsOffset(); P->setSymbolAndType(Rel.getSymIndex(), Rel.Type, Config->Mips64EL); } diff --git a/lld/ELF/SyntheticSections.h b/lld/ELF/SyntheticSections.h index 1841005..1fcb41c 100644 --- a/lld/ELF/SyntheticSections.h +++ b/lld/ELF/SyntheticSections.h @@ -178,49 +178,89 @@ public: void addEntry(SymbolBody &Sym, uintX_t Addend, RelExpr Expr); bool addDynTlsEntry(SymbolBody &Sym); bool addTlsIndex(); - bool empty() const { return MipsPageEntries == 0 && Entries.empty(); } - uintX_t getMipsLocalPageOffset(uintX_t Addr); - uintX_t getMipsGotOffset(const SymbolBody &B, uintX_t Addend) const; + bool empty() const { return PageEntriesNum == 0 && TlsEntries.empty(); } + uintX_t getPageEntryOffset(uintX_t Addr); + uintX_t getBodyEntryOffset(const SymbolBody &B, uintX_t Addend) const; uintX_t getGlobalDynOffset(const SymbolBody &B) const; // Returns the symbol which corresponds to the first entry of the global part // of GOT on MIPS platform. It is required to fill up MIPS-specific dynamic // table properties. // Returns nullptr if the global part is empty. - const SymbolBody *getMipsFirstGlobalEntry() const; + const SymbolBody *getFirstGlobalEntry() const; // Returns the number of entries in the local part of GOT including - // the number of reserved entries. This method is MIPS-specific. - unsigned getMipsLocalEntriesNum() const; + // the number of reserved entries. + unsigned getLocalEntriesNum() const; // Returns offset of TLS part of the MIPS GOT table. This part goes // after 'local' and 'global' entries. - uintX_t getMipsTlsOffset() const; + uintX_t getTlsOffset() const; uint32_t getTlsIndexOff() const { return TlsIndexOff; } private: - std::vector<const SymbolBody *> Entries; + // MIPS GOT consists of three parts: local, global and tls. Each part + // contains different types of entries. Here is a layout of GOT: + // - Header entries | + // - Page entries | Local part + // - Local entries (16-bit access) | + // - Local entries (32-bit access) | + // - Normal global entries || Global part + // - Reloc-only global entries || + // - TLS entries ||| TLS part + // + // Header: + // Two entries hold predefined value 0x0 and 0x80000000. + // Page entries: + // These entries created by R_MIPS_GOT_PAGE relocation and R_MIPS_GOT16 + // relocation against local symbols. They are initialized by higher 16-bit + // of the corresponding symbol's value. So each 64kb of address space + // requires a single GOT entry. + // Local entries (16-bit access): + // These entries created by GOT relocations against global non-preemptible + // symbols so dynamic linker is not necessary to resolve the symbol's + // values. "16-bit access" means that corresponding relocations address + // GOT using 16-bit index. Each unique Symbol-Addend pair has its own + // GOT entry. + // Local entries (32-bit access): + // These entries are the same as above but created by relocations which + // address GOT using 32-bit index (R_MIPS_GOT_HI16/LO16 etc). + // Normal global entries: + // These entries created by GOT relocations against preemptible global + // symbols. They need to be initialized by dynamic linker and they ordered + // exactly as the corresponding entries in the dynamic symbols table. + // Reloc-only global entries: + // These entries created for symbols that are referenced by dynamic + // relocations R_MIPS_REL32. These entries are not accessed with gp-relative + // addressing, but MIPS ABI requires that these entries be present in GOT. + // TLS entries: + // Entries created by TLS relocations. + + // Total number of allocated "Header" and "Page" entries. + uint32_t PageEntriesNum = 0; + // Output sections referenced by MIPS GOT relocations. + llvm::SmallPtrSet<const OutputSectionBase *, 10> OutSections; + // Map from "page" address to the GOT index. + llvm::DenseMap<uintX_t, size_t> PageIndexMap; + + typedef std::pair<const SymbolBody *, uintX_t> GotEntry; + typedef std::vector<GotEntry> GotEntries; + // Map from Symbol-Addend pair to the GOT index. + llvm::DenseMap<GotEntry, size_t> EntryIndexMap; + // Local entries (16-bit access). + GotEntries LocalEntries; + // Local entries (32-bit access). + GotEntries LocalEntries32; + + // Normal and reloc-only global entries. + GotEntries GlobalEntries; + + // TLS entries. + std::vector<const SymbolBody *> TlsEntries; + uint32_t TlsIndexOff = -1; - uint32_t MipsPageEntries = 0; uintX_t Size = 0; - // Output sections referenced by MIPS GOT relocations. - llvm::SmallPtrSet<const OutputSectionBase *, 10> MipsOutSections; - llvm::DenseMap<uintX_t, size_t> MipsLocalGotPos; - - // MIPS ABI requires to create unique GOT entry for each Symbol/Addend - // pairs. The `MipsGotMap` maps (S,A) pair to the GOT index in the `MipsLocal` - // or `MipsGlobal` vectors. In general it does not have a sence to take in - // account addend for preemptible symbols because the corresponding - // GOT entries should have one-to-one mapping with dynamic symbols table. - // But we use the same container's types for both kind of GOT entries - // to handle them uniformly. - typedef std::pair<const SymbolBody *, uintX_t> MipsGotEntry; - typedef std::vector<MipsGotEntry> MipsGotEntries; - llvm::DenseMap<MipsGotEntry, size_t> MipsGotMap; - MipsGotEntries MipsLocal; - MipsGotEntries MipsLocal32; - MipsGotEntries MipsGlobal; }; template <class ELFT> |