From 282251a22640d6a2845d761064718dc88c4ad1d0 Mon Sep 17 00:00:00 2001 From: Eugene Leviant Date: Tue, 1 Nov 2016 09:49:24 +0000 Subject: [PATCH] Convert BuildIdSection to input section Differential revision: https://reviews.llvm.org/D25627 llvm-svn: 285682 --- lld/ELF/InputSection.cpp | 89 +++++++++++++++++++++++++++++++++++++ lld/ELF/InputSection.h | 55 +++++++++++++++++++++++ lld/ELF/OutputSections.cpp | 90 -------------------------------------- lld/ELF/OutputSections.h | 50 --------------------- lld/ELF/Writer.cpp | 59 ++++++++++++++----------- lld/test/ELF/build-id.s | 2 +- 6 files changed, 179 insertions(+), 166 deletions(-) diff --git a/lld/ELF/InputSection.cpp b/lld/ELF/InputSection.cpp index 696e9d37d689..ce20b5f0164b 100644 --- a/lld/ELF/InputSection.cpp +++ b/lld/ELF/InputSection.cpp @@ -19,6 +19,8 @@ #include "llvm/Support/Compression.h" #include "llvm/Support/Endian.h" +#include "llvm/Support/RandomNumberGenerator.h" +#include "llvm/Support/xxhash.h" using namespace llvm; using namespace llvm::ELF; @@ -480,6 +482,9 @@ template void InputSection::writeTo(uint8_t *Buf) { if (this->Type == SHT_NOBITS) return; + // Set output location. + this->OutputLoc = Buf + OutSecOff; + // If -r is given, then an InputSection may be a relocation section. if (this->Type == SHT_RELA) { copyRelocations(Buf + OutSecOff, this->template getDataAs()); @@ -848,6 +853,60 @@ InputSection InputSection::createCommonInputSection( return Ret; } +template +BuildIdSection::BuildIdSection(size_t HashSize) + : InputSection(SHF_ALLOC, SHT_NOTE, 1, ArrayRef(), + ".note.gnu.build-id") { + Buf.resize(16 + HashSize); + const endianness E = ELFT::TargetEndianness; + write32(Buf.data(), 4); // Name size + write32(Buf.data() + 4, HashSize); // Content size + write32(Buf.data() + 8, NT_GNU_BUILD_ID); // Type + memcpy(Buf.data() + 12, "GNU", 4); // Name string + this->Data = ArrayRef(Buf); +} + +template +void BuildIdFastHash::writeBuildId(ArrayRef Buf) { + const endianness E = ELFT::TargetEndianness; + + // 64-bit xxhash + uint64_t Hash = xxHash64(toStringRef(Buf)); + write64(this->OutputLoc + 16, Hash); +} + +template +void BuildIdMd5::writeBuildId(ArrayRef Buf) { + MD5 Hash; + Hash.update(Buf); + MD5::MD5Result Res; + Hash.final(Res); + memcpy(this->OutputLoc + 16, Res, 16); +} + +template +void BuildIdSha1::writeBuildId(ArrayRef Buf) { + SHA1 Hash; + Hash.update(Buf); + memcpy(this->OutputLoc + 16, Hash.final().data(), 20); +} + +template +void BuildIdUuid::writeBuildId(ArrayRef Buf) { + if (getRandomBytes(this->OutputLoc + 16, 16)) + error("entropy source failure"); +} + +template +BuildIdHexstring::BuildIdHexstring() + : BuildIdSection(Config->BuildIdVector.size()) {} + +template +void BuildIdHexstring::writeBuildId(ArrayRef Buf) { + memcpy(this->OutputLoc + 16, Config->BuildIdVector.data(), + Config->BuildIdVector.size()); +} + template class elf::InputSectionBase; template class elf::InputSectionBase; template class elf::InputSectionBase; @@ -882,3 +941,33 @@ template class elf::MipsAbiFlagsInputSection; template class elf::MipsAbiFlagsInputSection; template class elf::MipsAbiFlagsInputSection; template class elf::MipsAbiFlagsInputSection; + +template class elf::BuildIdSection; +template class elf::BuildIdSection; +template class elf::BuildIdSection; +template class elf::BuildIdSection; + +template class elf::BuildIdFastHash; +template class elf::BuildIdFastHash; +template class elf::BuildIdFastHash; +template class elf::BuildIdFastHash; + +template class elf::BuildIdMd5; +template class elf::BuildIdMd5; +template class elf::BuildIdMd5; +template class elf::BuildIdMd5; + +template class elf::BuildIdSha1; +template class elf::BuildIdSha1; +template class elf::BuildIdSha1; +template class elf::BuildIdSha1; + +template class elf::BuildIdUuid; +template class elf::BuildIdUuid; +template class elf::BuildIdUuid; +template class elf::BuildIdUuid; + +template class elf::BuildIdHexstring; +template class elf::BuildIdHexstring; +template class elf::BuildIdHexstring; +template class elf::BuildIdHexstring; diff --git a/lld/ELF/InputSection.h b/lld/ELF/InputSection.h index d54d019f5965..9b4432e812c8 100644 --- a/lld/ELF/InputSection.h +++ b/lld/ELF/InputSection.h @@ -252,6 +252,9 @@ public: // to. The writer sets a value. uint64_t OutSecOff = 0; + // Location of this section in the output buffer + uint8_t *OutputLoc = nullptr; + // InputSection that is dependent on us (reverse dependency for GC) InputSectionBase *DependentSection = nullptr; @@ -339,6 +342,58 @@ public: const llvm::object::Elf_Mips_ABIFlags *Flags = nullptr; }; +template class BuildIdSection : public InputSection { + typedef OutputSectionBase Base; + +public: + virtual void writeBuildId(ArrayRef Buf) = 0; + virtual ~BuildIdSection() = default; + +protected: + BuildIdSection(size_t HashSize); + std::vector Buf; +}; + +template +class BuildIdFastHash final : public BuildIdSection { +public: + BuildIdFastHash() : BuildIdSection(8) {} + void writeBuildId(ArrayRef Buf) override; +}; + +template class BuildIdMd5 final : public BuildIdSection { +public: + BuildIdMd5() : BuildIdSection(16) {} + void writeBuildId(ArrayRef Buf) override; +}; + +template class BuildIdSha1 final : public BuildIdSection { +public: + BuildIdSha1() : BuildIdSection(20) {} + void writeBuildId(ArrayRef Buf) override; +}; + +template class BuildIdUuid final : public BuildIdSection { +public: + BuildIdUuid() : BuildIdSection(16) {} + void writeBuildId(ArrayRef Buf) override; +}; + +template +class BuildIdHexstring final : public BuildIdSection { +public: + BuildIdHexstring(); + void writeBuildId(ArrayRef) override; +}; + +// Linker generated sections which can be used as inputs. +template struct In { + static BuildIdSection *BuildId; + static std::vector *> Sections; +}; + +template BuildIdSection *In::BuildId; +template std::vector *> In::Sections; } // namespace elf } // namespace lld diff --git a/lld/ELF/OutputSections.cpp b/lld/ELF/OutputSections.cpp index 5566a4225378..9be3b3b9f4ae 100644 --- a/lld/ELF/OutputSections.cpp +++ b/lld/ELF/OutputSections.cpp @@ -19,9 +19,7 @@ #include "llvm/Support/Dwarf.h" #include "llvm/Support/MD5.h" #include "llvm/Support/MathExtras.h" -#include "llvm/Support/RandomNumberGenerator.h" #include "llvm/Support/SHA1.h" -#include "llvm/Support/xxhash.h" using namespace llvm; using namespace llvm::dwarf; @@ -1738,64 +1736,6 @@ template void VersionNeedSection::finalize() { this->Header.sh_size = Size; } -template -BuildIdSection::BuildIdSection(size_t HashSize) - : OutputSectionBase(".note.gnu.build-id", SHT_NOTE, SHF_ALLOC), - HashSize(HashSize) { - // 16 bytes for the note section header. - this->Header.sh_size = 16 + HashSize; -} - -template void BuildIdSection::writeTo(uint8_t *Buf) { - const endianness E = ELFT::TargetEndianness; - write32(Buf, 4); // Name size - write32(Buf + 4, HashSize); // Content size - write32(Buf + 8, NT_GNU_BUILD_ID); // Type - memcpy(Buf + 12, "GNU", 4); // Name string - HashBuf = Buf + 16; -} - -template -void BuildIdFastHash::writeBuildId(ArrayRef Buf) { - const endianness E = ELFT::TargetEndianness; - - // 64-bit xxhash - uint64_t Hash = xxHash64(toStringRef(Buf)); - write64(this->HashBuf, Hash); -} - -template -void BuildIdMd5::writeBuildId(ArrayRef Buf) { - MD5 Hash; - Hash.update(Buf); - MD5::MD5Result Res; - Hash.final(Res); - memcpy(this->HashBuf, Res, 16); -} - -template -void BuildIdSha1::writeBuildId(ArrayRef Buf) { - SHA1 Hash; - Hash.update(Buf); - memcpy(this->HashBuf, Hash.final().data(), 20); -} - -template -void BuildIdUuid::writeBuildId(ArrayRef Buf) { - if (getRandomBytes(this->HashBuf, 16)) - error("entropy source failure"); -} - -template -BuildIdHexstring::BuildIdHexstring() - : BuildIdSection(Config->BuildIdVector.size()) {} - -template -void BuildIdHexstring::writeBuildId(ArrayRef Buf) { - memcpy(this->HashBuf, Config->BuildIdVector.data(), - Config->BuildIdVector.size()); -} - template MipsReginfoOutputSection::MipsReginfoOutputSection() : OutputSectionBase(".reginfo", SHT_MIPS_REGINFO, SHF_ALLOC) { @@ -2101,36 +2041,6 @@ template class VersionDefinitionSection; template class VersionDefinitionSection; template class VersionDefinitionSection; -template class BuildIdSection; -template class BuildIdSection; -template class BuildIdSection; -template class BuildIdSection; - -template class BuildIdFastHash; -template class BuildIdFastHash; -template class BuildIdFastHash; -template class BuildIdFastHash; - -template class BuildIdMd5; -template class BuildIdMd5; -template class BuildIdMd5; -template class BuildIdMd5; - -template class BuildIdSha1; -template class BuildIdSha1; -template class BuildIdSha1; -template class BuildIdSha1; - -template class BuildIdUuid; -template class BuildIdUuid; -template class BuildIdUuid; -template class BuildIdUuid; - -template class BuildIdHexstring; -template class BuildIdHexstring; -template class BuildIdHexstring; -template class BuildIdHexstring; - template class GdbIndexSection; template class GdbIndexSection; template class GdbIndexSection; diff --git a/lld/ELF/OutputSections.h b/lld/ELF/OutputSections.h index 182c96f56b26..f90719f34672 100644 --- a/lld/ELF/OutputSections.h +++ b/lld/ELF/OutputSections.h @@ -51,7 +51,6 @@ public: typedef typename ELFT::Shdr Elf_Shdr; enum Kind { Base, - BuildId, Dynamic, EHFrame, EHFrameHdr, @@ -738,60 +737,12 @@ private: std::vector Fdes; }; -template class BuildIdSection : public OutputSectionBase { - typedef OutputSectionBase Base; - -public: - void writeTo(uint8_t *Buf) override; - virtual void writeBuildId(ArrayRef Buf) = 0; - typename Base::Kind getKind() const override { return Base::BuildId; } - static bool classof(const Base *B) { return B->getKind() == Base::BuildId; } - -protected: - BuildIdSection(size_t HashSize); - size_t HashSize; - uint8_t *HashBuf = nullptr; -}; - -template -class BuildIdFastHash final : public BuildIdSection { -public: - BuildIdFastHash() : BuildIdSection(8) {} - void writeBuildId(ArrayRef Buf) override; -}; - -template class BuildIdMd5 final : public BuildIdSection { -public: - BuildIdMd5() : BuildIdSection(16) {} - void writeBuildId(ArrayRef Buf) override; -}; - -template class BuildIdSha1 final : public BuildIdSection { -public: - BuildIdSha1() : BuildIdSection(20) {} - void writeBuildId(ArrayRef Buf) override; -}; - -template class BuildIdUuid final : public BuildIdSection { -public: - BuildIdUuid() : BuildIdSection(16) {} - void writeBuildId(ArrayRef Buf) override; -}; - -template -class BuildIdHexstring final : public BuildIdSection { -public: - BuildIdHexstring(); - void writeBuildId(ArrayRef) override; -}; - // All output sections that are hadnled by the linker specially are // globally accessible. Writer initializes them, so don't use them // until Writer is initialized. template struct Out { typedef typename ELFT::uint uintX_t; typedef typename ELFT::Phdr Elf_Phdr; - static BuildIdSection *BuildId; static DynamicSection *Dynamic; static EhFrameHeader *EhFrameHdr; static EhOutputSection *EhFrame; @@ -862,7 +813,6 @@ template uint64_t getHeaderSize() { return Out::ElfHeader->getSize() + Out::ProgramHeaders->getSize(); } -template BuildIdSection *Out::BuildId; template DynamicSection *Out::Dynamic; template EhFrameHeader *Out::EhFrameHdr; template EhOutputSection *Out::EhFrame; diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp index c54e0173e9f5..93540d89c1cf 100644 --- a/lld/ELF/Writer.cpp +++ b/lld/ELF/Writer.cpp @@ -50,6 +50,7 @@ private: void copyLocalSymbols(); void addReservedSymbols(); + void addInputSec(InputSectionBase *S); void createSections(); void forEachRelSec(std::function &, const typename ELFT::Shdr &)> Fn); @@ -209,7 +210,6 @@ template void elf::writeResult() { VerDef.reset(new VersionDefinitionSection()); Out::Bss = &Bss; - Out::BuildId = BuildId.get(); Out::DynStrTab = DynStrTab.get(); Out::DynSymTab = DynSymTab.get(); Out::Dynamic = &Dynamic; @@ -241,6 +241,10 @@ template void elf::writeResult() { Out::InitArray = nullptr; Out::FiniArray = nullptr; + // Initialize linker generated sections + In::BuildId = BuildId.get(); + In::Sections = {BuildId.get()}; + Writer().run(); Out::Pool.clear(); } @@ -696,28 +700,29 @@ void Writer::forEachRelSec( } } -template void Writer::createSections() { - auto Add = [&](InputSectionBase *IS) { - if (isDiscarded(IS)) { - reportDiscarded(IS); - return; - } - OutputSectionBase *Sec; - bool IsNew; - StringRef OutsecName = getOutputSectionName(IS->Name); - std::tie(Sec, IsNew) = Factory.create(IS, OutsecName); - if (IsNew) - OutputSections.push_back(Sec); - Sec->addSection(IS); - }; +template +void Writer::addInputSec(InputSectionBase *IS) { + if (isDiscarded(IS)) { + reportDiscarded(IS); + return; + } + OutputSectionBase *Sec; + bool IsNew; + StringRef OutsecName = getOutputSectionName(IS->Name); + std::tie(Sec, IsNew) = Factory.create(IS, OutsecName); + if (IsNew) + OutputSections.push_back(Sec); + Sec->addSection(IS); +} +template void Writer::createSections() { for (elf::ObjectFile *F : Symtab::X->getObjectFiles()) for (InputSectionBase *IS : F->getSections()) - Add(IS); + addInputSec(IS); for (BinaryFile *F : Symtab::X->getBinaryFiles()) for (InputSectionData *ID : F->getSections()) - Add(cast>(ID)); + addInputSec(cast>(ID)); sortInitFini(findSection(".init_array")); sortInitFini(findSection(".fini_array")); @@ -847,6 +852,11 @@ template void Writer::finalizeSections() { // This function adds linker-created Out::* sections. addPredefinedSections(); + // Adds linker generated input sections to + // corresponding output sections. + for (InputSection *S : In::Sections) + addInputSec(S); + sortSections(); unsigned I = 1; @@ -855,6 +865,11 @@ template void Writer::finalizeSections() { Sec->setSHName(Out::ShStrTab->addString(Sec->getName())); } + // Finalize linker generated sections. + for (InputSection *S : In::Sections) + if (S && S->OutSec) + S->OutSec->assignOffsets(); + // Finalizers fix each section's size. // .dynsym is finalized early since that may fill up .gnu.hash. if (Out::DynSymTab) @@ -899,12 +914,6 @@ template void Writer::addPredefinedSections() { OutputSections.push_back(OS); }; - // A core file does not usually contain unmodified segments except - // the first page of the executable. Add the build ID section to beginning of - // the file so that the section is included in the first page. - if (Out::BuildId) - OutputSections.insert(OutputSections.begin(), Out::BuildId); - // Add .interp at first because some loaders want to see that section // on the first page of the executable file when loaded into memory. if (Out::Interp) @@ -1484,13 +1493,13 @@ template void Writer::writeSections() { } template void Writer::writeBuildId() { - if (!Out::BuildId) + if (!In::BuildId || !In::BuildId->OutSec) return; // Compute a hash of all sections of the output file. uint8_t *Start = Buffer->getBufferStart(); uint8_t *End = Start + FileSize; - Out::BuildId->writeBuildId({Start, End}); + In::BuildId->writeBuildId({Start, End}); } template void elf::writeResult(); diff --git a/lld/test/ELF/build-id.s b/lld/test/ELF/build-id.s index 6f832d53667b..7dd7872993bb 100644 --- a/lld/test/ELF/build-id.s +++ b/lld/test/ELF/build-id.s @@ -23,9 +23,9 @@ _start: .section .note.test, "a", @note .quad 42 +# DEFAULT: Contents of section .note.test: # DEFAULT: Contents of section .note.gnu.build-id: # DEFAULT-NEXT: 04000000 08000000 03000000 474e5500 ............GNU. -# DEFAULT: Contents of section .note.test: # MD5: Contents of section .note.gnu.build-id: # MD5-NEXT: 04000000 10000000 03000000 474e5500 ............GNU.