From: Rafael Espindola Date: Wed, 26 Oct 2016 00:54:03 +0000 (+0000) Subject: Read section headers upfront. X-Git-Tag: llvmorg-4.0.0-rc1~6283 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=0e090522c89b5fb1de63644532995398a7f196a7;p=platform%2Fupstream%2Fllvm.git Read section headers upfront. Instead of storing a pointer, store the members we need. The reason for doing this is that it makes it far easier to create synthetic sections. It also avoids reading data from files multiple times., which might help with cross endian linking and host architectures with slow unaligned access. There are obvious compacting opportunities, but this already has mixed results even on native x86_64 linking. There is also the possibility of better refactoring the code for handling common symbols, but this already shows that a custom class is not necessary. llvm-svn: 285148 --- diff --git a/lld/ELF/InputSection.cpp b/lld/ELF/InputSection.cpp index 81f3cea..d407be4 100644 --- a/lld/ELF/InputSection.cpp +++ b/lld/ELF/InputSection.cpp @@ -33,28 +33,31 @@ template static ArrayRef getSectionContents(elf::ObjectFile *File, const typename ELFT::Shdr *Hdr) { if (!File || Hdr->sh_type == SHT_NOBITS) - return {}; + return makeArrayRef(nullptr, Hdr->sh_size); return check(File->getObj().getSectionContents(Hdr)); } // ELF supports ZLIB-compressed section. Returns true if the section // is compressed. template -static bool isCompressed(const typename ELFT::Shdr *Hdr, StringRef Name) { - return (Hdr->sh_flags & SHF_COMPRESSED) || Name.startswith(".zdebug"); +static bool isCompressed(typename ELFT::uint Flags, StringRef Name) { + return (Flags & SHF_COMPRESSED) || Name.startswith(".zdebug"); } template InputSectionBase::InputSectionBase(elf::ObjectFile *File, - const Elf_Shdr *Hdr, StringRef Name, + uintX_t Flags, uint32_t Type, + uintX_t Entsize, uint32_t Link, + uint32_t Info, uintX_t Addralign, + ArrayRef Data, StringRef Name, Kind SectionKind) - : InputSectionData(SectionKind, Name, getSectionContents(File, Hdr), - isCompressed(Hdr, Name), - !Config->GcSections || !(Hdr->sh_flags & SHF_ALLOC)), - Header(Hdr), File(File), Repl(this) { + : InputSectionData(SectionKind, Name, Data, isCompressed(Flags, Name), + !Config->GcSections || !(Flags & SHF_ALLOC)), + File(File), Flags(Flags), Entsize(Entsize), Type(Type), Link(Link), + Info(Info), Repl(this) { // The ELF spec states that a value of 0 means the section has // no alignment constraits. - uint64_t V = std::max(Hdr->sh_addralign, 1); + uint64_t V = std::max(Addralign, 1); if (!isPowerOf2_64(V)) fatal(getFilename(File) + ": section sh_addralign is not a power of 2"); @@ -66,11 +69,19 @@ InputSectionBase::InputSectionBase(elf::ObjectFile *File, Alignment = V; } +template +InputSectionBase::InputSectionBase(elf::ObjectFile *File, + const Elf_Shdr *Hdr, StringRef Name, + Kind SectionKind) + : InputSectionBase(File, Hdr->sh_flags, Hdr->sh_type, Hdr->sh_entsize, + Hdr->sh_link, Hdr->sh_info, Hdr->sh_addralign, + getSectionContents(File, Hdr), Name, SectionKind) {} + template size_t InputSectionBase::getSize() const { if (auto *D = dyn_cast>(this)) if (D->getThunksSize() > 0) return D->getThunkOff() + D->getThunksSize(); - return Header->sh_size; + return Data.size(); } // Returns a string for an error message. @@ -177,6 +188,13 @@ InputSectionBase *InputSectionBase::getLinkOrderDep() const { } template +InputSection::InputSection(uintX_t Flags, uint32_t Type, + uintX_t Addralign, ArrayRef Data) + : InputSectionBase(nullptr, Flags, Type, + /*Entsize*/ 0, /*Link*/ 0, /*Info*/ 0, Addralign, + Data, "", Base::Regular) {} + +template InputSection::InputSection(elf::ObjectFile *F, const Elf_Shdr *Header, StringRef Name) : InputSectionBase(F, Header, Name, Base::Regular) {} @@ -198,7 +216,7 @@ template void InputSection::addThunk(const Thunk *T) { } template uint64_t InputSection::getThunkOff() const { - return this->Header->sh_size; + return this->Data.size(); } template uint64_t InputSection::getThunksSize() const { @@ -458,15 +476,14 @@ void InputSectionBase::relocate(uint8_t *Buf, uint8_t *BufEnd) { template void InputSection::writeTo(uint8_t *Buf) { if (this->getType() == SHT_NOBITS) return; - ELFFile &EObj = this->File->getObj(); // If -r is given, then an InputSection may be a relocation section. if (this->getType() == SHT_RELA) { - copyRelocations(Buf + OutSecOff, EObj.relas(this->Header)); + copyRelocations(Buf + OutSecOff, this->template getDataAs()); return; } if (this->getType() == SHT_REL) { - copyRelocations(Buf + OutSecOff, EObj.rels(this->Header)); + copyRelocations(Buf + OutSecOff, this->template getDataAs()); return; } @@ -804,27 +821,28 @@ bool MipsAbiFlagsInputSection::classof(const InputSectionBase *S) { } template -CommonInputSection::CommonInputSection(std::vector Syms) - : InputSection(nullptr, &Hdr, "") { - Hdr.sh_size = 0; - Hdr.sh_type = SHT_NOBITS; - Hdr.sh_flags = SHF_ALLOC | SHF_WRITE; - this->Live = true; - +InputSection InputSection::createCommonInputSection( + std::vector Syms) { // Sort the common symbols by alignment as an heuristic to pack them better. std::stable_sort(Syms.begin(), Syms.end(), [](const DefinedCommon *A, const DefinedCommon *B) { return A->Alignment > B->Alignment; }); + size_t Size = 0; + uintX_t Alignment = 1; for (DefinedCommon *Sym : Syms) { - this->Alignment = std::max(this->Alignment, Sym->Alignment); - Hdr.sh_size = alignTo(Hdr.sh_size, Sym->Alignment); + Alignment = std::max(Alignment, Sym->Alignment); + Size = alignTo(Size, Sym->Alignment); // Compute symbol offset relative to beginning of input section. - Sym->Offset = Hdr.sh_size; - Hdr.sh_size += Sym->Size; + Sym->Offset = Size; + Size += Sym->Size; } + ArrayRef Data = makeArrayRef(nullptr, Size); + InputSection Ret(SHF_ALLOC | SHF_WRITE, SHT_NOBITS, Alignment, Data); + Ret.Live = true; + return Ret; } template class elf::InputSectionBase; @@ -861,8 +879,3 @@ template class elf::MipsAbiFlagsInputSection; template class elf::MipsAbiFlagsInputSection; template class elf::MipsAbiFlagsInputSection; template class elf::MipsAbiFlagsInputSection; - -template class elf::CommonInputSection; -template class elf::CommonInputSection; -template class elf::CommonInputSection; -template class elf::CommonInputSection; diff --git a/lld/ELF/InputSection.h b/lld/ELF/InputSection.h index 3ff3531..40ae21e 100644 --- a/lld/ELF/InputSection.h +++ b/lld/ELF/InputSection.h @@ -60,6 +60,12 @@ public: StringRef Name; ArrayRef Data; + template llvm::ArrayRef getDataAs() const { + size_t S = Data.size(); + assert(S % sizeof(T) == 0); + return llvm::makeArrayRef((const T *)Data.data(), S / sizeof(T)); + } + // If a section is compressed, this has the uncompressed section data. std::unique_ptr UncompressedData; @@ -75,11 +81,17 @@ protected: typedef typename ELFT::Shdr Elf_Shdr; typedef typename ELFT::Sym Elf_Sym; typedef typename ELFT::uint uintX_t; - const Elf_Shdr *Header; // The file this section is from. ObjectFile *File; + // These corresponds to the fields in Elf_Shdr. + uintX_t Flags; + uintX_t Entsize; + uint32_t Type; + uint32_t Link; + uint32_t Info; + public: InputSectionBase() : InputSectionData(Regular, "", ArrayRef(), false, false), @@ -87,6 +99,10 @@ public: InputSectionBase(ObjectFile *File, const Elf_Shdr *Header, StringRef Name, Kind SectionKind); + InputSectionBase(ObjectFile *File, uintX_t Flags, uint32_t Type, + uintX_t Entsize, uint32_t Link, uint32_t Info, + uintX_t Addralign, ArrayRef Data, StringRef Name, + Kind SectionKind); OutputSectionBase *OutSec = nullptr; // This pointer points to the "real" instance of this instance. @@ -101,11 +117,11 @@ public: static InputSectionBase Discarded; - uintX_t getFlags() const { return Header->sh_flags; } - uint32_t getType() const { return Header->sh_type; } - uintX_t getEntsize() const { return Header->sh_entsize; } - uint32_t getLink() const { return Header->sh_link; } - uint32_t getInfo() const { return Header->sh_info; } + uintX_t getFlags() const { return Flags; } + uint32_t getType() const { return Type; } + uintX_t getEntsize() const { return Entsize; } + uint32_t getLink() const { return Link; } + uint32_t getInfo() const { return Info; } ObjectFile *getFile() const { return File; } uintX_t getOffset(const DefinedRegular &Sym) const; InputSectionBase *getLinkOrderDep() const; @@ -225,6 +241,8 @@ template class InputSection : public InputSectionBase { typedef typename ELFT::uint uintX_t; public: + InputSection(uintX_t Flags, uint32_t Type, uintX_t Addralign, + ArrayRef Data); InputSection(ObjectFile *F, const Elf_Shdr *Header, StringRef Name); // Write this section to a mmap'ed file, assuming Buf is pointing to @@ -259,6 +277,14 @@ public: template void relocateNonAlloc(uint8_t *Buf, llvm::ArrayRef Rels); + // Common symbols don't belong to any section. But it is easier for us + // to handle them as if they belong to some input section. So we defined + // this section that "contains" all common symbols. + static InputSection *CommonInputSection; + + static InputSection + createCommonInputSection(std::vector Syms); + private: template void copyRelocations(uint8_t *Buf, llvm::ArrayRef Rels); @@ -272,6 +298,9 @@ private: llvm::TinyPtrVector *> Thunks; }; +template +InputSection *InputSection::CommonInputSection; + // MIPS .reginfo section provides information on the registers used by the code // in the object file. Linker should collect this information and write a single // .reginfo section in the output file. The output section contains a union of @@ -314,26 +343,6 @@ public: const llvm::object::Elf_Mips_ABIFlags *Flags = nullptr; }; -// Common symbols don't belong to any section. But it is easier for us -// to handle them as if they belong to some input section. So we defined -// this class. CommonInputSection is a virtual singleton class that -// "contains" all common symbols. -template class CommonInputSection : public InputSection { - typedef typename ELFT::uint uintX_t; - -public: - CommonInputSection(std::vector Syms); - - // The singleton instance of this class. - static CommonInputSection *X; - -private: - static typename ELFT::Shdr Hdr; -}; - -template CommonInputSection *CommonInputSection::X; -template typename ELFT::Shdr CommonInputSection::Hdr; - } // namespace elf } // namespace lld diff --git a/lld/ELF/LinkerScript.cpp b/lld/ELF/LinkerScript.cpp index 5fd49eb..ed6dd69 100644 --- a/lld/ELF/LinkerScript.cpp +++ b/lld/ELF/LinkerScript.cpp @@ -184,7 +184,7 @@ void LinkerScript::computeInputSections(InputSectionDescription *I) { if (!isDiscarded(S) && !S->OutSec && Pat.SectionRe.match(S->Name)) I->Sections.push_back(S); if (Pat.SectionRe.match("COMMON")) - I->Sections.push_back(CommonInputSection::X); + I->Sections.push_back(InputSection::CommonInputSection); } // Sort sections as instructed by SORT-family commands and --sort-section diff --git a/lld/ELF/OutputSections.cpp b/lld/ELF/OutputSections.cpp index e38de2e..0bbd4ed 100644 --- a/lld/ELF/OutputSections.cpp +++ b/lld/ELF/OutputSections.cpp @@ -1565,7 +1565,7 @@ SymbolTableSection::getOutputSection(SymbolBody *Sym) { break; } case SymbolBody::DefinedCommonKind: - return CommonInputSection::X->OutSec; + return InputSection::CommonInputSection->OutSec; case SymbolBody::SharedKind: if (cast>(Sym)->needsCopy()) return Out::Bss; diff --git a/lld/ELF/Symbols.cpp b/lld/ELF/Symbols.cpp index 707143e..f59132a 100644 --- a/lld/ELF/Symbols.cpp +++ b/lld/ELF/Symbols.cpp @@ -69,8 +69,8 @@ static typename ELFT::uint getSymVA(const SymbolBody &Body, return VA; } case SymbolBody::DefinedCommonKind: - return CommonInputSection::X->OutSec->getVA() + - CommonInputSection::X->OutSecOff + + return InputSection::CommonInputSection->OutSec->getVA() + + InputSection::CommonInputSection->OutSecOff + cast(Body).Offset; case SymbolBody::SharedKind: { auto &SS = cast>(Body); diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp index 037d4d9..7d54c15 100644 --- a/lld/ELF/Writer.cpp +++ b/lld/ELF/Writer.cpp @@ -261,8 +261,9 @@ template void Writer::run() { if (Target->NeedsThunks) forEachRelSec(createThunks); - CommonInputSection Common(getCommonSymbols()); - CommonInputSection::X = &Common; + InputSection Common = + InputSection::createCommonInputSection(getCommonSymbols()); + InputSection::CommonInputSection = &Common; Script::X->OutputSections = &OutputSections; if (ScriptConfig->HasSections) { @@ -825,8 +826,8 @@ template void Writer::finalizeSections() { // If linker script processor hasn't added common symbol section yet, // then add it to .bss now. - if (!CommonInputSection::X->OutSec) { - Out::Bss->addSection(CommonInputSection::X); + if (!InputSection::CommonInputSection->OutSec) { + Out::Bss->addSection(InputSection::CommonInputSection); Out::Bss->assignOffsets(); }