diff options
| author | Dimitry Andric <dim@FreeBSD.org> | 2021-02-16 20:13:02 +0000 |
|---|---|---|
| committer | Dimitry Andric <dim@FreeBSD.org> | 2021-02-16 20:13:02 +0000 |
| commit | b60736ec1405bb0a8dd40989f67ef4c93da068ab (patch) | |
| tree | 5c43fbb7c9fc45f0f87e0e6795a86267dbd12f9d /llvm/lib/ObjectYAML/ELFEmitter.cpp | |
| parent | cfca06d7963fa0909f90483b42a6d7d194d01e08 (diff) | |
Diffstat (limited to 'llvm/lib/ObjectYAML/ELFEmitter.cpp')
| -rw-r--r-- | llvm/lib/ObjectYAML/ELFEmitter.cpp | 675 |
1 files changed, 348 insertions, 327 deletions
diff --git a/llvm/lib/ObjectYAML/ELFEmitter.cpp b/llvm/lib/ObjectYAML/ELFEmitter.cpp index f9f2f128e2e8..e477a1b2b8f2 100644 --- a/llvm/lib/ObjectYAML/ELFEmitter.cpp +++ b/llvm/lib/ObjectYAML/ELFEmitter.cpp @@ -124,6 +124,11 @@ public: if (checkLimit(sizeof(T))) support::endian::write<T>(OS, Val, E); } + + void updateDataAt(uint64_t Pos, void *Data, size_t Size) { + assert(Pos >= InitialOffset && Pos + Size <= getOffset()); + memcpy(&Buf[Pos - InitialOffset], Data, Size); + } }; // Used to keep track of section and symbol names, so that in the YAML file @@ -168,15 +173,7 @@ struct Fragment { /// TODO: This class still has a ways to go before it is truly a "single /// point of truth". template <class ELFT> class ELFState { - typedef typename ELFT::Ehdr Elf_Ehdr; - typedef typename ELFT::Phdr Elf_Phdr; - typedef typename ELFT::Shdr Elf_Shdr; - typedef typename ELFT::Sym Elf_Sym; - typedef typename ELFT::Rel Elf_Rel; - typedef typename ELFT::Rela Elf_Rela; - typedef typename ELFT::Relr Elf_Relr; - typedef typename ELFT::Dyn Elf_Dyn; - typedef typename ELFT::uint uintX_t; + LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) enum class SymtabType { Static, Dynamic }; @@ -232,7 +229,7 @@ template <class ELFT> class ELFState { ArrayRef<typename ELFT::Shdr> SHeaders); void finalizeStrings(); - void writeELFHeader(raw_ostream &OS, uint64_t SHOff); + void writeELFHeader(raw_ostream &OS); void writeSectionContent(Elf_Shdr &SHeader, const ELFYAML::NoBitsSection &Section, ContiguousBlobAccumulator &CBA); @@ -245,7 +242,8 @@ template <class ELFT> class ELFState { void writeSectionContent(Elf_Shdr &SHeader, const ELFYAML::RelrSection &Section, ContiguousBlobAccumulator &CBA); - void writeSectionContent(Elf_Shdr &SHeader, const ELFYAML::Group &Group, + void writeSectionContent(Elf_Shdr &SHeader, + const ELFYAML::GroupSection &Group, ContiguousBlobAccumulator &CBA); void writeSectionContent(Elf_Shdr &SHeader, const ELFYAML::SymtabShndxSection &Shndx, @@ -260,6 +258,9 @@ template <class ELFT> class ELFState { const ELFYAML::VerdefSection &Section, ContiguousBlobAccumulator &CBA); void writeSectionContent(Elf_Shdr &SHeader, + const ELFYAML::ARMIndexTableSection &Section, + ContiguousBlobAccumulator &CBA); + void writeSectionContent(Elf_Shdr &SHeader, const ELFYAML::MipsABIFlags &Section, ContiguousBlobAccumulator &CBA); void writeSectionContent(Elf_Shdr &SHeader, @@ -269,6 +270,9 @@ template <class ELFT> class ELFState { const ELFYAML::StackSizesSection &Section, ContiguousBlobAccumulator &CBA); void writeSectionContent(Elf_Shdr &SHeader, + const ELFYAML::BBAddrMapSection &Section, + ContiguousBlobAccumulator &CBA); + void writeSectionContent(Elf_Shdr &SHeader, const ELFYAML::HashSection &Section, ContiguousBlobAccumulator &CBA); void writeSectionContent(Elf_Shdr &SHeader, @@ -331,12 +335,22 @@ ELFState<ELFT>::ELFState(ELFYAML::Object &D, yaml::ErrorHandler EH) std::make_unique<ELFYAML::Section>( ELFYAML::Chunk::ChunkKind::RawContent, /*IsImplicit=*/true)); - // We add a technical suffix for each unnamed section/fill. It does not affect - // the output, but allows us to map them by name in the code and report better - // error messages. StringSet<> DocSections; + ELFYAML::SectionHeaderTable *SecHdrTable = nullptr; for (size_t I = 0; I < Doc.Chunks.size(); ++I) { const std::unique_ptr<ELFYAML::Chunk> &C = Doc.Chunks[I]; + + // We might have an explicit section header table declaration. + if (auto S = dyn_cast<ELFYAML::SectionHeaderTable>(C.get())) { + if (SecHdrTable) + reportError("multiple section header tables are not allowed"); + SecHdrTable = S; + continue; + } + + // We add a technical suffix for each unnamed section/fill. It does not + // affect the output, but allows us to map them by name in the code and + // report better error messages. if (C->Name.empty()) { std::string NewName = ELFYAML::appendUniqueSuffix( /*Name=*/"", "index " + Twine(I)); @@ -355,11 +369,13 @@ ELFState<ELFT>::ELFState(ELFYAML::Object &D, yaml::ErrorHandler EH) if (Doc.Symbols) ImplicitSections.push_back(".symtab"); if (Doc.DWARF) - for (StringRef DebugSecName : Doc.DWARF->getUsedSectionNames()) { + for (StringRef DebugSecName : Doc.DWARF->getNonEmptySectionNames()) { std::string SecName = ("." + DebugSecName).str(); ImplicitSections.push_back(StringRef(SecName).copy(StringAlloc)); } - ImplicitSections.insert(ImplicitSections.end(), {".strtab", ".shstrtab"}); + ImplicitSections.insert(ImplicitSections.end(), {".strtab"}); + if (!SecHdrTable || !SecHdrTable->NoHeaders.getValueOr(false)) + ImplicitSections.insert(ImplicitSections.end(), {".shstrtab"}); // Insert placeholders for implicit sections that are not // defined explicitly in YAML. @@ -367,15 +383,37 @@ ELFState<ELFT>::ELFState(ELFYAML::Object &D, yaml::ErrorHandler EH) if (DocSections.count(SecName)) continue; - std::unique_ptr<ELFYAML::Chunk> Sec = std::make_unique<ELFYAML::Section>( + std::unique_ptr<ELFYAML::Section> Sec = std::make_unique<ELFYAML::Section>( ELFYAML::Chunk::ChunkKind::RawContent, true /*IsImplicit*/); Sec->Name = SecName; - Doc.Chunks.push_back(std::move(Sec)); + + if (SecName == ".dynsym") + Sec->Type = ELF::SHT_DYNSYM; + else if (SecName == ".symtab") + Sec->Type = ELF::SHT_SYMTAB; + else + Sec->Type = ELF::SHT_STRTAB; + + // When the section header table is explicitly defined at the end of the + // sections list, it is reasonable to assume that the user wants to reorder + // section headers, but still wants to place the section header table after + // all sections, like it normally happens. In this case we want to insert + // other implicit sections right before the section header table. + if (Doc.Chunks.back().get() == SecHdrTable) + Doc.Chunks.insert(Doc.Chunks.end() - 1, std::move(Sec)); + else + Doc.Chunks.push_back(std::move(Sec)); } + + // Insert the section header table implicitly at the end, when it is not + // explicitly defined. + if (!SecHdrTable) + Doc.Chunks.push_back( + std::make_unique<ELFYAML::SectionHeaderTable>(/*IsImplicit=*/true)); } template <class ELFT> -void ELFState<ELFT>::writeELFHeader(raw_ostream &OS, uint64_t SHOff) { +void ELFState<ELFT>::writeELFHeader(raw_ostream &OS) { using namespace llvm::ELF; Elf_Ehdr Header; @@ -390,7 +428,12 @@ void ELFState<ELFT>::writeELFHeader(raw_ostream &OS, uint64_t SHOff) { Header.e_ident[EI_OSABI] = Doc.Header.OSABI; Header.e_ident[EI_ABIVERSION] = Doc.Header.ABIVersion; Header.e_type = Doc.Header.Type; - Header.e_machine = Doc.Header.Machine; + + if (Doc.Header.Machine) + Header.e_machine = *Doc.Header.Machine; + else + Header.e_machine = EM_NONE; + Header.e_version = EV_CURRENT; Header.e_entry = Doc.Header.Entry; Header.e_flags = Doc.Header.Flags; @@ -420,34 +463,27 @@ void ELFState<ELFT>::writeELFHeader(raw_ostream &OS, uint64_t SHOff) { Header.e_shentsize = Doc.Header.EShEntSize ? (uint16_t)*Doc.Header.EShEntSize : sizeof(Elf_Shdr); - const bool NoShdrs = - Doc.SectionHeaders && Doc.SectionHeaders->NoHeaders.getValueOr(false); + const ELFYAML::SectionHeaderTable &SectionHeaders = + Doc.getSectionHeaderTable(); if (Doc.Header.EShOff) Header.e_shoff = *Doc.Header.EShOff; - else if (NoShdrs) - Header.e_shoff = 0; + else if (SectionHeaders.Offset) + Header.e_shoff = *SectionHeaders.Offset; else - Header.e_shoff = SHOff; + Header.e_shoff = 0; if (Doc.Header.EShNum) Header.e_shnum = *Doc.Header.EShNum; - else if (!Doc.SectionHeaders) - Header.e_shnum = Doc.getSections().size(); - else if (NoShdrs) - Header.e_shnum = 0; else - Header.e_shnum = - (Doc.SectionHeaders->Sections ? Doc.SectionHeaders->Sections->size() - : 0) + - /*Null section*/ 1; + Header.e_shnum = SectionHeaders.getNumHeaders(Doc.getSections().size()); if (Doc.Header.EShStrNdx) Header.e_shstrndx = *Doc.Header.EShStrNdx; - else if (NoShdrs || ExcludedSectionHeaders.count(".shstrtab")) - Header.e_shstrndx = 0; - else + else if (SectionHeaders.Offset && !ExcludedSectionHeaders.count(".shstrtab")) Header.e_shstrndx = SN2I.get(".shstrtab"); + else + Header.e_shstrndx = 0; OS.write((const char *)&Header, sizeof(Header)); } @@ -455,12 +491,16 @@ void ELFState<ELFT>::writeELFHeader(raw_ostream &OS, uint64_t SHOff) { template <class ELFT> void ELFState<ELFT>::initProgramHeaders(std::vector<Elf_Phdr> &PHeaders) { DenseMap<StringRef, ELFYAML::Fill *> NameToFill; - for (const std::unique_ptr<ELFYAML::Chunk> &D : Doc.Chunks) - if (auto S = dyn_cast<ELFYAML::Fill>(D.get())) + DenseMap<StringRef, size_t> NameToIndex; + for (size_t I = 0, E = Doc.Chunks.size(); I != E; ++I) { + if (auto S = dyn_cast<ELFYAML::Fill>(Doc.Chunks[I].get())) NameToFill[S->Name] = S; + NameToIndex[Doc.Chunks[I]->Name] = I + 1; + } std::vector<ELFYAML::Section *> Sections = Doc.getSections(); - for (ELFYAML::ProgramHeader &YamlPhdr : Doc.ProgramHeaders) { + for (size_t I = 0, E = Doc.ProgramHeaders.size(); I != E; ++I) { + ELFYAML::ProgramHeader &YamlPhdr = Doc.ProgramHeaders[I]; Elf_Phdr Phdr; zero(Phdr); Phdr.p_type = YamlPhdr.Type; @@ -469,22 +509,30 @@ void ELFState<ELFT>::initProgramHeaders(std::vector<Elf_Phdr> &PHeaders) { Phdr.p_paddr = YamlPhdr.PAddr; PHeaders.push_back(Phdr); - // Map Sections list to corresponding chunks. - for (const ELFYAML::SectionName &SecName : YamlPhdr.Sections) { - if (ELFYAML::Fill *Fill = NameToFill.lookup(SecName.Section)) { - YamlPhdr.Chunks.push_back(Fill); - continue; - } + if (!YamlPhdr.FirstSec && !YamlPhdr.LastSec) + continue; - unsigned Index; - if (SN2I.lookup(SecName.Section, Index)) { - YamlPhdr.Chunks.push_back(Sections[Index]); - continue; - } + // Get the index of the section, or 0 in the case when the section doesn't exist. + size_t First = NameToIndex[*YamlPhdr.FirstSec]; + if (!First) + reportError("unknown section or fill referenced: '" + *YamlPhdr.FirstSec + + "' by the 'FirstSec' key of the program header with index " + + Twine(I)); + size_t Last = NameToIndex[*YamlPhdr.LastSec]; + if (!Last) + reportError("unknown section or fill referenced: '" + *YamlPhdr.LastSec + + "' by the 'LastSec' key of the program header with index " + + Twine(I)); + if (!First || !Last) + continue; - reportError("unknown section or fill referenced: '" + SecName.Section + - "' by program header"); - } + if (First > Last) + reportError("program header with index " + Twine(I) + + ": the section index of " + *YamlPhdr.FirstSec + + " is greater than the index of " + *YamlPhdr.LastSec); + + for (size_t I = First; I <= Last; ++I) + YamlPhdr.Chunks.push_back(Doc.Chunks[I - 1].get()); } } @@ -504,14 +552,16 @@ unsigned ELFState<ELFT>::toSectionIndex(StringRef S, StringRef LocSec, return 0; } - if (!Doc.SectionHeaders || (Doc.SectionHeaders->NoHeaders && - !Doc.SectionHeaders->NoHeaders.getValue())) + const ELFYAML::SectionHeaderTable &SectionHeaders = + Doc.getSectionHeaderTable(); + if (SectionHeaders.IsImplicit || + (SectionHeaders.NoHeaders && !SectionHeaders.NoHeaders.getValue())) return Index; - assert(!Doc.SectionHeaders->NoHeaders.getValueOr(false) || - !Doc.SectionHeaders->Sections); + assert(!SectionHeaders.NoHeaders.getValueOr(false) || + !SectionHeaders.Sections); size_t FirstExcluded = - Doc.SectionHeaders->Sections ? Doc.SectionHeaders->Sections->size() : 0; + SectionHeaders.Sections ? SectionHeaders.Sections->size() : 0; if (Index >= FirstExcluded) { if (LocSym.empty()) reportError("unable to link '" + LocSec + "' to excluded section '" + S + @@ -542,6 +592,8 @@ template <class ELFT> static void overrideFields(ELFYAML::Section *From, typename ELFT::Shdr &To) { if (!From) return; + if (From->ShAddrAlign) + To.sh_addralign = *From->ShAddrAlign; if (From->ShFlags) To.sh_flags = *From->ShFlags; if (From->ShName) @@ -550,6 +602,8 @@ static void overrideFields(ELFYAML::Section *From, typename ELFT::Shdr &To) { To.sh_offset = *From->ShOffset; if (From->ShSize) To.sh_size = *From->ShSize; + if (From->ShType) + To.sh_type = *From->ShType; } template <class ELFT> @@ -619,6 +673,45 @@ uint64_t ELFState<ELFT>::getSectionNameOffset(StringRef Name) { return DotShStrtab.getOffset(Name); } +static uint64_t writeContent(ContiguousBlobAccumulator &CBA, + const Optional<yaml::BinaryRef> &Content, + const Optional<llvm::yaml::Hex64> &Size) { + size_t ContentSize = 0; + if (Content) { + CBA.writeAsBinary(*Content); + ContentSize = Content->binary_size(); + } + + if (!Size) + return ContentSize; + + CBA.writeZeros(*Size - ContentSize); + return *Size; +} + +static StringRef getDefaultLinkSec(unsigned SecType) { + switch (SecType) { + case ELF::SHT_REL: + case ELF::SHT_RELA: + case ELF::SHT_GROUP: + case ELF::SHT_LLVM_CALL_GRAPH_PROFILE: + case ELF::SHT_LLVM_ADDRSIG: + return ".symtab"; + case ELF::SHT_GNU_versym: + case ELF::SHT_HASH: + case ELF::SHT_GNU_HASH: + return ".dynsym"; + case ELF::SHT_DYNSYM: + case ELF::SHT_GNU_verdef: + case ELF::SHT_GNU_verneed: + return ".dynstr"; + case ELF::SHT_SYMTAB: + return ".strtab"; + default: + return ""; + } +} + template <class ELFT> void ELFState<ELFT>::initSectionHeaders(std::vector<Elf_Shdr> &SHeaders, ContiguousBlobAccumulator &CBA) { @@ -634,16 +727,51 @@ void ELFState<ELFT>::initSectionHeaders(std::vector<Elf_Shdr> &SHeaders, continue; } + if (ELFYAML::SectionHeaderTable *S = + dyn_cast<ELFYAML::SectionHeaderTable>(D.get())) { + if (S->NoHeaders.getValueOr(false)) + continue; + + if (!S->Offset) + S->Offset = alignToOffset(CBA, sizeof(typename ELFT::uint), + /*Offset=*/None); + else + S->Offset = alignToOffset(CBA, /*Align=*/1, S->Offset); + + uint64_t Size = S->getNumHeaders(SHeaders.size()) * sizeof(Elf_Shdr); + // The full section header information might be not available here, so + // fill the space with zeroes as a placeholder. + CBA.writeZeros(Size); + LocationCounter += Size; + continue; + } + ELFYAML::Section *Sec = cast<ELFYAML::Section>(D.get()); - bool IsFirstUndefSection = D == Doc.Chunks.front(); + bool IsFirstUndefSection = Sec == Doc.getSections().front(); if (IsFirstUndefSection && Sec->IsImplicit) continue; + Elf_Shdr &SHeader = SHeaders[SN2I.get(Sec->Name)]; + if (Sec->Link) { + SHeader.sh_link = toSectionIndex(*Sec->Link, Sec->Name); + } else { + StringRef LinkSec = getDefaultLinkSec(Sec->Type); + unsigned Link = 0; + if (!LinkSec.empty() && !ExcludedSectionHeaders.count(LinkSec) && + SN2I.lookup(LinkSec, Link)) + SHeader.sh_link = Link; + } + + if (Sec->EntSize) + SHeader.sh_entsize = *Sec->EntSize; + else + SHeader.sh_entsize = ELFYAML::getDefaultShEntSize<ELFT>( + Doc.Header.Machine.getValueOr(ELF::EM_NONE), Sec->Type, Sec->Name); + // We have a few sections like string or symbol tables that are usually // added implicitly to the end. However, if they are explicitly specified // in the YAML, we need to write them here. This ensures the file offset // remains correct. - Elf_Shdr &SHeader = SHeaders[SN2I.get(Sec->Name)]; if (initImplicitHeader(CBA, SHeader, Sec->Name, Sec->IsImplicit ? nullptr : Sec)) continue; @@ -665,9 +793,6 @@ void ELFState<ELFT>::initSectionHeaders(std::vector<Elf_Shdr> &SHeaders, assignSectionAddress(SHeader, Sec); - if (!Sec->Link.empty()) - SHeader.sh_link = toSectionIndex(Sec->Link, Sec->Name); - if (IsFirstUndefSection) { if (auto RawSec = dyn_cast<ELFYAML::RawContentSection>(Sec)) { // We do not write any content for special SHN_UNDEF section. @@ -676,9 +801,16 @@ void ELFState<ELFT>::initSectionHeaders(std::vector<Elf_Shdr> &SHeaders, if (RawSec->Info) SHeader.sh_info = *RawSec->Info; } - if (Sec->EntSize) - SHeader.sh_entsize = *Sec->EntSize; - } else if (auto S = dyn_cast<ELFYAML::RawContentSection>(Sec)) { + + LocationCounter += SHeader.sh_size; + overrideFields<ELFT>(Sec, SHeader); + continue; + } + + if (!isa<ELFYAML::NoBitsSection>(Sec) && (Sec->Content || Sec->Size)) + SHeader.sh_size = writeContent(CBA, Sec->Content, Sec->Size); + + if (auto S = dyn_cast<ELFYAML::RawContentSection>(Sec)) { writeSectionContent(SHeader, *S, CBA); } else if (auto S = dyn_cast<ELFYAML::SymtabShndxSection>(Sec)) { writeSectionContent(SHeader, *S, CBA); @@ -686,7 +818,9 @@ void ELFState<ELFT>::initSectionHeaders(std::vector<Elf_Shdr> &SHeaders, writeSectionContent(SHeader, *S, CBA); } else if (auto S = dyn_cast<ELFYAML::RelrSection>(Sec)) { writeSectionContent(SHeader, *S, CBA); - } else if (auto S = dyn_cast<ELFYAML::Group>(Sec)) { + } else if (auto S = dyn_cast<ELFYAML::GroupSection>(Sec)) { + writeSectionContent(SHeader, *S, CBA); + } else if (auto S = dyn_cast<ELFYAML::ARMIndexTableSection>(Sec)) { writeSectionContent(SHeader, *S, CBA); } else if (auto S = dyn_cast<ELFYAML::MipsABIFlags>(Sec)) { writeSectionContent(SHeader, *S, CBA); @@ -716,6 +850,8 @@ void ELFState<ELFT>::initSectionHeaders(std::vector<Elf_Shdr> &SHeaders, writeSectionContent(SHeader, *S, CBA); } else if (auto S = dyn_cast<ELFYAML::CallGraphProfileSection>(Sec)) { writeSectionContent(SHeader, *S, CBA); + } else if (auto S = dyn_cast<ELFYAML::BBAddrMapSection>(Sec)) { + writeSectionContent(SHeader, *S, CBA); } else { llvm_unreachable("Unknown section type"); } @@ -755,22 +891,6 @@ static size_t findFirstNonGlobal(ArrayRef<ELFYAML::Symbol> Symbols) { return Symbols.size(); } -static uint64_t writeContent(ContiguousBlobAccumulator &CBA, - const Optional<yaml::BinaryRef> &Content, - const Optional<llvm::yaml::Hex64> &Size) { - size_t ContentSize = 0; - if (Content) { - CBA.writeAsBinary(*Content); - ContentSize = Content->binary_size(); - } - - if (!Size) - return ContentSize; - - CBA.writeZeros(*Size - ContentSize); - return *Size; -} - template <class ELFT> std::vector<typename ELFT::Sym> ELFState<ELFT>::toELFSymbols(ArrayRef<ELFYAML::Symbol> Symbols, @@ -791,14 +911,14 @@ ELFState<ELFT>::toELFSymbols(ArrayRef<ELFYAML::Symbol> Symbols, Symbol.st_name = Strtab.getOffset(ELFYAML::dropUniqueSuffix(Sym.Name)); Symbol.setBindingAndType(Sym.Binding, Sym.Type); - if (!Sym.Section.empty()) - Symbol.st_shndx = toSectionIndex(Sym.Section, "", Sym.Name); + if (Sym.Section) + Symbol.st_shndx = toSectionIndex(*Sym.Section, "", Sym.Name); else if (Sym.Index) Symbol.st_shndx = *Sym.Index; - Symbol.st_value = Sym.Value; + Symbol.st_value = Sym.Value.getValueOr(yaml::Hex64(0)); Symbol.st_other = Sym.Other ? *Sym.Other : 0; - Symbol.st_size = Sym.Size; + Symbol.st_size = Sym.Size.getValueOr(yaml::Hex64(0)); } return Ret; @@ -834,7 +954,6 @@ void ELFState<ELFT>::initSymtabSectionHeader(Elf_Shdr &SHeader, } } - zero(SHeader); SHeader.sh_name = getSectionNameOffset(IsStatic ? ".symtab" : ".dynsym"); if (YAMLSec) @@ -842,26 +961,6 @@ void ELFState<ELFT>::initSymtabSectionHeader(Elf_Shdr &SHeader, else SHeader.sh_type = IsStatic ? ELF::SHT_SYMTAB : ELF::SHT_DYNSYM; - if (RawSec && !RawSec->Link.empty()) { - // If the Link field is explicitly defined in the document, - // we should use it. - SHeader.sh_link = toSectionIndex(RawSec->Link, RawSec->Name); - } else { - // When we describe the .dynsym section in the document explicitly, it is - // allowed to omit the "DynamicSymbols" tag. In this case .dynstr is not - // added implicitly and we should be able to leave the Link zeroed if - // .dynstr is not defined. - unsigned Link = 0; - if (IsStatic) { - if (!ExcludedSectionHeaders.count(".strtab")) - Link = SN2I.get(".strtab"); - } else { - if (!ExcludedSectionHeaders.count(".dynstr")) - SN2I.lookup(".dynstr", Link); - } - SHeader.sh_link = Link; - } - if (YAMLSec && YAMLSec->Flags) SHeader.sh_flags = *YAMLSec->Flags; else if (!IsStatic) @@ -871,14 +970,12 @@ void ELFState<ELFT>::initSymtabSectionHeader(Elf_Shdr &SHeader, // then we should set the fields requested. SHeader.sh_info = (RawSec && RawSec->Info) ? (unsigned)(*RawSec->Info) : findFirstNonGlobal(Symbols) + 1; - SHeader.sh_entsize = (YAMLSec && YAMLSec->EntSize) - ? (uint64_t)(*YAMLSec->EntSize) - : sizeof(Elf_Sym); SHeader.sh_addralign = YAMLSec ? (uint64_t)YAMLSec->AddressAlign : 8; assignSectionAddress(SHeader, YAMLSec); - SHeader.sh_offset = alignToOffset(CBA, SHeader.sh_addralign, /*Offset=*/None); + SHeader.sh_offset = + alignToOffset(CBA, SHeader.sh_addralign, RawSec ? RawSec->Offset : None); if (RawSec && (RawSec->Content || RawSec->Size)) { assert(Symbols.empty()); @@ -897,7 +994,6 @@ void ELFState<ELFT>::initStrtabSectionHeader(Elf_Shdr &SHeader, StringRef Name, StringTableBuilder &STB, ContiguousBlobAccumulator &CBA, ELFYAML::Section *YAMLSec) { - zero(SHeader); SHeader.sh_name = getSectionNameOffset(Name); SHeader.sh_type = YAMLSec ? YAMLSec->Type : ELF::SHT_STRTAB; SHeader.sh_addralign = YAMLSec ? (uint64_t)YAMLSec->AddressAlign : 1; @@ -905,7 +1001,8 @@ void ELFState<ELFT>::initStrtabSectionHeader(Elf_Shdr &SHeader, StringRef Name, ELFYAML::RawContentSection *RawSec = dyn_cast_or_null<ELFYAML::RawContentSection>(YAMLSec); - SHeader.sh_offset = alignToOffset(CBA, SHeader.sh_addralign, /*Offset=*/None); + SHeader.sh_offset = alignToOffset(CBA, SHeader.sh_addralign, + YAMLSec ? YAMLSec->Offset : None); if (RawSec && (RawSec->Content || RawSec->Size)) { SHeader.sh_size = writeContent(CBA, RawSec->Content, RawSec->Size); @@ -915,9 +1012,6 @@ void ELFState<ELFT>::initStrtabSectionHeader(Elf_Shdr &SHeader, StringRef Name, SHeader.sh_size = STB.getSize(); } - if (YAMLSec && YAMLSec->EntSize) - SHeader.sh_entsize = *YAMLSec->EntSize; - if (RawSec && RawSec->Info) SHeader.sh_info = *RawSec->Info; @@ -930,7 +1024,7 @@ void ELFState<ELFT>::initStrtabSectionHeader(Elf_Shdr &SHeader, StringRef Name, } static bool shouldEmitDWARF(DWARFYAML::Data &DWARF, StringRef Name) { - SetVector<StringRef> DebugSecNames = DWARF.getUsedSectionNames(); + SetVector<StringRef> DebugSecNames = DWARF.getNonEmptySectionNames(); return Name.consume_front(".") && DebugSecNames.count(Name); } @@ -946,37 +1040,9 @@ Expected<uint64_t> emitDWARF(typename ELFT::Shdr &SHeader, StringRef Name, return 0; uint64_t BeginOffset = CBA.tell(); - Error Err = Error::success(); - cantFail(std::move(Err)); - - if (Name == ".debug_str") - Err = DWARFYAML::emitDebugStr(*OS, DWARF); - else if (Name == ".debug_aranges") - Err = DWARFYAML::emitDebugAranges(*OS, DWARF); - else if (Name == ".debug_ranges") - Err = DWARFYAML::emitDebugRanges(*OS, DWARF); - else if (Name == ".debug_line") - Err = DWARFYAML::emitDebugLine(*OS, DWARF); - else if (Name == ".debug_addr") - Err = DWARFYAML::emitDebugAddr(*OS, DWARF); - else if (Name == ".debug_abbrev") - Err = DWARFYAML::emitDebugAbbrev(*OS, DWARF); - else if (Name == ".debug_info") - Err = DWARFYAML::emitDebugInfo(*OS, DWARF); - else if (Name == ".debug_pubnames") - Err = DWARFYAML::emitPubSection(*OS, *DWARF.PubNames, DWARF.IsLittleEndian); - else if (Name == ".debug_pubtypes") - Err = DWARFYAML::emitPubSection(*OS, *DWARF.PubTypes, DWARF.IsLittleEndian); - else if (Name == ".debug_gnu_pubnames") - Err = DWARFYAML::emitPubSection(*OS, *DWARF.GNUPubNames, - DWARF.IsLittleEndian, /*IsGNUStyle=*/true); - else if (Name == ".debug_gnu_pubtypes") - Err = DWARFYAML::emitPubSection(*OS, *DWARF.GNUPubTypes, - DWARF.IsLittleEndian, /*IsGNUStyle=*/true); - else - llvm_unreachable("unexpected emitDWARF() call"); - if (Err) + auto EmitFunc = DWARFYAML::getDWARFEmitterByName(Name.substr(1)); + if (Error Err = EmitFunc(*OS, DWARF)) return std::move(Err); return CBA.tell() - BeginOffset; @@ -986,7 +1052,6 @@ template <class ELFT> void ELFState<ELFT>::initDWARFSectionHeader(Elf_Shdr &SHeader, StringRef Name, ContiguousBlobAccumulator &CBA, ELFYAML::Section *YAMLSec) { - zero(SHeader); SHeader.sh_name = getSectionNameOffset(ELFYAML::dropUniqueSuffix(Name)); SHeader.sh_type = YAMLSec ? YAMLSec->Type : ELF::SHT_PROGBITS; SHeader.sh_addralign = YAMLSec ? (uint64_t)YAMLSec->AddressAlign : 1; @@ -1013,11 +1078,6 @@ void ELFState<ELFT>::initDWARFSectionHeader(Elf_Shdr &SHeader, StringRef Name, llvm_unreachable("debug sections can only be initialized via the 'DWARF' " "entry or a RawContentSection"); - if (YAMLSec && YAMLSec->EntSize) - SHeader.sh_entsize = *YAMLSec->EntSize; - else if (Name == ".debug_str") - SHeader.sh_entsize = 1; - if (RawSec && RawSec->Info) SHeader.sh_info = *RawSec->Info; @@ -1026,9 +1086,6 @@ void ELFState<ELFT>::initDWARFSectionHeader(Elf_Shdr &SHeader, StringRef Name, else if (Name == ".debug_str") SHeader.sh_flags = ELF::SHF_MERGE | ELF::SHF_STRINGS; - if (YAMLSec && !YAMLSec->Link.empty()) - SHeader.sh_link = toSectionIndex(YAMLSec->Link, Name); - assignSectionAddress(SHeader, YAMLSec); } @@ -1120,8 +1177,8 @@ void ELFState<ELFT>::setProgramHeaderLayout(std::vector<Elf_Phdr> &PHeaders, } } -static bool shouldAllocateFileSpace(ArrayRef<ELFYAML::ProgramHeader> Phdrs, - const ELFYAML::NoBitsSection &S) { +bool llvm::ELFYAML::shouldAllocateFileSpace( + ArrayRef<ELFYAML::ProgramHeader> Phdrs, const ELFYAML::NoBitsSection &S) { for (const ELFYAML::ProgramHeader &PH : Phdrs) { auto It = llvm::find_if( PH.Chunks, [&](ELFYAML::Chunk *C) { return C->Name == S.Name; }); @@ -1138,34 +1195,30 @@ template <class ELFT> void ELFState<ELFT>::writeSectionContent(Elf_Shdr &SHeader, const ELFYAML::NoBitsSection &S, ContiguousBlobAccumulator &CBA) { - // SHT_NOBITS sections do not have any content to write. - SHeader.sh_entsize = 0; - SHeader.sh_size = S.Size; + if (!S.Size) + return; + + SHeader.sh_size = *S.Size; // When a nobits section is followed by a non-nobits section or fill // in the same segment, we allocate the file space for it. This behavior // matches linkers. if (shouldAllocateFileSpace(Doc.ProgramHeaders, S)) - CBA.writeZeros(S.Size); + CBA.writeZeros(*S.Size); } template <class ELFT> void ELFState<ELFT>::writeSectionContent( Elf_Shdr &SHeader, const ELFYAML::RawContentSection &Section, ContiguousBlobAccumulator &CBA) { - SHeader.sh_size = writeContent(CBA, Section.Content, Section.Size); - - if (Section.EntSize) - SHeader.sh_entsize = *Section.EntSize; - if (Section.Info) SHeader.sh_info = *Section.Info; } -static bool isMips64EL(const ELFYAML::Object &Doc) { - return Doc.Header.Machine == ELFYAML::ELF_EM(llvm::ELF::EM_MIPS) && - Doc.Header.Class == ELFYAML::ELF_ELFCLASS(ELF::ELFCLASS64) && - Doc.Header.Data == ELFYAML::ELF_ELFDATA(ELF::ELFDATA2LSB); +static bool isMips64EL(const ELFYAML::Object &Obj) { + return Obj.getMachine() == llvm::ELF::EM_MIPS && + Obj.Header.Class == ELFYAML::ELF_ELFCLASS(ELF::ELFCLASS64) && + Obj.Header.Data == ELFYAML::ELF_ELFDATA(ELF::ELFDATA2LSB); } template <class ELFT> @@ -1176,27 +1229,17 @@ void ELFState<ELFT>::writeSectionContent( Section.Type == llvm::ELF::SHT_RELA) && "Section type is not SHT_REL nor SHT_RELA"); - bool IsRela = Section.Type == llvm::ELF::SHT_RELA; - if (Section.EntSize) - SHeader.sh_entsize = *Section.EntSize; - else - SHeader.sh_entsize = IsRela ? sizeof(Elf_Rela) : sizeof(Elf_Rel); - SHeader.sh_size = (IsRela ? sizeof(Elf_Rela) : sizeof(Elf_Rel)) * - Section.Relocations.size(); - - // For relocation section set link to .symtab by default. - unsigned Link = 0; - if (Section.Link.empty() && !ExcludedSectionHeaders.count(".symtab") && - SN2I.lookup(".symtab", Link)) - SHeader.sh_link = Link; - if (!Section.RelocatableSec.empty()) SHeader.sh_info = toSectionIndex(Section.RelocatableSec, Section.Name); - for (const auto &Rel : Section.Relocations) { - unsigned SymIdx = Rel.Symbol ? toSymbolIndex(*Rel.Symbol, Section.Name, - Section.Link == ".dynsym") - : 0; + if (!Section.Relocations) + return; + + const bool IsRela = Section.Type == llvm::ELF::SHT_RELA; + for (const ELFYAML::Relocation &Rel : *Section.Relocations) { + const bool IsDynamic = Section.Link && (*Section.Link == ".dynsym"); + unsigned SymIdx = + Rel.Symbol ? toSymbolIndex(*Rel.Symbol, Section.Name, IsDynamic) : 0; if (IsRela) { Elf_Rela REntry; zero(REntry); @@ -1212,20 +1255,15 @@ void ELFState<ELFT>::writeSectionContent( CBA.write((const char *)&REntry, sizeof(REntry)); } } + + SHeader.sh_size = (IsRela ? sizeof(Elf_Rela) : sizeof(Elf_Rel)) * + Section.Relocations->size(); } template <class ELFT> void ELFState<ELFT>::writeSectionContent(Elf_Shdr &SHeader, const ELFYAML::RelrSection &Section, ContiguousBlobAccumulator &CBA) { - SHeader.sh_entsize = - Section.EntSize ? uint64_t(*Section.EntSize) : sizeof(Elf_Relr); - - if (Section.Content) { - SHeader.sh_size = writeContent(CBA, Section.Content, None); - return; - } - if (!Section.Entries) return; @@ -1243,33 +1281,34 @@ template <class ELFT> void ELFState<ELFT>::writeSectionContent( Elf_Shdr &SHeader, const ELFYAML::SymtabShndxSection &Shndx, ContiguousBlobAccumulator &CBA) { - for (uint32_t E : Shndx.Entries) - CBA.write<uint32_t>(E, ELFT::TargetEndianness); + if (Shndx.Content || Shndx.Size) { + SHeader.sh_size = writeContent(CBA, Shndx.Content, Shndx.Size); + return; + } + + if (!Shndx.Entries) + return; - SHeader.sh_entsize = Shndx.EntSize ? (uint64_t)*Shndx.EntSize : 4; - SHeader.sh_size = Shndx.Entries.size() * SHeader.sh_entsize; + for (uint32_t E : *Shndx.Entries) + CBA.write<uint32_t>(E, ELFT::TargetEndianness); + SHeader.sh_size = Shndx.Entries->size() * SHeader.sh_entsize; } template <class ELFT> void ELFState<ELFT>::writeSectionContent(Elf_Shdr &SHeader, - const ELFYAML::Group &Section, + const ELFYAML::GroupSection &Section, ContiguousBlobAccumulator &CBA) { assert(Section.Type == llvm::ELF::SHT_GROUP && "Section type is not SHT_GROUP"); - unsigned Link = 0; - if (Section.Link.empty() && !ExcludedSectionHeaders.count(".symtab") && - SN2I.lookup(".symtab", Link)) - SHeader.sh_link = Link; - - SHeader.sh_entsize = 4; - SHeader.sh_size = SHeader.sh_entsize * Section.Members.size(); - if (Section.Signature) SHeader.sh_info = toSymbolIndex(*Section.Signature, Section.Name, /*IsDynamic=*/false); - for (const ELFYAML::SectionOrType &Member : Section.Members) { + if (!Section.Members) + return; + + for (const ELFYAML::SectionOrType &Member : *Section.Members) { unsigned int SectionIndex = 0; if (Member.sectionNameOrType == "GRP_COMDAT") SectionIndex = llvm::ELF::GRP_COMDAT; @@ -1277,27 +1316,30 @@ void ELFState<ELFT>::writeSectionContent(Elf_Shdr &SHeader, SectionIndex = toSectionIndex(Member.sectionNameOrType, Section.Name); CBA.write<uint32_t>(SectionIndex, ELFT::TargetEndianness); } + SHeader.sh_size = SHeader.sh_entsize * Section.Members->size(); } template <class ELFT> void ELFState<ELFT>::writeSectionContent(Elf_Shdr &SHeader, const ELFYAML::SymverSection &Section, ContiguousBlobAccumulator &CBA) { - for (uint16_t Version : Section.Entries) - CBA.write<uint16_t>(Version, ELFT::TargetEndianness); + if (!Section.Entries) + return; - SHeader.sh_entsize = Section.EntSize ? (uint64_t)*Section.EntSize : 2; - SHeader.sh_size = Section.Entries.size() * SHeader.sh_entsize; + for (uint16_t Version : *Section.Entries) + CBA.write<uint16_t>(Version, ELFT::TargetEndianness); + SHeader.sh_size = Section.Entries->size() * SHeader.sh_entsize; } template <class ELFT> void ELFState<ELFT>::writeSectionContent( Elf_Shdr &SHeader, const ELFYAML::StackSizesSection &Section, ContiguousBlobAccumulator &CBA) { - if (Section.Content || Section.Size) { - SHeader.sh_size = writeContent(CBA, Section.Content, Section.Size); + if (!Section.Entries) + return; + + if (!Section.Entries) return; - } for (const ELFYAML::StackSizeEntry &E : *Section.Entries) { CBA.write<uintX_t>(E.Address, ELFT::TargetEndianness); @@ -1307,13 +1349,31 @@ void ELFState<ELFT>::writeSectionContent( template <class ELFT> void ELFState<ELFT>::writeSectionContent( - Elf_Shdr &SHeader, const ELFYAML::LinkerOptionsSection &Section, + Elf_Shdr &SHeader, const ELFYAML::BBAddrMapSection &Section, ContiguousBlobAccumulator &CBA) { - if (Section.Content) { - SHeader.sh_size = writeContent(CBA, Section.Content, None); + if (!Section.Entries) return; + + for (const ELFYAML::BBAddrMapEntry &E : *Section.Entries) { + // Write the address of the function. + CBA.write<uintX_t>(E.Address, ELFT::TargetEndianness); + // Write number of BBEntries (number of basic blocks in the function). + size_t NumBlocks = E.BBEntries ? E.BBEntries->size() : 0; + SHeader.sh_size += sizeof(uintX_t) + CBA.writeULEB128(NumBlocks); + if (!NumBlocks) + continue; + // Write all BBEntries. + for (const ELFYAML::BBAddrMapEntry::BBEntry &BBE : *E.BBEntries) + SHeader.sh_size += CBA.writeULEB128(BBE.AddressOffset) + + CBA.writeULEB128(BBE.Size) + + CBA.writeULEB128(BBE.Metadata); } +} +template <class ELFT> +void ELFState<ELFT>::writeSectionContent( + Elf_Shdr &SHeader, const ELFYAML::LinkerOptionsSection &Section, + ContiguousBlobAccumulator &CBA) { if (!Section.Options) return; @@ -1330,11 +1390,6 @@ template <class ELFT> void ELFState<ELFT>::writeSectionContent( Elf_Shdr &SHeader, const ELFYAML::DependentLibrariesSection &Section, ContiguousBlobAccumulator &CBA) { - if (Section.Content) { - SHeader.sh_size = writeContent(CBA, Section.Content, None); - return; - } - if (!Section.Libs) return; @@ -1373,21 +1428,6 @@ template <class ELFT> void ELFState<ELFT>::writeSectionContent( Elf_Shdr &SHeader, const ELFYAML::CallGraphProfileSection &Section, ContiguousBlobAccumulator &CBA) { - if (Section.EntSize) - SHeader.sh_entsize = *Section.EntSize; - else - SHeader.sh_entsize = 16; - - unsigned Link = 0; - if (Section.Link.empty() && !ExcludedSectionHeaders.count(".symtab") && - SN2I.lookup(".symtab", Link)) - SHeader.sh_link = Link; - - if (Section.Content) { - SHeader.sh_size = writeContent(CBA, Section.Content, None); - return; - } - if (!Section.Entries) return; @@ -1406,15 +1446,11 @@ template <class ELFT> void ELFState<ELFT>::writeSectionContent(Elf_Shdr &SHeader, const ELFYAML::HashSection &Section, ContiguousBlobAccumulator &CBA) { - unsigned Link = 0; - if (Section.Link.empty() && !ExcludedSectionHeaders.count(".dynsym") && - SN2I.lookup(".dynsym", Link)) - SHeader.sh_link = Link; + if (!Section.Bucket) + return; - if (Section.Content || Section.Size) { - SHeader.sh_size = writeContent(CBA, Section.Content, Section.Size); + if (!Section.Bucket) return; - } CBA.write<uint32_t>( Section.NBucket.getValueOr(llvm::yaml::Hex64(Section.Bucket->size())), @@ -1435,15 +1471,11 @@ template <class ELFT> void ELFState<ELFT>::writeSectionContent(Elf_Shdr &SHeader, const ELFYAML::VerdefSection &Section, ContiguousBlobAccumulator &CBA) { - typedef typename ELFT::Verdef Elf_Verdef; - typedef typename ELFT::Verdaux Elf_Verdaux; - - SHeader.sh_info = Section.Info; - if (Section.Content) { - SHeader.sh_size = writeContent(CBA, Section.Content, None); - return; - } + if (Section.Info) + SHeader.sh_info = *Section.Info; + else if (Section.Entries) + SHeader.sh_info = Section.Entries->size(); if (!Section.Entries) return; @@ -1453,10 +1485,10 @@ void ELFState<ELFT>::writeSectionContent(Elf_Shdr &SHeader, const ELFYAML::VerdefEntry &E = (*Section.Entries)[I]; Elf_Verdef VerDef; - VerDef.vd_version = E.Version; - VerDef.vd_flags = E.Flags; - VerDef.vd_ndx = E.VersionNdx; - VerDef.vd_hash = E.Hash; + VerDef.vd_version = E.Version.getValueOr(1); + VerDef.vd_flags = E.Flags.getValueOr(0); + VerDef.vd_ndx = E.VersionNdx.getValueOr(0); + VerDef.vd_hash = E.Hash.getValueOr(0); VerDef.vd_aux = sizeof(Elf_Verdef); VerDef.vd_cnt = E.VerNames.size(); if (I == Section.Entries->size() - 1) @@ -1485,15 +1517,10 @@ template <class ELFT> void ELFState<ELFT>::writeSectionContent(Elf_Shdr &SHeader, const ELFYAML::VerneedSection &Section, ContiguousBlobAccumulator &CBA) { - typedef typename ELFT::Verneed Elf_Verneed; - typedef typename ELFT::Vernaux Elf_Vernaux; - - SHeader.sh_info = Section.Info; - - if (Section.Content) { - SHeader.sh_size = writeContent(CBA, Section.Content, None); - return; - } + if (Section.Info) + SHeader.sh_info = *Section.Info; + else if (Section.VerneedV) + SHeader.sh_info = Section.VerneedV->size(); if (!Section.VerneedV) return; @@ -1535,6 +1562,20 @@ void ELFState<ELFT>::writeSectionContent(Elf_Shdr &SHeader, } template <class ELFT> +void ELFState<ELFT>::writeSectionContent( + Elf_Shdr &SHeader, const ELFYAML::ARMIndexTableSection &Section, + ContiguousBlobAccumulator &CBA) { + if (!Section.Entries) + return; + + for (const ELFYAML::ARMIndexTableEntry &E : *Section.Entries) { + CBA.write<uint32_t>(E.Offset, ELFT::TargetEndianness); + CBA.write<uint32_t>(E.Value, ELFT::TargetEndianness); + } + SHeader.sh_size = Section.Entries->size() * 8; +} + +template <class ELFT> void ELFState<ELFT>::writeSectionContent(Elf_Shdr &SHeader, const ELFYAML::MipsABIFlags &Section, ContiguousBlobAccumulator &CBA) { @@ -1543,7 +1584,6 @@ void ELFState<ELFT>::writeSectionContent(Elf_Shdr &SHeader, object::Elf_Mips_ABIFlags<ELFT> Flags; zero(Flags); - SHeader.sh_entsize = sizeof(Flags); SHeader.sh_size = SHeader.sh_entsize; Flags.version = Section.Version; @@ -1567,41 +1607,25 @@ void ELFState<ELFT>::writeSectionContent(Elf_Shdr &SHeader, assert(Section.Type == llvm::ELF::SHT_DYNAMIC && "Section type is not SHT_DYNAMIC"); - if (!Section.Entries.empty() && Section.Content) - reportError("cannot specify both raw content and explicit entries " - "for dynamic section '" + - Section.Name + "'"); - - if (Section.Content) - SHeader.sh_size = Section.Content->binary_size(); - else - SHeader.sh_size = 2 * sizeof(uintX_t) * Section.Entries.size(); - if (Section.EntSize) - SHeader.sh_entsize = *Section.EntSize; - else - SHeader.sh_entsize = sizeof(Elf_Dyn); + if (!Section.Entries) + return; - for (const ELFYAML::DynamicEntry &DE : Section.Entries) { + for (const ELFYAML::DynamicEntry &DE : *Section.Entries) { CBA.write<uintX_t>(DE.Tag, ELFT::TargetEndianness); CBA.write<uintX_t>(DE.Val, ELFT::TargetEndianness); } - if (Section.Content) - CBA.writeAsBinary(*Section.Content); + SHeader.sh_size = 2 * sizeof(uintX_t) * Section.Entries->size(); } template <class ELFT> void ELFState<ELFT>::writeSectionContent(Elf_Shdr &SHeader, const ELFYAML::AddrsigSection &Section, ContiguousBlobAccumulator &CBA) { - unsigned Link = 0; - if (Section.Link.empty() && !ExcludedSectionHeaders.count(".symtab") && - SN2I.lookup(".symtab", Link)) - SHeader.sh_link = Link; + if (!Section.Symbols) + return; - if (Section.Content || Section.Size) { - SHeader.sh_size = writeContent(CBA, Section.Content, Section.Size); + if (!Section.Symbols) return; - } for (StringRef Sym : *Section.Symbols) SHeader.sh_size += @@ -1612,12 +1636,10 @@ template <class ELFT> void ELFState<ELFT>::writeSectionContent(Elf_Shdr &SHeader, const ELFYAML::NoteSection &Section, ContiguousBlobAccumulator &CBA) { - uint64_t Offset = CBA.tell(); - if (Section.Content || Section.Size) { - SHeader.sh_size = writeContent(CBA, Section.Content, Section.Size); + if (!Section.Notes) return; - } + uint64_t Offset = CBA.tell(); for (const ELFYAML::NoteEntry &NE : *Section.Notes) { // Write name size. if (NE.Name.empty()) @@ -1655,15 +1677,11 @@ template <class ELFT> void ELFState<ELFT>::writeSectionContent(Elf_Shdr &SHeader, const ELFYAML::GnuHashSection &Section, ContiguousBlobAccumulator &CBA) { - unsigned Link = 0; - if (Section.Link.empty() && !ExcludedSectionHeaders.count(".dynsym") && - SN2I.lookup(".dynsym", Link)) - SHeader.sh_link = Link; + if (!Section.HashBuckets) + return; - if (Section.Content) { - SHeader.sh_size = writeContent(CBA, Section.Content, None); + if (!Section.Header) return; - } // We write the header first, starting with the hash buckets count. Normally // it is the number of entries in HashBuckets, but the "NBuckets" property can @@ -1724,7 +1742,9 @@ void ELFState<ELFT>::writeFill(ELFYAML::Fill &Fill, template <class ELFT> DenseMap<StringRef, size_t> ELFState<ELFT>::buildSectionHeaderReorderMap() { - if (!Doc.SectionHeaders || Doc.SectionHeaders->NoHeaders) + const ELFYAML::SectionHeaderTable &SectionHeaders = + Doc.getSectionHeaderTable(); + if (SectionHeaders.IsImplicit || SectionHeaders.NoHeaders) return DenseMap<StringRef, size_t>(); DenseMap<StringRef, size_t> Ret; @@ -1738,12 +1758,12 @@ DenseMap<StringRef, size_t> ELFState<ELFT>::buildSectionHeaderReorderMap() { Seen.insert(Hdr.Name); }; - if (Doc.SectionHeaders->Sections) - for (const ELFYAML::SectionHeader &Hdr : *Doc.SectionHeaders->Sections) + if (SectionHeaders.Sections) + for (const ELFYAML::SectionHeader &Hdr : *SectionHeaders.Sections) AddSection(Hdr); - if (Doc.SectionHeaders->Excluded) - for (const ELFYAML::SectionHeader &Hdr : *Doc.SectionHeaders->Excluded) + if (SectionHeaders.Excluded) + for (const ELFYAML::SectionHeader &Hdr : *SectionHeaders.Excluded) AddSection(Hdr); for (const ELFYAML::Section *S : Doc.getSections()) { @@ -1772,17 +1792,17 @@ template <class ELFT> void ELFState<ELFT>::buildSectionIndex() { // Build excluded section headers map. std::vector<ELFYAML::Section *> Sections = Doc.getSections(); - if (Doc.SectionHeaders) { - if (Doc.SectionHeaders->Excluded) - for (const ELFYAML::SectionHeader &Hdr : *Doc.SectionHeaders->Excluded) - if (!ExcludedSectionHeaders.insert(Hdr.Name).second) - llvm_unreachable("buildSectionIndex() failed"); + const ELFYAML::SectionHeaderTable &SectionHeaders = + Doc.getSectionHeaderTable(); + if (SectionHeaders.Excluded) + for (const ELFYAML::SectionHeader &Hdr : *SectionHeaders.Excluded) + if (!ExcludedSectionHeaders.insert(Hdr.Name).second) + llvm_unreachable("buildSectionIndex() failed"); - if (Doc.SectionHeaders->NoHeaders.getValueOr(false)) - for (const ELFYAML::Section *S : Sections) - if (!ExcludedSectionHeaders.insert(S->Name).second) - llvm_unreachable("buildSectionIndex() failed"); - } + if (SectionHeaders.NoHeaders.getValueOr(false)) + for (const ELFYAML::Section *S : Sections) + if (!ExcludedSectionHeaders.insert(S->Name).second) + llvm_unreachable("buildSectionIndex() failed"); size_t SecNdx = -1; for (const ELFYAML::Section *S : Sections) { @@ -1885,11 +1905,7 @@ bool ELFState<ELFT>::writeELF(raw_ostream &OS, ELFYAML::Object &Doc, // Now we can decide segment offsets. State.setProgramHeaderLayout(PHeaders, SHeaders); - // Align the start of the section header table, which is written after all - // section data. - uint64_t SHOff = - State.alignToOffset(CBA, sizeof(typename ELFT::uint), /*Offset=*/None); - bool ReachedLimit = SHOff + arrayDataSize(makeArrayRef(SHeaders)) > MaxSize; + bool ReachedLimit = CBA.getOffset() > MaxSize; if (Error E = CBA.takeLimitError()) { // We report a custom error message instead below. consumeError(std::move(E)); @@ -1904,10 +1920,15 @@ bool ELFState<ELFT>::writeELF(raw_ostream &OS, ELFYAML::Object &Doc, if (State.HasError) return false; - State.writeELFHeader(OS, SHOff); + State.writeELFHeader(OS); writeArrayData(OS, makeArrayRef(PHeaders)); + + const ELFYAML::SectionHeaderTable &SHT = Doc.getSectionHeaderTable(); + if (!SHT.NoHeaders.getValueOr(false)) + CBA.updateDataAt(*SHT.Offset, SHeaders.data(), + SHT.getNumHeaders(SHeaders.size()) * sizeof(Elf_Shdr)); + CBA.writeBlobToStream(OS); - writeArrayData(OS, makeArrayRef(SHeaders)); return true; } |
