Index: ELF/ICF.cpp =================================================================== --- ELF/ICF.cpp +++ ELF/ICF.cpp @@ -231,7 +231,7 @@ } return A->getFlags() == B->getFlags() && A->getSize() == B->getSize() && - A->Data == B->Data; + A->getData() == B->getData(); } template Index: ELF/InputSection.h =================================================================== --- ELF/InputSection.h +++ ELF/InputSection.h @@ -43,10 +43,10 @@ // The garbage collector sets sections' Live bits. // If GC is disabled, all sections are considered live by default. - InputSectionData(Kind SectionKind, StringRef Name, ArrayRef Data, - bool Compressed, bool Live) + InputSectionData(Kind SectionKind, StringRef Name, const uint8_t *Data, + size_t Size, bool Compressed, bool Live) : SectionKind(SectionKind), Live(Live), Compressed(Compressed), - Name(Name), Data(Data) {} + Name(Name), Data(Data), Size(Size) {} private: unsigned SectionKind : 3; @@ -58,7 +58,18 @@ unsigned Compressed : 1; uint32_t Alignment; StringRef Name; - ArrayRef Data; + + const uint8_t *Data; + size_t Size; + + llvm::ArrayRef getData() const { + return llvm::makeArrayRef(Data, Size); + } + + template llvm::ArrayRef getDataAs() const { + assert(Size % sizeof(T) == 0); + return llvm::makeArrayRef((const T *)Data, Size / sizeof(T)); + } // If a section is compressed, this has the uncompressed section data. std::unique_ptr UncompressedData; @@ -75,18 +86,27 @@ 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), - Repl(this) {} + : InputSectionData(Regular, "", nullptr, 0, false, false), Repl(this) {} 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, const uint8_t *Data, size_t Size, + StringRef Name, Kind SectionKind); OutputSectionBase *OutSec = nullptr; // This pointer points to the "real" instance of this instance. @@ -101,11 +121,11 @@ 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 +245,8 @@ typedef typename ELFT::uint uintX_t; public: + InputSection(uintX_t Flags, uint32_t Type, uintX_t Addralign, + const uint8_t *Data, size_t Size); InputSection(ObjectFile *F, const Elf_Shdr *Header, StringRef Name); // Write this section to a mmap'ed file, assuming Buf is pointing to @@ -259,6 +281,14 @@ 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 +302,9 @@ 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 +347,6 @@ 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 Index: ELF/InputSection.cpp =================================================================== --- ELF/InputSection.cpp +++ ELF/InputSection.cpp @@ -30,31 +30,35 @@ using namespace lld::elf; template -static ArrayRef getSectionContents(elf::ObjectFile *File, - const typename ELFT::Shdr *Hdr) { +static const uint8_t *getSectionContents(elf::ObjectFile *File, + const typename ELFT::Shdr *Hdr) { if (!File || Hdr->sh_type == SHT_NOBITS) - return {}; - return check(File->getObj().getSectionContents(Hdr)); + return nullptr; + return check(File->getObj().getSectionContents(Hdr)).data(); } // 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, - Kind SectionKind) - : InputSectionData(SectionKind, Name, getSectionContents(File, Hdr), - isCompressed(Hdr, Name), - !Config->GcSections || !(Hdr->sh_flags & SHF_ALLOC)), - Header(Hdr), File(File), Repl(this) { + uintX_t Flags, uint32_t Type, + uintX_t Entsize, uint32_t Link, + uint32_t Info, uintX_t Addralign, + const uint8_t *Data, size_t Size, + StringRef Name, Kind SectionKind) + : InputSectionData(SectionKind, Name, Data, Size, + 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 +70,20 @@ 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), Hdr->sh_size, 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 Size; } // Returns a string for an error message. @@ -151,16 +164,17 @@ ArrayRef Buf; // Compressed data size_t Size; // Uncompressed size if (getFlags() & SHF_COMPRESSED) - std::tie(Buf, Size) = getElfCompressedData(Data); + std::tie(Buf, Size) = getElfCompressedData(getData()); else - std::tie(Buf, Size) = getRawCompressedData(Data); + std::tie(Buf, Size) = getRawCompressedData(getData()); // Uncompress Buf. UncompressedData.reset(new uint8_t[Size]); if (zlib::uncompress(toStringRef(Buf), (char *)UncompressedData.get(), Size) != zlib::StatusOK) fatal(getName(this) + ": error while uncompressing section"); - Data = ArrayRef(UncompressedData.get(), Size); + Data = UncompressedData.get(); + this->Size = Size; } template @@ -177,6 +191,14 @@ } template +InputSection::InputSection(uintX_t Flags, uint32_t Type, + uintX_t Addralign, const uint8_t *Data, + size_t Size) + : InputSectionBase(nullptr, Flags, Type, + /*Entsize*/ 0, /*Link*/ 0, /*Info*/ 0, Addralign, + Data, Size, "", Base::Regular) {} + +template InputSection::InputSection(elf::ObjectFile *F, const Elf_Shdr *Header, StringRef Name) : InputSectionBase(F, Header, Name, Base::Regular) {} @@ -198,7 +220,7 @@ } template uint64_t InputSection::getThunkOff() const { - return this->Header->sh_size; + return this->Size; } template uint64_t InputSection::getThunksSize() const { @@ -458,20 +480,19 @@ 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; } // Copy section contents from source object file to output file. - ArrayRef Data = this->Data; + ArrayRef Data = this->getData(); memcpy(Buf + OutSecOff, Data.data(), Data.size()); // Iterate over all relocation sections that apply to this section. @@ -554,7 +575,7 @@ template template void EhInputSection::split(ArrayRef Rels) { - ArrayRef Data = this->Data; + ArrayRef Data = this->getData(); unsigned RelI = 0; for (size_t Off = 0, End = Data.size(); Off != End;) { size_t Size = readEhRecordSize(Data.slice(Off)); @@ -606,8 +627,8 @@ ArrayRef MergeInputSection::getData( std::vector::const_iterator I) const { auto Next = I + 1; - size_t End = Next == Pieces.end() ? this->Data.size() : Next->InputOff; - return this->Data.slice(I->InputOff, End - I->InputOff); + size_t End = Next == Pieces.end() ? this->Size : Next->InputOff; + return InputSectionData::getData().slice(I->InputOff, End - I->InputOff); } // Split non-SHF_STRINGS section. Such section is a sequence of @@ -634,7 +655,7 @@ : InputSectionBase(F, Header, Name, InputSectionBase::Merge) {} template void MergeInputSection::splitIntoPieces() { - ArrayRef Data = this->Data; + ArrayRef Data = InputSectionData::getData(); uintX_t EntSize = this->getEntsize(); if (this->getFlags() & SHF_STRINGS) this->Pieces = splitStrings(Data, EntSize); @@ -674,7 +695,7 @@ template const SectionPiece * MergeInputSection::getSectionPiece(uintX_t Offset) const { - uintX_t Size = this->Data.size(); + uintX_t Size = this->Size; if (Offset >= Size) fatal(getName(this) + ": entry is past the end of the section"); @@ -737,7 +758,7 @@ StringRef Name) : InputSectionBase(F, Hdr, Name, InputSectionBase::MipsReginfo) { - ArrayRef Data = this->Data; + ArrayRef Data = this->getData(); // Initialize this->Reginfo. if (Data.size() != sizeof(Elf_Mips_RegInfo)) { error(getName(this) + ": invalid size of .reginfo section"); @@ -760,7 +781,7 @@ : InputSectionBase(F, Hdr, Name, InputSectionBase::MipsOptions) { // Find ODK_REGINFO option in the section's content. - ArrayRef D = this->Data; + ArrayRef D = this->getData(); while (!D.empty()) { if (D.size() < sizeof(Elf_Mips_Options)) { error(getName(this) + ": invalid size of .MIPS.options section"); @@ -790,7 +811,7 @@ : InputSectionBase(F, Hdr, Name, InputSectionBase::MipsAbiFlags) { // Initialize this->Flags. - ArrayRef Data = this->Data; + ArrayRef Data = this->getData(); if (Data.size() != sizeof(Elf_Mips_ABIFlags)) { error("invalid size of .MIPS.abiflags section"); return; @@ -804,27 +825,28 @@ } 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; } + + InputSection Ret(SHF_ALLOC | SHF_WRITE, SHT_NOBITS, Alignment, nullptr, Size); + Ret.Live = true; + return Ret; } template class elf::InputSectionBase; @@ -861,8 +883,3 @@ 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; Index: ELF/LinkerScript.cpp =================================================================== --- ELF/LinkerScript.cpp +++ ELF/LinkerScript.cpp @@ -184,7 +184,7 @@ 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 Index: ELF/MarkLive.cpp =================================================================== --- ELF/MarkLive.cpp +++ ELF/MarkLive.cpp @@ -53,7 +53,7 @@ template static typename ELFT::uint getAddend(InputSectionBase &Sec, const typename ELFT::Rel &Rel) { - return Target->getImplicitAddend(Sec.Data.begin() + Rel.r_offset, + return Target->getImplicitAddend(Sec.Data + Rel.r_offset, Rel.getType(Config->Mips64EL)); } Index: ELF/OutputSections.cpp =================================================================== --- ELF/OutputSections.cpp +++ ELF/OutputSections.cpp @@ -1565,7 +1565,7 @@ break; } case SymbolBody::DefinedCommonKind: - return CommonInputSection::X->OutSec; + return InputSection::CommonInputSection->OutSec; case SymbolBody::SharedKind: if (cast>(Sym)->needsCopy()) return Out::Bss; Index: ELF/Relocations.cpp =================================================================== --- ELF/Relocations.cpp +++ ELF/Relocations.cpp @@ -565,7 +565,7 @@ }; const elf::ObjectFile &File = *C.getFile(); - ArrayRef SectionData = C.Data; + ArrayRef SectionData = C.getData(); const uint8_t *Buf = SectionData.begin(); ArrayRef Pieces; Index: ELF/Symbols.cpp =================================================================== --- ELF/Symbols.cpp +++ ELF/Symbols.cpp @@ -69,8 +69,8 @@ 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); Index: ELF/Writer.cpp =================================================================== --- ELF/Writer.cpp +++ ELF/Writer.cpp @@ -261,8 +261,9 @@ 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 @@ // 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(); }