diff options
Diffstat (limited to 'ELF/OutputSections.cpp')
-rw-r--r-- | ELF/OutputSections.cpp | 174 |
1 files changed, 100 insertions, 74 deletions
diff --git a/ELF/OutputSections.cpp b/ELF/OutputSections.cpp index 30ec83f4d3b1f..2aa814524d6be 100644 --- a/ELF/OutputSections.cpp +++ b/ELF/OutputSections.cpp @@ -21,21 +21,20 @@ using namespace llvm::ELF; using namespace lld; using namespace lld::elf2; -bool lld::elf2::HasGotOffRel = false; +bool elf2::HasGotOffRel = false; template <class ELFT> -OutputSectionBase<ELFT>::OutputSectionBase(StringRef Name, uint32_t sh_type, - uintX_t sh_flags) +OutputSectionBase<ELFT>::OutputSectionBase(StringRef Name, uint32_t Type, + uintX_t Flags) : Name(Name) { memset(&Header, 0, sizeof(Elf_Shdr)); - Header.sh_type = sh_type; - Header.sh_flags = sh_flags; + Header.sh_type = Type; + Header.sh_flags = Flags; } template <class ELFT> GotPltSection<ELFT>::GotPltSection() - : OutputSectionBase<ELFT>(".got.plt", llvm::ELF::SHT_PROGBITS, - llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_WRITE) { + : OutputSectionBase<ELFT>(".got.plt", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE) { this->Header.sh_addralign = sizeof(uintX_t); } @@ -70,10 +69,9 @@ template <class ELFT> void GotPltSection<ELFT>::writeTo(uint8_t *Buf) { template <class ELFT> GotSection<ELFT>::GotSection() - : OutputSectionBase<ELFT>(".got", llvm::ELF::SHT_PROGBITS, - llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_WRITE) { + : OutputSectionBase<ELFT>(".got", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE) { if (Config->EMachine == EM_MIPS) - this->Header.sh_flags |= llvm::ELF::SHF_MIPS_GPREL; + this->Header.sh_flags |= SHF_MIPS_GPREL; this->Header.sh_addralign = sizeof(uintX_t); } @@ -120,7 +118,7 @@ const SymbolBody *GotSection<ELFT>::getMipsFirstGlobalEntry() const { template <class ELFT> unsigned GotSection<ELFT>::getMipsLocalEntriesNum() const { - // TODO: Update when the suppoort of GOT entries for local symbols is added. + // TODO: Update when the support of GOT entries for local symbols is added. return Target->getGotHeaderEntriesNum(); } @@ -151,8 +149,7 @@ template <class ELFT> void GotSection<ELFT>::writeTo(uint8_t *Buf) { template <class ELFT> PltSection<ELFT>::PltSection() - : OutputSectionBase<ELFT>(".plt", llvm::ELF::SHT_PROGBITS, - llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_EXECINSTR) { + : OutputSectionBase<ELFT>(".plt", SHT_PROGBITS, SHF_ALLOC | SHF_EXECINSTR) { this->Header.sh_addralign = 16; } @@ -199,9 +196,7 @@ template <class ELFT> void PltSection<ELFT>::finalize() { template <class ELFT> RelocationSection<ELFT>::RelocationSection(StringRef Name, bool IsRela) - : OutputSectionBase<ELFT>(Name, - IsRela ? llvm::ELF::SHT_RELA : llvm::ELF::SHT_REL, - llvm::ELF::SHF_ALLOC), + : OutputSectionBase<ELFT>(Name, IsRela ? SHT_RELA : SHT_REL, SHF_ALLOC), IsRela(IsRela) { this->Header.sh_entsize = IsRela ? sizeof(Elf_Rela) : sizeof(Elf_Rel); this->Header.sh_addralign = ELFT::Is64Bits ? 8 : 4; @@ -328,15 +323,14 @@ template <class ELFT> void RelocationSection<ELFT>::finalize() { template <class ELFT> InterpSection<ELFT>::InterpSection() - : OutputSectionBase<ELFT>(".interp", llvm::ELF::SHT_PROGBITS, - llvm::ELF::SHF_ALLOC) { + : OutputSectionBase<ELFT>(".interp", SHT_PROGBITS, SHF_ALLOC) { this->Header.sh_size = Config->DynamicLinker.size() + 1; this->Header.sh_addralign = 1; } template <class ELFT> void OutputSectionBase<ELFT>::writeHeaderTo(Elf_Shdr *SHdr) { - Header.sh_name = Out<ELFT>::ShStrTab->getOffset(Name); + Header.sh_name = Out<ELFT>::ShStrTab->addString(Name); *SHdr = Header; } @@ -346,8 +340,7 @@ template <class ELFT> void InterpSection<ELFT>::writeTo(uint8_t *Buf) { template <class ELFT> HashTableSection<ELFT>::HashTableSection() - : OutputSectionBase<ELFT>(".hash", llvm::ELF::SHT_HASH, - llvm::ELF::SHF_ALLOC) { + : OutputSectionBase<ELFT>(".hash", SHT_HASH, SHF_ALLOC) { this->Header.sh_entsize = sizeof(Elf_Word); this->Header.sh_addralign = sizeof(Elf_Word); } @@ -404,8 +397,7 @@ static uint32_t hashGnu(StringRef Name) { template <class ELFT> GnuHashTableSection<ELFT>::GnuHashTableSection() - : OutputSectionBase<ELFT>(".gnu.hash", llvm::ELF::SHT_GNU_HASH, - llvm::ELF::SHF_ALLOC) { + : OutputSectionBase<ELFT>(".gnu.hash", SHT_GNU_HASH, SHF_ALLOC) { this->Header.sh_entsize = ELFT::Is64Bits ? 0 : 4; this->Header.sh_addralign = ELFT::Is64Bits ? 8 : 4; } @@ -545,8 +537,7 @@ void GnuHashTableSection<ELFT>::addSymbols(std::vector<SymbolBody *> &Symbols) { template <class ELFT> DynamicSection<ELFT>::DynamicSection(SymbolTable<ELFT> &SymTab) - : OutputSectionBase<ELFT>(".dynamic", llvm::ELF::SHT_DYNAMIC, - llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_WRITE), + : OutputSectionBase<ELFT>(".dynamic", SHT_DYNAMIC, SHF_ALLOC | SHF_WRITE), SymTab(SymTab) { Elf_Shdr &Header = this->Header; Header.sh_addralign = ELFT::Is64Bits ? 8 : 4; @@ -556,7 +547,7 @@ DynamicSection<ELFT>::DynamicSection(SymbolTable<ELFT> &SymTab) // See "Special Section" in Chapter 4 in the following document: // ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf if (Config->EMachine == EM_MIPS) - Header.sh_flags = llvm::ELF::SHF_ALLOC; + Header.sh_flags = SHF_ALLOC; } template <class ELFT> void DynamicSection<ELFT>::finalize() { @@ -590,12 +581,12 @@ template <class ELFT> void DynamicSection<ELFT>::finalize() { if (!Config->RPath.empty()) { ++NumEntries; // DT_RUNPATH / DT_RPATH - Out<ELFT>::DynStrTab->add(Config->RPath); + Out<ELFT>::DynStrTab->reserve(Config->RPath); } if (!Config->SoName.empty()) { ++NumEntries; // DT_SONAME - Out<ELFT>::DynStrTab->add(Config->SoName); + Out<ELFT>::DynStrTab->reserve(Config->SoName); } if (PreInitArraySec) @@ -608,7 +599,7 @@ template <class ELFT> void DynamicSection<ELFT>::finalize() { for (const std::unique_ptr<SharedFile<ELFT>> &F : SymTab.getSharedFiles()) { if (!F->isNeeded()) continue; - Out<ELFT>::DynStrTab->add(F->getSoName()); + Out<ELFT>::DynStrTab->reserve(F->getSoName()); ++NumEntries; } @@ -696,7 +687,7 @@ template <class ELFT> void DynamicSection<ELFT>::writeTo(uint8_t *Buf) { WritePtr(DT_SYMTAB, Out<ELFT>::DynSymTab->getVA()); WritePtr(DT_SYMENT, sizeof(Elf_Sym)); WritePtr(DT_STRTAB, Out<ELFT>::DynStrTab->getVA()); - WriteVal(DT_STRSZ, Out<ELFT>::DynStrTab->data().size()); + WriteVal(DT_STRSZ, Out<ELFT>::DynStrTab->getSize()); if (Out<ELFT>::GnuHashTab) WritePtr(DT_GNU_HASH, Out<ELFT>::GnuHashTab->getVA()); if (Out<ELFT>::HashTab) @@ -712,10 +703,10 @@ template <class ELFT> void DynamicSection<ELFT>::writeTo(uint8_t *Buf) { // DT_RPATH is used for indirect dependencies as well. if (!Config->RPath.empty()) WriteVal(Config->EnableNewDtags ? DT_RUNPATH : DT_RPATH, - Out<ELFT>::DynStrTab->getOffset(Config->RPath)); + Out<ELFT>::DynStrTab->addString(Config->RPath)); if (!Config->SoName.empty()) - WriteVal(DT_SONAME, Out<ELFT>::DynStrTab->getOffset(Config->SoName)); + WriteVal(DT_SONAME, Out<ELFT>::DynStrTab->addString(Config->SoName)); auto WriteArray = [&](int32_t T1, int32_t T2, const OutputSectionBase<ELFT> *Sec) { @@ -730,7 +721,7 @@ template <class ELFT> void DynamicSection<ELFT>::writeTo(uint8_t *Buf) { for (const std::unique_ptr<SharedFile<ELFT>> &F : SymTab.getSharedFiles()) if (F->isNeeded()) - WriteVal(DT_NEEDED, Out<ELFT>::DynStrTab->getOffset(F->getSoName())); + WriteVal(DT_NEEDED, Out<ELFT>::DynStrTab->addString(F->getSoName())); if (InitSym) WritePtr(DT_INIT, getSymVA<ELFT>(*InitSym)); @@ -765,9 +756,9 @@ template <class ELFT> void DynamicSection<ELFT>::writeTo(uint8_t *Buf) { } template <class ELFT> -OutputSection<ELFT>::OutputSection(StringRef Name, uint32_t sh_type, - uintX_t sh_flags) - : OutputSectionBase<ELFT>(Name, sh_type, sh_flags) {} +OutputSection<ELFT>::OutputSection(StringRef Name, uint32_t Type, + uintX_t Flags) + : OutputSectionBase<ELFT>(Name, Type, Flags) {} template <class ELFT> void OutputSection<ELFT>::addSection(InputSectionBase<ELFT> *C) { @@ -779,14 +770,14 @@ void OutputSection<ELFT>::addSection(InputSectionBase<ELFT> *C) { this->Header.sh_addralign = Align; uintX_t Off = this->Header.sh_size; - Off = RoundUpToAlignment(Off, Align); + Off = align(Off, Align); S->OutSecOff = Off; Off += S->getSize(); this->Header.sh_size = Off; } template <class ELFT> -typename ELFFile<ELFT>::uintX_t lld::elf2::getSymVA(const SymbolBody &S) { +typename ELFFile<ELFT>::uintX_t elf2::getSymVA(const SymbolBody &S) { switch (S.kind()) { case SymbolBody::DefinedSyntheticKind: { auto &D = cast<DefinedSynthetic<ELFT>>(S); @@ -797,6 +788,11 @@ typename ELFFile<ELFT>::uintX_t lld::elf2::getSymVA(const SymbolBody &S) { InputSectionBase<ELFT> *SC = DR.Section; if (!SC) return DR.Sym.st_value; + + // Symbol offsets for AMDGPU need to be the offset in bytes of the symbol + // from the beginning of the section. + if (Config->EMachine == EM_AMDGPU) + return SC->getOffset(DR.Sym); if (DR.Sym.getType() == STT_TLS) return SC->OutSec->getVA() + SC->getOffset(DR.Sym) - Out<ELFT>::TlsPhdr->p_vaddr; @@ -824,9 +820,9 @@ typename ELFFile<ELFT>::uintX_t lld::elf2::getSymVA(const SymbolBody &S) { // For non-local symbols, use getSymVA instead. template <class ELFT, bool IsRela> typename ELFFile<ELFT>::uintX_t -lld::elf2::getLocalRelTarget(const ObjectFile<ELFT> &File, - const Elf_Rel_Impl<ELFT, IsRela> &RI, - typename ELFFile<ELFT>::uintX_t Addend) { +elf2::getLocalRelTarget(const ObjectFile<ELFT> &File, + const Elf_Rel_Impl<ELFT, IsRela> &RI, + typename ELFFile<ELFT>::uintX_t Addend) { typedef typename ELFFile<ELFT>::Elf_Sym Elf_Sym; typedef typename ELFFile<ELFT>::uintX_t uintX_t; @@ -868,7 +864,7 @@ lld::elf2::getLocalRelTarget(const ObjectFile<ELFT> &File, // Returns true if a symbol can be replaced at load-time by a symbol // with the same name defined in other ELF executable or DSO. -bool lld::elf2::canBePreempted(const SymbolBody *Body, bool NeedsGot) { +bool elf2::canBePreempted(const SymbolBody *Body, bool NeedsGot) { if (!Body) return false; // Body is a local symbol. if (Body->isShared()) @@ -910,9 +906,9 @@ template <class ELFT> void OutputSection<ELFT>::writeTo(uint8_t *Buf) { } template <class ELFT> -EHOutputSection<ELFT>::EHOutputSection(StringRef Name, uint32_t sh_type, - uintX_t sh_flags) - : OutputSectionBase<ELFT>(Name, sh_type, sh_flags) {} +EHOutputSection<ELFT>::EHOutputSection(StringRef Name, uint32_t Type, + uintX_t Flags) + : OutputSectionBase<ELFT>(Name, Type, Flags) {} template <class ELFT> EHRegion<ELFT>::EHRegion(EHInputSection<ELFT> *S, unsigned Index) @@ -980,7 +976,7 @@ void EHOutputSection<ELFT>::addSectionAux( auto P = CieMap.insert(std::make_pair(CieInfo, Cies.size())); if (P.second) { Cies.push_back(C); - this->Header.sh_size += RoundUpToAlignment(Length, sizeof(uintX_t)); + this->Header.sh_size += align(Length, sizeof(uintX_t)); } OffsetToIndex[Offset] = P.first->second; } else { @@ -993,7 +989,7 @@ void EHOutputSection<ELFT>::addSectionAux( if (I == OffsetToIndex.end()) error("Invalid CIE reference"); Cies[I->second].Fdes.push_back(EHRegion<ELFT>(S, Index)); - this->Header.sh_size += RoundUpToAlignment(Length, sizeof(uintX_t)); + this->Header.sh_size += align(Length, sizeof(uintX_t)); } } @@ -1046,7 +1042,7 @@ static typename ELFFile<ELFT>::uintX_t writeAlignedCieOrFde(StringRef Data, uint8_t *Buf) { typedef typename ELFFile<ELFT>::uintX_t uintX_t; const endianness E = ELFT::TargetEndianness; - uint64_t Len = RoundUpToAlignment(Data.size(), sizeof(uintX_t)); + uint64_t Len = align(Data.size(), sizeof(uintX_t)); write32<E>(Buf, Len - 4); memcpy(Buf + 4, Data.data() + 4, Data.size() - 4); return Len; @@ -1083,9 +1079,9 @@ template <class ELFT> void EHOutputSection<ELFT>::writeTo(uint8_t *Buf) { } template <class ELFT> -MergeOutputSection<ELFT>::MergeOutputSection(StringRef Name, uint32_t sh_type, - uintX_t sh_flags) - : OutputSectionBase<ELFT>(Name, sh_type, sh_flags) {} +MergeOutputSection<ELFT>::MergeOutputSection(StringRef Name, uint32_t Type, + uintX_t Flags) + : OutputSectionBase<ELFT>(Name, Type, Flags) {} template <class ELFT> void MergeOutputSection<ELFT>::writeTo(uint8_t *Buf) { if (shouldTailMerge()) { @@ -1165,21 +1161,50 @@ template <class ELFT> void MergeOutputSection<ELFT>::finalize() { template <class ELFT> StringTableSection<ELFT>::StringTableSection(StringRef Name, bool Dynamic) - : OutputSectionBase<ELFT>(Name, llvm::ELF::SHT_STRTAB, - Dynamic ? (uintX_t)llvm::ELF::SHF_ALLOC : 0), + : OutputSectionBase<ELFT>(Name, SHT_STRTAB, + Dynamic ? (uintX_t)SHF_ALLOC : 0), Dynamic(Dynamic) { this->Header.sh_addralign = 1; } +// String tables are created in two phases. First you call reserve() +// to reserve room in the string table, and then call addString() to actually +// add that string. +// +// Why two phases? We want to know the size of the string table as early as +// possible to fix file layout. So we have separated finalize(), which +// determines the size of the section, from writeTo(), which writes the section +// contents to the output buffer. If we merge reserve() with addString(), +// we need a plumbing work for finalize() and writeTo() so that offsets +// we obtained in the former function can be written in the latter. +// This design eliminated that need. +template <class ELFT> void StringTableSection<ELFT>::reserve(StringRef S) { + Reserved += S.size() + 1; // +1 for NUL +} + +// Adds a string to the string table. You must call reserve() with the +// same string before calling addString(). +template <class ELFT> size_t StringTableSection<ELFT>::addString(StringRef S) { + size_t Pos = Used; + Strings.push_back(S); + Used += S.size() + 1; + Reserved -= S.size() + 1; + assert((int64_t)Reserved >= 0); + return Pos; +} + template <class ELFT> void StringTableSection<ELFT>::writeTo(uint8_t *Buf) { - StringRef Data = StrTabBuilder.data(); - memcpy(Buf, Data.data(), Data.size()); + // ELF string tables start with NUL byte, so advance the pointer by one. + ++Buf; + for (StringRef S : Strings) { + memcpy(Buf, S.data(), S.size()); + Buf += S.size() + 1; + } } template <class ELFT> -bool lld::elf2::shouldKeepInSymtab(const ObjectFile<ELFT> &File, - StringRef SymName, - const typename ELFFile<ELFT>::Elf_Sym &Sym) { +bool elf2::shouldKeepInSymtab(const ObjectFile<ELFT> &File, StringRef SymName, + const typename ELFFile<ELFT>::Elf_Sym &Sym) { if (Sym.getType() == STT_SECTION) return false; @@ -1208,16 +1233,12 @@ bool lld::elf2::shouldKeepInSymtab(const ObjectFile<ELFT> &File, template <class ELFT> SymbolTableSection<ELFT>::SymbolTableSection( SymbolTable<ELFT> &Table, StringTableSection<ELFT> &StrTabSec) - : OutputSectionBase<ELFT>( - StrTabSec.isDynamic() ? ".dynsym" : ".symtab", - StrTabSec.isDynamic() ? llvm::ELF::SHT_DYNSYM : llvm::ELF::SHT_SYMTAB, - StrTabSec.isDynamic() ? (uintX_t)llvm::ELF::SHF_ALLOC : 0), + : OutputSectionBase<ELFT>(StrTabSec.isDynamic() ? ".dynsym" : ".symtab", + StrTabSec.isDynamic() ? SHT_DYNSYM : SHT_SYMTAB, + StrTabSec.isDynamic() ? (uintX_t)SHF_ALLOC : 0), Table(Table), StrTabSec(StrTabSec) { - typedef OutputSectionBase<ELFT> Base; - typename Base::Elf_Shdr &Header = this->Header; - - Header.sh_entsize = sizeof(Elf_Sym); - Header.sh_addralign = ELFT::Is64Bits ? 8 : 4; + this->Header.sh_entsize = sizeof(Elf_Sym); + this->Header.sh_addralign = ELFT::Is64Bits ? 8 : 4; } // Orders symbols according to their positions in the GOT, @@ -1259,14 +1280,14 @@ template <class ELFT> void SymbolTableSection<ELFT>::finalize() { template <class ELFT> void SymbolTableSection<ELFT>::addLocalSymbol(StringRef Name) { - StrTabSec.add(Name); + StrTabSec.reserve(Name); ++NumVisible; ++NumLocals; } template <class ELFT> void SymbolTableSection<ELFT>::addSymbol(SymbolBody *Body) { - StrTabSec.add(Body->getName()); + StrTabSec.reserve(Body->getName()); Symbols.push_back(Body); ++NumVisible; } @@ -1306,9 +1327,13 @@ void SymbolTableSection<ELFT>::writeLocalSymbols(uint8_t *&Buf) { continue; const OutputSectionBase<ELFT> *OutSec = Section->OutSec; ESym->st_shndx = OutSec->SectionIndex; - VA += OutSec->getVA() + Section->getOffset(Sym); + VA = Section->getOffset(Sym); + // Symbol offsets for AMDGPU need to be the offset in bytes of the + // symbol from the beginning of the section. + if (Config->EMachine != EM_AMDGPU) + VA += OutSec->getVA(); } - ESym->st_name = StrTabSec.getOffset(SymName); + ESym->st_name = StrTabSec.addString(SymName); ESym->st_size = Sym.st_size; ESym->setBindingAndType(Sym.getBinding(), Sym.getType()); ESym->st_value = VA; @@ -1363,7 +1388,7 @@ void SymbolTableSection<ELFT>::writeGlobalSymbols(uint8_t *Buf) { } StringRef Name = Body->getName(); - ESym->st_name = StrTabSec.getOffset(Name); + ESym->st_name = StrTabSec.addString(Name); unsigned char Type = STT_NOTYPE; uintX_t Size = 0; @@ -1413,13 +1438,14 @@ template <class ELFT> void MipsReginfoOutputSection<ELFT>::writeTo(uint8_t *Buf) { auto *R = reinterpret_cast<Elf_Mips_RegInfo *>(Buf); R->ri_gp_value = getMipsGpAddr<ELFT>(); - R->ri_gprmask = GeneralMask; + R->ri_gprmask = GprMask; } template <class ELFT> void MipsReginfoOutputSection<ELFT>::addSection(InputSectionBase<ELFT> *C) { + // Copy input object file's .reginfo gprmask to output. auto *S = cast<MipsReginfoInputSection<ELFT>>(C); - GeneralMask |= S->getGeneralMask(); + GprMask |= S->Reginfo->ri_gprmask; } namespace lld { |