Path: blob/main/contrib/llvm-project/llvm/lib/ObjectYAML/ELFEmitter.cpp
35233 views
//===- yaml2elf - Convert YAML to a ELF object file -----------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7///8/// \file9/// The ELF component of yaml2obj.10///11//===----------------------------------------------------------------------===//1213#include "llvm/ADT/ArrayRef.h"14#include "llvm/ADT/DenseMap.h"15#include "llvm/ADT/SetVector.h"16#include "llvm/ADT/StringSet.h"17#include "llvm/BinaryFormat/ELF.h"18#include "llvm/MC/StringTableBuilder.h"19#include "llvm/Object/ELFObjectFile.h"20#include "llvm/Object/ELFTypes.h"21#include "llvm/ObjectYAML/DWARFEmitter.h"22#include "llvm/ObjectYAML/DWARFYAML.h"23#include "llvm/ObjectYAML/ELFYAML.h"24#include "llvm/ObjectYAML/yaml2obj.h"25#include "llvm/Support/EndianStream.h"26#include "llvm/Support/Errc.h"27#include "llvm/Support/Error.h"28#include "llvm/Support/LEB128.h"29#include "llvm/Support/MemoryBuffer.h"30#include "llvm/Support/WithColor.h"31#include "llvm/Support/YAMLTraits.h"32#include "llvm/Support/raw_ostream.h"33#include <optional>34#include <variant>3536using namespace llvm;3738// This class is used to build up a contiguous binary blob while keeping39// track of an offset in the output (which notionally begins at40// `InitialOffset`).41// The blob might be limited to an arbitrary size. All attempts to write data42// are ignored and the error condition is remembered once the limit is reached.43// Such an approach allows us to simplify the code by delaying error reporting44// and doing it at a convenient time.45namespace {46class ContiguousBlobAccumulator {47const uint64_t InitialOffset;48const uint64_t MaxSize;4950SmallVector<char, 128> Buf;51raw_svector_ostream OS;52Error ReachedLimitErr = Error::success();5354bool checkLimit(uint64_t Size) {55if (!ReachedLimitErr && getOffset() + Size <= MaxSize)56return true;57if (!ReachedLimitErr)58ReachedLimitErr = createStringError(errc::invalid_argument,59"reached the output size limit");60return false;61}6263public:64ContiguousBlobAccumulator(uint64_t BaseOffset, uint64_t SizeLimit)65: InitialOffset(BaseOffset), MaxSize(SizeLimit), OS(Buf) {}6667uint64_t tell() const { return OS.tell(); }68uint64_t getOffset() const { return InitialOffset + OS.tell(); }69void writeBlobToStream(raw_ostream &Out) const { Out << OS.str(); }7071Error takeLimitError() {72// Request to write 0 bytes to check we did not reach the limit.73checkLimit(0);74return std::move(ReachedLimitErr);75}7677/// \returns The new offset.78uint64_t padToAlignment(unsigned Align) {79uint64_t CurrentOffset = getOffset();80if (ReachedLimitErr)81return CurrentOffset;8283uint64_t AlignedOffset = alignTo(CurrentOffset, Align == 0 ? 1 : Align);84uint64_t PaddingSize = AlignedOffset - CurrentOffset;85if (!checkLimit(PaddingSize))86return CurrentOffset;8788writeZeros(PaddingSize);89return AlignedOffset;90}9192raw_ostream *getRawOS(uint64_t Size) {93if (checkLimit(Size))94return &OS;95return nullptr;96}9798void writeAsBinary(const yaml::BinaryRef &Bin, uint64_t N = UINT64_MAX) {99if (!checkLimit(Bin.binary_size()))100return;101Bin.writeAsBinary(OS, N);102}103104void writeZeros(uint64_t Num) {105if (checkLimit(Num))106OS.write_zeros(Num);107}108109void write(const char *Ptr, size_t Size) {110if (checkLimit(Size))111OS.write(Ptr, Size);112}113114void write(unsigned char C) {115if (checkLimit(1))116OS.write(C);117}118119unsigned writeULEB128(uint64_t Val) {120if (!checkLimit(sizeof(uint64_t)))121return 0;122return encodeULEB128(Val, OS);123}124125unsigned writeSLEB128(int64_t Val) {126if (!checkLimit(10))127return 0;128return encodeSLEB128(Val, OS);129}130131template <typename T> void write(T Val, llvm::endianness E) {132if (checkLimit(sizeof(T)))133support::endian::write<T>(OS, Val, E);134}135136void updateDataAt(uint64_t Pos, void *Data, size_t Size) {137assert(Pos >= InitialOffset && Pos + Size <= getOffset());138memcpy(&Buf[Pos - InitialOffset], Data, Size);139}140};141142// Used to keep track of section and symbol names, so that in the YAML file143// sections and symbols can be referenced by name instead of by index.144class NameToIdxMap {145StringMap<unsigned> Map;146147public:148/// \Returns false if name is already present in the map.149bool addName(StringRef Name, unsigned Ndx) {150return Map.insert({Name, Ndx}).second;151}152/// \Returns false if name is not present in the map.153bool lookup(StringRef Name, unsigned &Idx) const {154auto I = Map.find(Name);155if (I == Map.end())156return false;157Idx = I->getValue();158return true;159}160/// Asserts if name is not present in the map.161unsigned get(StringRef Name) const {162unsigned Idx;163if (lookup(Name, Idx))164return Idx;165assert(false && "Expected section not found in index");166return 0;167}168unsigned size() const { return Map.size(); }169};170171namespace {172struct Fragment {173uint64_t Offset;174uint64_t Size;175uint32_t Type;176uint64_t AddrAlign;177};178} // namespace179180/// "Single point of truth" for the ELF file construction.181/// TODO: This class still has a ways to go before it is truly a "single182/// point of truth".183template <class ELFT> class ELFState {184LLVM_ELF_IMPORT_TYPES_ELFT(ELFT)185186enum class SymtabType { Static, Dynamic };187188/// The future symbol table string section.189StringTableBuilder DotStrtab{StringTableBuilder::ELF};190191/// The future section header string table section, if a unique string table192/// is needed. Don't reference this variable direectly: use the193/// ShStrtabStrings member instead.194StringTableBuilder DotShStrtab{StringTableBuilder::ELF};195196/// The future dynamic symbol string section.197StringTableBuilder DotDynstr{StringTableBuilder::ELF};198199/// The name of the section header string table section. If it is .strtab or200/// .dynstr, the section header strings will be written to the same string201/// table as the static/dynamic symbols respectively. Otherwise a dedicated202/// section will be created with that name.203StringRef SectionHeaderStringTableName = ".shstrtab";204StringTableBuilder *ShStrtabStrings = &DotShStrtab;205206NameToIdxMap SN2I;207NameToIdxMap SymN2I;208NameToIdxMap DynSymN2I;209ELFYAML::Object &Doc;210211StringSet<> ExcludedSectionHeaders;212213uint64_t LocationCounter = 0;214bool HasError = false;215yaml::ErrorHandler ErrHandler;216void reportError(const Twine &Msg);217void reportError(Error Err);218219std::vector<Elf_Sym> toELFSymbols(ArrayRef<ELFYAML::Symbol> Symbols,220const StringTableBuilder &Strtab);221unsigned toSectionIndex(StringRef S, StringRef LocSec, StringRef LocSym = "");222unsigned toSymbolIndex(StringRef S, StringRef LocSec, bool IsDynamic);223224void buildSectionIndex();225void buildSymbolIndexes();226void initProgramHeaders(std::vector<Elf_Phdr> &PHeaders);227bool initImplicitHeader(ContiguousBlobAccumulator &CBA, Elf_Shdr &Header,228StringRef SecName, ELFYAML::Section *YAMLSec);229void initSectionHeaders(std::vector<Elf_Shdr> &SHeaders,230ContiguousBlobAccumulator &CBA);231void initSymtabSectionHeader(Elf_Shdr &SHeader, SymtabType STType,232ContiguousBlobAccumulator &CBA,233ELFYAML::Section *YAMLSec);234void initStrtabSectionHeader(Elf_Shdr &SHeader, StringRef Name,235StringTableBuilder &STB,236ContiguousBlobAccumulator &CBA,237ELFYAML::Section *YAMLSec);238void initDWARFSectionHeader(Elf_Shdr &SHeader, StringRef Name,239ContiguousBlobAccumulator &CBA,240ELFYAML::Section *YAMLSec);241void setProgramHeaderLayout(std::vector<Elf_Phdr> &PHeaders,242std::vector<Elf_Shdr> &SHeaders);243244std::vector<Fragment>245getPhdrFragments(const ELFYAML::ProgramHeader &Phdr,246ArrayRef<typename ELFT::Shdr> SHeaders);247248void finalizeStrings();249void writeELFHeader(raw_ostream &OS);250void writeSectionContent(Elf_Shdr &SHeader,251const ELFYAML::NoBitsSection &Section,252ContiguousBlobAccumulator &CBA);253void writeSectionContent(Elf_Shdr &SHeader,254const ELFYAML::RawContentSection &Section,255ContiguousBlobAccumulator &CBA);256void writeSectionContent(Elf_Shdr &SHeader,257const ELFYAML::RelocationSection &Section,258ContiguousBlobAccumulator &CBA);259void writeSectionContent(Elf_Shdr &SHeader,260const ELFYAML::RelrSection &Section,261ContiguousBlobAccumulator &CBA);262void writeSectionContent(Elf_Shdr &SHeader,263const ELFYAML::GroupSection &Group,264ContiguousBlobAccumulator &CBA);265void writeSectionContent(Elf_Shdr &SHeader,266const ELFYAML::SymtabShndxSection &Shndx,267ContiguousBlobAccumulator &CBA);268void writeSectionContent(Elf_Shdr &SHeader,269const ELFYAML::SymverSection &Section,270ContiguousBlobAccumulator &CBA);271void writeSectionContent(Elf_Shdr &SHeader,272const ELFYAML::VerneedSection &Section,273ContiguousBlobAccumulator &CBA);274void writeSectionContent(Elf_Shdr &SHeader,275const ELFYAML::VerdefSection &Section,276ContiguousBlobAccumulator &CBA);277void writeSectionContent(Elf_Shdr &SHeader,278const ELFYAML::ARMIndexTableSection &Section,279ContiguousBlobAccumulator &CBA);280void writeSectionContent(Elf_Shdr &SHeader,281const ELFYAML::MipsABIFlags &Section,282ContiguousBlobAccumulator &CBA);283void writeSectionContent(Elf_Shdr &SHeader,284const ELFYAML::DynamicSection &Section,285ContiguousBlobAccumulator &CBA);286void writeSectionContent(Elf_Shdr &SHeader,287const ELFYAML::StackSizesSection &Section,288ContiguousBlobAccumulator &CBA);289void writeSectionContent(Elf_Shdr &SHeader,290const ELFYAML::BBAddrMapSection &Section,291ContiguousBlobAccumulator &CBA);292void writeSectionContent(Elf_Shdr &SHeader,293const ELFYAML::HashSection &Section,294ContiguousBlobAccumulator &CBA);295void writeSectionContent(Elf_Shdr &SHeader,296const ELFYAML::AddrsigSection &Section,297ContiguousBlobAccumulator &CBA);298void writeSectionContent(Elf_Shdr &SHeader,299const ELFYAML::NoteSection &Section,300ContiguousBlobAccumulator &CBA);301void writeSectionContent(Elf_Shdr &SHeader,302const ELFYAML::GnuHashSection &Section,303ContiguousBlobAccumulator &CBA);304void writeSectionContent(Elf_Shdr &SHeader,305const ELFYAML::LinkerOptionsSection &Section,306ContiguousBlobAccumulator &CBA);307void writeSectionContent(Elf_Shdr &SHeader,308const ELFYAML::DependentLibrariesSection &Section,309ContiguousBlobAccumulator &CBA);310void writeSectionContent(Elf_Shdr &SHeader,311const ELFYAML::CallGraphProfileSection &Section,312ContiguousBlobAccumulator &CBA);313314void writeFill(ELFYAML::Fill &Fill, ContiguousBlobAccumulator &CBA);315316ELFState(ELFYAML::Object &D, yaml::ErrorHandler EH);317318void assignSectionAddress(Elf_Shdr &SHeader, ELFYAML::Section *YAMLSec);319320DenseMap<StringRef, size_t> buildSectionHeaderReorderMap();321322BumpPtrAllocator StringAlloc;323uint64_t alignToOffset(ContiguousBlobAccumulator &CBA, uint64_t Align,324std::optional<llvm::yaml::Hex64> Offset);325326uint64_t getSectionNameOffset(StringRef Name);327328public:329static bool writeELF(raw_ostream &OS, ELFYAML::Object &Doc,330yaml::ErrorHandler EH, uint64_t MaxSize);331};332} // end anonymous namespace333334template <class T> static size_t arrayDataSize(ArrayRef<T> A) {335return A.size() * sizeof(T);336}337338template <class T> static void writeArrayData(raw_ostream &OS, ArrayRef<T> A) {339OS.write((const char *)A.data(), arrayDataSize(A));340}341342template <class T> static void zero(T &Obj) { memset(&Obj, 0, sizeof(Obj)); }343344template <class ELFT>345ELFState<ELFT>::ELFState(ELFYAML::Object &D, yaml::ErrorHandler EH)346: Doc(D), ErrHandler(EH) {347// The input may explicitly request to store the section header table strings348// in the same string table as dynamic or static symbol names. Set the349// ShStrtabStrings member accordingly.350if (Doc.Header.SectionHeaderStringTable) {351SectionHeaderStringTableName = *Doc.Header.SectionHeaderStringTable;352if (*Doc.Header.SectionHeaderStringTable == ".strtab")353ShStrtabStrings = &DotStrtab;354else if (*Doc.Header.SectionHeaderStringTable == ".dynstr")355ShStrtabStrings = &DotDynstr;356// Otherwise, the unique table will be used.357}358359std::vector<ELFYAML::Section *> Sections = Doc.getSections();360// Insert SHT_NULL section implicitly when it is not defined in YAML.361if (Sections.empty() || Sections.front()->Type != ELF::SHT_NULL)362Doc.Chunks.insert(363Doc.Chunks.begin(),364std::make_unique<ELFYAML::Section>(365ELFYAML::Chunk::ChunkKind::RawContent, /*IsImplicit=*/true));366367StringSet<> DocSections;368ELFYAML::SectionHeaderTable *SecHdrTable = nullptr;369for (size_t I = 0; I < Doc.Chunks.size(); ++I) {370const std::unique_ptr<ELFYAML::Chunk> &C = Doc.Chunks[I];371372// We might have an explicit section header table declaration.373if (auto S = dyn_cast<ELFYAML::SectionHeaderTable>(C.get())) {374if (SecHdrTable)375reportError("multiple section header tables are not allowed");376SecHdrTable = S;377continue;378}379380// We add a technical suffix for each unnamed section/fill. It does not381// affect the output, but allows us to map them by name in the code and382// report better error messages.383if (C->Name.empty()) {384std::string NewName = ELFYAML::appendUniqueSuffix(385/*Name=*/"", "index " + Twine(I));386C->Name = StringRef(NewName).copy(StringAlloc);387assert(ELFYAML::dropUniqueSuffix(C->Name).empty());388}389390if (!DocSections.insert(C->Name).second)391reportError("repeated section/fill name: '" + C->Name +392"' at YAML section/fill number " + Twine(I));393}394395SmallSetVector<StringRef, 8> ImplicitSections;396if (Doc.DynamicSymbols) {397if (SectionHeaderStringTableName == ".dynsym")398reportError("cannot use '.dynsym' as the section header name table when "399"there are dynamic symbols");400ImplicitSections.insert(".dynsym");401ImplicitSections.insert(".dynstr");402}403if (Doc.Symbols) {404if (SectionHeaderStringTableName == ".symtab")405reportError("cannot use '.symtab' as the section header name table when "406"there are symbols");407ImplicitSections.insert(".symtab");408}409if (Doc.DWARF)410for (StringRef DebugSecName : Doc.DWARF->getNonEmptySectionNames()) {411std::string SecName = ("." + DebugSecName).str();412// TODO: For .debug_str it should be possible to share the string table,413// in the same manner as the symbol string tables.414if (SectionHeaderStringTableName == SecName)415reportError("cannot use '" + SecName +416"' as the section header name table when it is needed for "417"DWARF output");418ImplicitSections.insert(StringRef(SecName).copy(StringAlloc));419}420// TODO: Only create the .strtab here if any symbols have been requested.421ImplicitSections.insert(".strtab");422if (!SecHdrTable || !SecHdrTable->NoHeaders.value_or(false))423ImplicitSections.insert(SectionHeaderStringTableName);424425// Insert placeholders for implicit sections that are not426// defined explicitly in YAML.427for (StringRef SecName : ImplicitSections) {428if (DocSections.count(SecName))429continue;430431std::unique_ptr<ELFYAML::Section> Sec = std::make_unique<ELFYAML::Section>(432ELFYAML::Chunk::ChunkKind::RawContent, true /*IsImplicit*/);433Sec->Name = SecName;434435if (SecName == SectionHeaderStringTableName)436Sec->Type = ELF::SHT_STRTAB;437else if (SecName == ".dynsym")438Sec->Type = ELF::SHT_DYNSYM;439else if (SecName == ".symtab")440Sec->Type = ELF::SHT_SYMTAB;441else442Sec->Type = ELF::SHT_STRTAB;443444// When the section header table is explicitly defined at the end of the445// sections list, it is reasonable to assume that the user wants to reorder446// section headers, but still wants to place the section header table after447// all sections, like it normally happens. In this case we want to insert448// other implicit sections right before the section header table.449if (Doc.Chunks.back().get() == SecHdrTable)450Doc.Chunks.insert(Doc.Chunks.end() - 1, std::move(Sec));451else452Doc.Chunks.push_back(std::move(Sec));453}454455// Insert the section header table implicitly at the end, when it is not456// explicitly defined.457if (!SecHdrTable)458Doc.Chunks.push_back(459std::make_unique<ELFYAML::SectionHeaderTable>(/*IsImplicit=*/true));460}461462template <class ELFT>463void ELFState<ELFT>::writeELFHeader(raw_ostream &OS) {464using namespace llvm::ELF;465466Elf_Ehdr Header;467zero(Header);468Header.e_ident[EI_MAG0] = 0x7f;469Header.e_ident[EI_MAG1] = 'E';470Header.e_ident[EI_MAG2] = 'L';471Header.e_ident[EI_MAG3] = 'F';472Header.e_ident[EI_CLASS] = ELFT::Is64Bits ? ELFCLASS64 : ELFCLASS32;473Header.e_ident[EI_DATA] = Doc.Header.Data;474Header.e_ident[EI_VERSION] = EV_CURRENT;475Header.e_ident[EI_OSABI] = Doc.Header.OSABI;476Header.e_ident[EI_ABIVERSION] = Doc.Header.ABIVersion;477Header.e_type = Doc.Header.Type;478479if (Doc.Header.Machine)480Header.e_machine = *Doc.Header.Machine;481else482Header.e_machine = EM_NONE;483484Header.e_version = EV_CURRENT;485Header.e_entry = Doc.Header.Entry;486Header.e_flags = Doc.Header.Flags;487Header.e_ehsize = sizeof(Elf_Ehdr);488489if (Doc.Header.EPhOff)490Header.e_phoff = *Doc.Header.EPhOff;491else if (!Doc.ProgramHeaders.empty())492Header.e_phoff = sizeof(Header);493else494Header.e_phoff = 0;495496if (Doc.Header.EPhEntSize)497Header.e_phentsize = *Doc.Header.EPhEntSize;498else if (!Doc.ProgramHeaders.empty())499Header.e_phentsize = sizeof(Elf_Phdr);500else501Header.e_phentsize = 0;502503if (Doc.Header.EPhNum)504Header.e_phnum = *Doc.Header.EPhNum;505else if (!Doc.ProgramHeaders.empty())506Header.e_phnum = Doc.ProgramHeaders.size();507else508Header.e_phnum = 0;509510Header.e_shentsize = Doc.Header.EShEntSize ? (uint16_t)*Doc.Header.EShEntSize511: sizeof(Elf_Shdr);512513const ELFYAML::SectionHeaderTable &SectionHeaders =514Doc.getSectionHeaderTable();515516if (Doc.Header.EShOff)517Header.e_shoff = *Doc.Header.EShOff;518else if (SectionHeaders.Offset)519Header.e_shoff = *SectionHeaders.Offset;520else521Header.e_shoff = 0;522523if (Doc.Header.EShNum)524Header.e_shnum = *Doc.Header.EShNum;525else526Header.e_shnum = SectionHeaders.getNumHeaders(Doc.getSections().size());527528if (Doc.Header.EShStrNdx)529Header.e_shstrndx = *Doc.Header.EShStrNdx;530else if (SectionHeaders.Offset &&531!ExcludedSectionHeaders.count(SectionHeaderStringTableName))532Header.e_shstrndx = SN2I.get(SectionHeaderStringTableName);533else534Header.e_shstrndx = 0;535536OS.write((const char *)&Header, sizeof(Header));537}538539template <class ELFT>540void ELFState<ELFT>::initProgramHeaders(std::vector<Elf_Phdr> &PHeaders) {541DenseMap<StringRef, ELFYAML::Fill *> NameToFill;542DenseMap<StringRef, size_t> NameToIndex;543for (size_t I = 0, E = Doc.Chunks.size(); I != E; ++I) {544if (auto S = dyn_cast<ELFYAML::Fill>(Doc.Chunks[I].get()))545NameToFill[S->Name] = S;546NameToIndex[Doc.Chunks[I]->Name] = I + 1;547}548549std::vector<ELFYAML::Section *> Sections = Doc.getSections();550for (size_t I = 0, E = Doc.ProgramHeaders.size(); I != E; ++I) {551ELFYAML::ProgramHeader &YamlPhdr = Doc.ProgramHeaders[I];552Elf_Phdr Phdr;553zero(Phdr);554Phdr.p_type = YamlPhdr.Type;555Phdr.p_flags = YamlPhdr.Flags;556Phdr.p_vaddr = YamlPhdr.VAddr;557Phdr.p_paddr = YamlPhdr.PAddr;558PHeaders.push_back(Phdr);559560if (!YamlPhdr.FirstSec && !YamlPhdr.LastSec)561continue;562563// Get the index of the section, or 0 in the case when the section doesn't exist.564size_t First = NameToIndex[*YamlPhdr.FirstSec];565if (!First)566reportError("unknown section or fill referenced: '" + *YamlPhdr.FirstSec +567"' by the 'FirstSec' key of the program header with index " +568Twine(I));569size_t Last = NameToIndex[*YamlPhdr.LastSec];570if (!Last)571reportError("unknown section or fill referenced: '" + *YamlPhdr.LastSec +572"' by the 'LastSec' key of the program header with index " +573Twine(I));574if (!First || !Last)575continue;576577if (First > Last)578reportError("program header with index " + Twine(I) +579": the section index of " + *YamlPhdr.FirstSec +580" is greater than the index of " + *YamlPhdr.LastSec);581582for (size_t I = First; I <= Last; ++I)583YamlPhdr.Chunks.push_back(Doc.Chunks[I - 1].get());584}585}586587template <class ELFT>588unsigned ELFState<ELFT>::toSectionIndex(StringRef S, StringRef LocSec,589StringRef LocSym) {590assert(LocSec.empty() || LocSym.empty());591592unsigned Index;593if (!SN2I.lookup(S, Index) && !to_integer(S, Index)) {594if (!LocSym.empty())595reportError("unknown section referenced: '" + S + "' by YAML symbol '" +596LocSym + "'");597else598reportError("unknown section referenced: '" + S + "' by YAML section '" +599LocSec + "'");600return 0;601}602603const ELFYAML::SectionHeaderTable &SectionHeaders =604Doc.getSectionHeaderTable();605if (SectionHeaders.IsImplicit ||606(SectionHeaders.NoHeaders && !*SectionHeaders.NoHeaders) ||607SectionHeaders.isDefault())608return Index;609610assert(!SectionHeaders.NoHeaders.value_or(false) || !SectionHeaders.Sections);611size_t FirstExcluded =612SectionHeaders.Sections ? SectionHeaders.Sections->size() : 0;613if (Index > FirstExcluded) {614if (LocSym.empty())615reportError("unable to link '" + LocSec + "' to excluded section '" + S +616"'");617else618reportError("excluded section referenced: '" + S + "' by symbol '" +619LocSym + "'");620}621return Index;622}623624template <class ELFT>625unsigned ELFState<ELFT>::toSymbolIndex(StringRef S, StringRef LocSec,626bool IsDynamic) {627const NameToIdxMap &SymMap = IsDynamic ? DynSymN2I : SymN2I;628unsigned Index;629// Here we try to look up S in the symbol table. If it is not there,630// treat its value as a symbol index.631if (!SymMap.lookup(S, Index) && !to_integer(S, Index)) {632reportError("unknown symbol referenced: '" + S + "' by YAML section '" +633LocSec + "'");634return 0;635}636return Index;637}638639template <class ELFT>640static void overrideFields(ELFYAML::Section *From, typename ELFT::Shdr &To) {641if (!From)642return;643if (From->ShAddrAlign)644To.sh_addralign = *From->ShAddrAlign;645if (From->ShFlags)646To.sh_flags = *From->ShFlags;647if (From->ShName)648To.sh_name = *From->ShName;649if (From->ShOffset)650To.sh_offset = *From->ShOffset;651if (From->ShSize)652To.sh_size = *From->ShSize;653if (From->ShType)654To.sh_type = *From->ShType;655}656657template <class ELFT>658bool ELFState<ELFT>::initImplicitHeader(ContiguousBlobAccumulator &CBA,659Elf_Shdr &Header, StringRef SecName,660ELFYAML::Section *YAMLSec) {661// Check if the header was already initialized.662if (Header.sh_offset)663return false;664665if (SecName == ".strtab")666initStrtabSectionHeader(Header, SecName, DotStrtab, CBA, YAMLSec);667else if (SecName == ".dynstr")668initStrtabSectionHeader(Header, SecName, DotDynstr, CBA, YAMLSec);669else if (SecName == SectionHeaderStringTableName)670initStrtabSectionHeader(Header, SecName, *ShStrtabStrings, CBA, YAMLSec);671else if (SecName == ".symtab")672initSymtabSectionHeader(Header, SymtabType::Static, CBA, YAMLSec);673else if (SecName == ".dynsym")674initSymtabSectionHeader(Header, SymtabType::Dynamic, CBA, YAMLSec);675else if (SecName.starts_with(".debug_")) {676// If a ".debug_*" section's type is a preserved one, e.g., SHT_DYNAMIC, we677// will not treat it as a debug section.678if (YAMLSec && !isa<ELFYAML::RawContentSection>(YAMLSec))679return false;680initDWARFSectionHeader(Header, SecName, CBA, YAMLSec);681} else682return false;683684LocationCounter += Header.sh_size;685686// Override section fields if requested.687overrideFields<ELFT>(YAMLSec, Header);688return true;689}690691constexpr char SuffixStart = '(';692constexpr char SuffixEnd = ')';693694std::string llvm::ELFYAML::appendUniqueSuffix(StringRef Name,695const Twine &Msg) {696// Do not add a space when a Name is empty.697std::string Ret = Name.empty() ? "" : Name.str() + ' ';698return Ret + (Twine(SuffixStart) + Msg + Twine(SuffixEnd)).str();699}700701StringRef llvm::ELFYAML::dropUniqueSuffix(StringRef S) {702if (S.empty() || S.back() != SuffixEnd)703return S;704705// A special case for empty names. See appendUniqueSuffix() above.706size_t SuffixPos = S.rfind(SuffixStart);707if (SuffixPos == 0)708return "";709710if (SuffixPos == StringRef::npos || S[SuffixPos - 1] != ' ')711return S;712return S.substr(0, SuffixPos - 1);713}714715template <class ELFT>716uint64_t ELFState<ELFT>::getSectionNameOffset(StringRef Name) {717// If a section is excluded from section headers, we do not save its name in718// the string table.719if (ExcludedSectionHeaders.count(Name))720return 0;721return ShStrtabStrings->getOffset(Name);722}723724static uint64_t writeContent(ContiguousBlobAccumulator &CBA,725const std::optional<yaml::BinaryRef> &Content,726const std::optional<llvm::yaml::Hex64> &Size) {727size_t ContentSize = 0;728if (Content) {729CBA.writeAsBinary(*Content);730ContentSize = Content->binary_size();731}732733if (!Size)734return ContentSize;735736CBA.writeZeros(*Size - ContentSize);737return *Size;738}739740static StringRef getDefaultLinkSec(unsigned SecType) {741switch (SecType) {742case ELF::SHT_REL:743case ELF::SHT_RELA:744case ELF::SHT_GROUP:745case ELF::SHT_LLVM_CALL_GRAPH_PROFILE:746case ELF::SHT_LLVM_ADDRSIG:747return ".symtab";748case ELF::SHT_GNU_versym:749case ELF::SHT_HASH:750case ELF::SHT_GNU_HASH:751return ".dynsym";752case ELF::SHT_DYNSYM:753case ELF::SHT_GNU_verdef:754case ELF::SHT_GNU_verneed:755return ".dynstr";756case ELF::SHT_SYMTAB:757return ".strtab";758default:759return "";760}761}762763template <class ELFT>764void ELFState<ELFT>::initSectionHeaders(std::vector<Elf_Shdr> &SHeaders,765ContiguousBlobAccumulator &CBA) {766// Ensure SHN_UNDEF entry is present. An all-zero section header is a767// valid SHN_UNDEF entry since SHT_NULL == 0.768SHeaders.resize(Doc.getSections().size());769770for (const std::unique_ptr<ELFYAML::Chunk> &D : Doc.Chunks) {771if (ELFYAML::Fill *S = dyn_cast<ELFYAML::Fill>(D.get())) {772S->Offset = alignToOffset(CBA, /*Align=*/1, S->Offset);773writeFill(*S, CBA);774LocationCounter += S->Size;775continue;776}777778if (ELFYAML::SectionHeaderTable *S =779dyn_cast<ELFYAML::SectionHeaderTable>(D.get())) {780if (S->NoHeaders.value_or(false))781continue;782783if (!S->Offset)784S->Offset = alignToOffset(CBA, sizeof(typename ELFT::uint),785/*Offset=*/std::nullopt);786else787S->Offset = alignToOffset(CBA, /*Align=*/1, S->Offset);788789uint64_t Size = S->getNumHeaders(SHeaders.size()) * sizeof(Elf_Shdr);790// The full section header information might be not available here, so791// fill the space with zeroes as a placeholder.792CBA.writeZeros(Size);793LocationCounter += Size;794continue;795}796797ELFYAML::Section *Sec = cast<ELFYAML::Section>(D.get());798bool IsFirstUndefSection = Sec == Doc.getSections().front();799if (IsFirstUndefSection && Sec->IsImplicit)800continue;801802Elf_Shdr &SHeader = SHeaders[SN2I.get(Sec->Name)];803if (Sec->Link) {804SHeader.sh_link = toSectionIndex(*Sec->Link, Sec->Name);805} else {806StringRef LinkSec = getDefaultLinkSec(Sec->Type);807unsigned Link = 0;808if (!LinkSec.empty() && !ExcludedSectionHeaders.count(LinkSec) &&809SN2I.lookup(LinkSec, Link))810SHeader.sh_link = Link;811}812813if (Sec->EntSize)814SHeader.sh_entsize = *Sec->EntSize;815else816SHeader.sh_entsize = ELFYAML::getDefaultShEntSize<ELFT>(817Doc.Header.Machine.value_or(ELF::EM_NONE), Sec->Type, Sec->Name);818819// We have a few sections like string or symbol tables that are usually820// added implicitly to the end. However, if they are explicitly specified821// in the YAML, we need to write them here. This ensures the file offset822// remains correct.823if (initImplicitHeader(CBA, SHeader, Sec->Name,824Sec->IsImplicit ? nullptr : Sec))825continue;826827assert(Sec && "It can't be null unless it is an implicit section. But all "828"implicit sections should already have been handled above.");829830SHeader.sh_name =831getSectionNameOffset(ELFYAML::dropUniqueSuffix(Sec->Name));832SHeader.sh_type = Sec->Type;833if (Sec->Flags)834SHeader.sh_flags = *Sec->Flags;835SHeader.sh_addralign = Sec->AddressAlign;836837// Set the offset for all sections, except the SHN_UNDEF section with index838// 0 when not explicitly requested.839if (!IsFirstUndefSection || Sec->Offset)840SHeader.sh_offset = alignToOffset(CBA, SHeader.sh_addralign, Sec->Offset);841842assignSectionAddress(SHeader, Sec);843844if (IsFirstUndefSection) {845if (auto RawSec = dyn_cast<ELFYAML::RawContentSection>(Sec)) {846// We do not write any content for special SHN_UNDEF section.847if (RawSec->Size)848SHeader.sh_size = *RawSec->Size;849if (RawSec->Info)850SHeader.sh_info = *RawSec->Info;851}852853LocationCounter += SHeader.sh_size;854overrideFields<ELFT>(Sec, SHeader);855continue;856}857858if (!isa<ELFYAML::NoBitsSection>(Sec) && (Sec->Content || Sec->Size))859SHeader.sh_size = writeContent(CBA, Sec->Content, Sec->Size);860861if (auto S = dyn_cast<ELFYAML::RawContentSection>(Sec)) {862writeSectionContent(SHeader, *S, CBA);863} else if (auto S = dyn_cast<ELFYAML::SymtabShndxSection>(Sec)) {864writeSectionContent(SHeader, *S, CBA);865} else if (auto S = dyn_cast<ELFYAML::RelocationSection>(Sec)) {866writeSectionContent(SHeader, *S, CBA);867} else if (auto S = dyn_cast<ELFYAML::RelrSection>(Sec)) {868writeSectionContent(SHeader, *S, CBA);869} else if (auto S = dyn_cast<ELFYAML::GroupSection>(Sec)) {870writeSectionContent(SHeader, *S, CBA);871} else if (auto S = dyn_cast<ELFYAML::ARMIndexTableSection>(Sec)) {872writeSectionContent(SHeader, *S, CBA);873} else if (auto S = dyn_cast<ELFYAML::MipsABIFlags>(Sec)) {874writeSectionContent(SHeader, *S, CBA);875} else if (auto S = dyn_cast<ELFYAML::NoBitsSection>(Sec)) {876writeSectionContent(SHeader, *S, CBA);877} else if (auto S = dyn_cast<ELFYAML::DynamicSection>(Sec)) {878writeSectionContent(SHeader, *S, CBA);879} else if (auto S = dyn_cast<ELFYAML::SymverSection>(Sec)) {880writeSectionContent(SHeader, *S, CBA);881} else if (auto S = dyn_cast<ELFYAML::VerneedSection>(Sec)) {882writeSectionContent(SHeader, *S, CBA);883} else if (auto S = dyn_cast<ELFYAML::VerdefSection>(Sec)) {884writeSectionContent(SHeader, *S, CBA);885} else if (auto S = dyn_cast<ELFYAML::StackSizesSection>(Sec)) {886writeSectionContent(SHeader, *S, CBA);887} else if (auto S = dyn_cast<ELFYAML::HashSection>(Sec)) {888writeSectionContent(SHeader, *S, CBA);889} else if (auto S = dyn_cast<ELFYAML::AddrsigSection>(Sec)) {890writeSectionContent(SHeader, *S, CBA);891} else if (auto S = dyn_cast<ELFYAML::LinkerOptionsSection>(Sec)) {892writeSectionContent(SHeader, *S, CBA);893} else if (auto S = dyn_cast<ELFYAML::NoteSection>(Sec)) {894writeSectionContent(SHeader, *S, CBA);895} else if (auto S = dyn_cast<ELFYAML::GnuHashSection>(Sec)) {896writeSectionContent(SHeader, *S, CBA);897} else if (auto S = dyn_cast<ELFYAML::DependentLibrariesSection>(Sec)) {898writeSectionContent(SHeader, *S, CBA);899} else if (auto S = dyn_cast<ELFYAML::CallGraphProfileSection>(Sec)) {900writeSectionContent(SHeader, *S, CBA);901} else if (auto S = dyn_cast<ELFYAML::BBAddrMapSection>(Sec)) {902writeSectionContent(SHeader, *S, CBA);903} else {904llvm_unreachable("Unknown section type");905}906907LocationCounter += SHeader.sh_size;908909// Override section fields if requested.910overrideFields<ELFT>(Sec, SHeader);911}912}913914template <class ELFT>915void ELFState<ELFT>::assignSectionAddress(Elf_Shdr &SHeader,916ELFYAML::Section *YAMLSec) {917if (YAMLSec && YAMLSec->Address) {918SHeader.sh_addr = *YAMLSec->Address;919LocationCounter = *YAMLSec->Address;920return;921}922923// sh_addr represents the address in the memory image of a process. Sections924// in a relocatable object file or non-allocatable sections do not need925// sh_addr assignment.926if (Doc.Header.Type.value == ELF::ET_REL ||927!(SHeader.sh_flags & ELF::SHF_ALLOC))928return;929930LocationCounter =931alignTo(LocationCounter, SHeader.sh_addralign ? SHeader.sh_addralign : 1);932SHeader.sh_addr = LocationCounter;933}934935static size_t findFirstNonGlobal(ArrayRef<ELFYAML::Symbol> Symbols) {936for (size_t I = 0; I < Symbols.size(); ++I)937if (Symbols[I].Binding.value != ELF::STB_LOCAL)938return I;939return Symbols.size();940}941942template <class ELFT>943std::vector<typename ELFT::Sym>944ELFState<ELFT>::toELFSymbols(ArrayRef<ELFYAML::Symbol> Symbols,945const StringTableBuilder &Strtab) {946std::vector<Elf_Sym> Ret;947Ret.resize(Symbols.size() + 1);948949size_t I = 0;950for (const ELFYAML::Symbol &Sym : Symbols) {951Elf_Sym &Symbol = Ret[++I];952953// If NameIndex, which contains the name offset, is explicitly specified, we954// use it. This is useful for preparing broken objects. Otherwise, we add955// the specified Name to the string table builder to get its offset.956if (Sym.StName)957Symbol.st_name = *Sym.StName;958else if (!Sym.Name.empty())959Symbol.st_name = Strtab.getOffset(ELFYAML::dropUniqueSuffix(Sym.Name));960961Symbol.setBindingAndType(Sym.Binding, Sym.Type);962if (Sym.Section)963Symbol.st_shndx = toSectionIndex(*Sym.Section, "", Sym.Name);964else if (Sym.Index)965Symbol.st_shndx = *Sym.Index;966967Symbol.st_value = Sym.Value.value_or(yaml::Hex64(0));968Symbol.st_other = Sym.Other ? *Sym.Other : 0;969Symbol.st_size = Sym.Size.value_or(yaml::Hex64(0));970}971972return Ret;973}974975template <class ELFT>976void ELFState<ELFT>::initSymtabSectionHeader(Elf_Shdr &SHeader,977SymtabType STType,978ContiguousBlobAccumulator &CBA,979ELFYAML::Section *YAMLSec) {980981bool IsStatic = STType == SymtabType::Static;982ArrayRef<ELFYAML::Symbol> Symbols;983if (IsStatic && Doc.Symbols)984Symbols = *Doc.Symbols;985else if (!IsStatic && Doc.DynamicSymbols)986Symbols = *Doc.DynamicSymbols;987988ELFYAML::RawContentSection *RawSec =989dyn_cast_or_null<ELFYAML::RawContentSection>(YAMLSec);990if (RawSec && (RawSec->Content || RawSec->Size)) {991bool HasSymbolsDescription =992(IsStatic && Doc.Symbols) || (!IsStatic && Doc.DynamicSymbols);993if (HasSymbolsDescription) {994StringRef Property = (IsStatic ? "`Symbols`" : "`DynamicSymbols`");995if (RawSec->Content)996reportError("cannot specify both `Content` and " + Property +997" for symbol table section '" + RawSec->Name + "'");998if (RawSec->Size)999reportError("cannot specify both `Size` and " + Property +1000" for symbol table section '" + RawSec->Name + "'");1001return;1002}1003}10041005SHeader.sh_name = getSectionNameOffset(IsStatic ? ".symtab" : ".dynsym");10061007if (YAMLSec)1008SHeader.sh_type = YAMLSec->Type;1009else1010SHeader.sh_type = IsStatic ? ELF::SHT_SYMTAB : ELF::SHT_DYNSYM;10111012if (YAMLSec && YAMLSec->Flags)1013SHeader.sh_flags = *YAMLSec->Flags;1014else if (!IsStatic)1015SHeader.sh_flags = ELF::SHF_ALLOC;10161017// If the symbol table section is explicitly described in the YAML1018// then we should set the fields requested.1019SHeader.sh_info = (RawSec && RawSec->Info) ? (unsigned)(*RawSec->Info)1020: findFirstNonGlobal(Symbols) + 1;1021SHeader.sh_addralign = YAMLSec ? (uint64_t)YAMLSec->AddressAlign : 8;10221023assignSectionAddress(SHeader, YAMLSec);10241025SHeader.sh_offset = alignToOffset(CBA, SHeader.sh_addralign,1026RawSec ? RawSec->Offset : std::nullopt);10271028if (RawSec && (RawSec->Content || RawSec->Size)) {1029assert(Symbols.empty());1030SHeader.sh_size = writeContent(CBA, RawSec->Content, RawSec->Size);1031return;1032}10331034std::vector<Elf_Sym> Syms =1035toELFSymbols(Symbols, IsStatic ? DotStrtab : DotDynstr);1036SHeader.sh_size = Syms.size() * sizeof(Elf_Sym);1037CBA.write((const char *)Syms.data(), SHeader.sh_size);1038}10391040template <class ELFT>1041void ELFState<ELFT>::initStrtabSectionHeader(Elf_Shdr &SHeader, StringRef Name,1042StringTableBuilder &STB,1043ContiguousBlobAccumulator &CBA,1044ELFYAML::Section *YAMLSec) {1045SHeader.sh_name = getSectionNameOffset(ELFYAML::dropUniqueSuffix(Name));1046SHeader.sh_type = YAMLSec ? YAMLSec->Type : ELF::SHT_STRTAB;1047SHeader.sh_addralign = YAMLSec ? (uint64_t)YAMLSec->AddressAlign : 1;10481049ELFYAML::RawContentSection *RawSec =1050dyn_cast_or_null<ELFYAML::RawContentSection>(YAMLSec);10511052SHeader.sh_offset = alignToOffset(CBA, SHeader.sh_addralign,1053YAMLSec ? YAMLSec->Offset : std::nullopt);10541055if (RawSec && (RawSec->Content || RawSec->Size)) {1056SHeader.sh_size = writeContent(CBA, RawSec->Content, RawSec->Size);1057} else {1058if (raw_ostream *OS = CBA.getRawOS(STB.getSize()))1059STB.write(*OS);1060SHeader.sh_size = STB.getSize();1061}10621063if (RawSec && RawSec->Info)1064SHeader.sh_info = *RawSec->Info;10651066if (YAMLSec && YAMLSec->Flags)1067SHeader.sh_flags = *YAMLSec->Flags;1068else if (Name == ".dynstr")1069SHeader.sh_flags = ELF::SHF_ALLOC;10701071assignSectionAddress(SHeader, YAMLSec);1072}10731074static bool shouldEmitDWARF(DWARFYAML::Data &DWARF, StringRef Name) {1075SetVector<StringRef> DebugSecNames = DWARF.getNonEmptySectionNames();1076return Name.consume_front(".") && DebugSecNames.count(Name);1077}10781079template <class ELFT>1080Expected<uint64_t> emitDWARF(typename ELFT::Shdr &SHeader, StringRef Name,1081const DWARFYAML::Data &DWARF,1082ContiguousBlobAccumulator &CBA) {1083// We are unable to predict the size of debug data, so we request to write 01084// bytes. This should always return us an output stream unless CBA is already1085// in an error state.1086raw_ostream *OS = CBA.getRawOS(0);1087if (!OS)1088return 0;10891090uint64_t BeginOffset = CBA.tell();10911092auto EmitFunc = DWARFYAML::getDWARFEmitterByName(Name.substr(1));1093if (Error Err = EmitFunc(*OS, DWARF))1094return std::move(Err);10951096return CBA.tell() - BeginOffset;1097}10981099template <class ELFT>1100void ELFState<ELFT>::initDWARFSectionHeader(Elf_Shdr &SHeader, StringRef Name,1101ContiguousBlobAccumulator &CBA,1102ELFYAML::Section *YAMLSec) {1103SHeader.sh_name = getSectionNameOffset(ELFYAML::dropUniqueSuffix(Name));1104SHeader.sh_type = YAMLSec ? YAMLSec->Type : ELF::SHT_PROGBITS;1105SHeader.sh_addralign = YAMLSec ? (uint64_t)YAMLSec->AddressAlign : 1;1106SHeader.sh_offset = alignToOffset(CBA, SHeader.sh_addralign,1107YAMLSec ? YAMLSec->Offset : std::nullopt);11081109ELFYAML::RawContentSection *RawSec =1110dyn_cast_or_null<ELFYAML::RawContentSection>(YAMLSec);1111if (Doc.DWARF && shouldEmitDWARF(*Doc.DWARF, Name)) {1112if (RawSec && (RawSec->Content || RawSec->Size))1113reportError("cannot specify section '" + Name +1114"' contents in the 'DWARF' entry and the 'Content' "1115"or 'Size' in the 'Sections' entry at the same time");1116else {1117if (Expected<uint64_t> ShSizeOrErr =1118emitDWARF<ELFT>(SHeader, Name, *Doc.DWARF, CBA))1119SHeader.sh_size = *ShSizeOrErr;1120else1121reportError(ShSizeOrErr.takeError());1122}1123} else if (RawSec)1124SHeader.sh_size = writeContent(CBA, RawSec->Content, RawSec->Size);1125else1126llvm_unreachable("debug sections can only be initialized via the 'DWARF' "1127"entry or a RawContentSection");11281129if (RawSec && RawSec->Info)1130SHeader.sh_info = *RawSec->Info;11311132if (YAMLSec && YAMLSec->Flags)1133SHeader.sh_flags = *YAMLSec->Flags;1134else if (Name == ".debug_str")1135SHeader.sh_flags = ELF::SHF_MERGE | ELF::SHF_STRINGS;11361137assignSectionAddress(SHeader, YAMLSec);1138}11391140template <class ELFT> void ELFState<ELFT>::reportError(const Twine &Msg) {1141ErrHandler(Msg);1142HasError = true;1143}11441145template <class ELFT> void ELFState<ELFT>::reportError(Error Err) {1146handleAllErrors(std::move(Err), [&](const ErrorInfoBase &Err) {1147reportError(Err.message());1148});1149}11501151template <class ELFT>1152std::vector<Fragment>1153ELFState<ELFT>::getPhdrFragments(const ELFYAML::ProgramHeader &Phdr,1154ArrayRef<Elf_Shdr> SHeaders) {1155std::vector<Fragment> Ret;1156for (const ELFYAML::Chunk *C : Phdr.Chunks) {1157if (const ELFYAML::Fill *F = dyn_cast<ELFYAML::Fill>(C)) {1158Ret.push_back({*F->Offset, F->Size, llvm::ELF::SHT_PROGBITS,1159/*ShAddrAlign=*/1});1160continue;1161}11621163const ELFYAML::Section *S = cast<ELFYAML::Section>(C);1164const Elf_Shdr &H = SHeaders[SN2I.get(S->Name)];1165Ret.push_back({H.sh_offset, H.sh_size, H.sh_type, H.sh_addralign});1166}1167return Ret;1168}11691170template <class ELFT>1171void ELFState<ELFT>::setProgramHeaderLayout(std::vector<Elf_Phdr> &PHeaders,1172std::vector<Elf_Shdr> &SHeaders) {1173uint32_t PhdrIdx = 0;1174for (auto &YamlPhdr : Doc.ProgramHeaders) {1175Elf_Phdr &PHeader = PHeaders[PhdrIdx++];1176std::vector<Fragment> Fragments = getPhdrFragments(YamlPhdr, SHeaders);1177if (!llvm::is_sorted(Fragments, [](const Fragment &A, const Fragment &B) {1178return A.Offset < B.Offset;1179}))1180reportError("sections in the program header with index " +1181Twine(PhdrIdx) + " are not sorted by their file offset");11821183if (YamlPhdr.Offset) {1184if (!Fragments.empty() && *YamlPhdr.Offset > Fragments.front().Offset)1185reportError("'Offset' for segment with index " + Twine(PhdrIdx) +1186" must be less than or equal to the minimum file offset of "1187"all included sections (0x" +1188Twine::utohexstr(Fragments.front().Offset) + ")");1189PHeader.p_offset = *YamlPhdr.Offset;1190} else if (!Fragments.empty()) {1191PHeader.p_offset = Fragments.front().Offset;1192}11931194// Set the file size if not set explicitly.1195if (YamlPhdr.FileSize) {1196PHeader.p_filesz = *YamlPhdr.FileSize;1197} else if (!Fragments.empty()) {1198uint64_t FileSize = Fragments.back().Offset - PHeader.p_offset;1199// SHT_NOBITS sections occupy no physical space in a file, we should not1200// take their sizes into account when calculating the file size of a1201// segment.1202if (Fragments.back().Type != llvm::ELF::SHT_NOBITS)1203FileSize += Fragments.back().Size;1204PHeader.p_filesz = FileSize;1205}12061207// Find the maximum offset of the end of a section in order to set p_memsz.1208uint64_t MemOffset = PHeader.p_offset;1209for (const Fragment &F : Fragments)1210MemOffset = std::max(MemOffset, F.Offset + F.Size);1211// Set the memory size if not set explicitly.1212PHeader.p_memsz = YamlPhdr.MemSize ? uint64_t(*YamlPhdr.MemSize)1213: MemOffset - PHeader.p_offset;12141215if (YamlPhdr.Align) {1216PHeader.p_align = *YamlPhdr.Align;1217} else {1218// Set the alignment of the segment to be the maximum alignment of the1219// sections so that by default the segment has a valid and sensible1220// alignment.1221PHeader.p_align = 1;1222for (const Fragment &F : Fragments)1223PHeader.p_align = std::max((uint64_t)PHeader.p_align, F.AddrAlign);1224}1225}1226}12271228bool llvm::ELFYAML::shouldAllocateFileSpace(1229ArrayRef<ELFYAML::ProgramHeader> Phdrs, const ELFYAML::NoBitsSection &S) {1230for (const ELFYAML::ProgramHeader &PH : Phdrs) {1231auto It = llvm::find_if(1232PH.Chunks, [&](ELFYAML::Chunk *C) { return C->Name == S.Name; });1233if (std::any_of(It, PH.Chunks.end(), [](ELFYAML::Chunk *C) {1234return (isa<ELFYAML::Fill>(C) ||1235cast<ELFYAML::Section>(C)->Type != ELF::SHT_NOBITS);1236}))1237return true;1238}1239return false;1240}12411242template <class ELFT>1243void ELFState<ELFT>::writeSectionContent(Elf_Shdr &SHeader,1244const ELFYAML::NoBitsSection &S,1245ContiguousBlobAccumulator &CBA) {1246if (!S.Size)1247return;12481249SHeader.sh_size = *S.Size;12501251// When a nobits section is followed by a non-nobits section or fill1252// in the same segment, we allocate the file space for it. This behavior1253// matches linkers.1254if (shouldAllocateFileSpace(Doc.ProgramHeaders, S))1255CBA.writeZeros(*S.Size);1256}12571258template <class ELFT>1259void ELFState<ELFT>::writeSectionContent(1260Elf_Shdr &SHeader, const ELFYAML::RawContentSection &Section,1261ContiguousBlobAccumulator &CBA) {1262if (Section.Info)1263SHeader.sh_info = *Section.Info;1264}12651266static bool isMips64EL(const ELFYAML::Object &Obj) {1267return Obj.getMachine() == llvm::ELF::EM_MIPS &&1268Obj.Header.Class == ELFYAML::ELF_ELFCLASS(ELF::ELFCLASS64) &&1269Obj.Header.Data == ELFYAML::ELF_ELFDATA(ELF::ELFDATA2LSB);1270}12711272template <class ELFT>1273void ELFState<ELFT>::writeSectionContent(1274Elf_Shdr &SHeader, const ELFYAML::RelocationSection &Section,1275ContiguousBlobAccumulator &CBA) {1276assert((Section.Type == llvm::ELF::SHT_REL ||1277Section.Type == llvm::ELF::SHT_RELA ||1278Section.Type == llvm::ELF::SHT_CREL) &&1279"Section type is not SHT_REL nor SHT_RELA");12801281if (!Section.RelocatableSec.empty())1282SHeader.sh_info = toSectionIndex(Section.RelocatableSec, Section.Name);12831284if (!Section.Relocations)1285return;12861287const bool IsCrel = Section.Type == llvm::ELF::SHT_CREL;1288const bool IsRela = Section.Type == llvm::ELF::SHT_RELA;1289typename ELFT::uint OffsetMask = 8, Offset = 0, Addend = 0;1290uint32_t SymIdx = 0, Type = 0;1291uint64_t CurrentOffset = CBA.getOffset();1292if (IsCrel)1293for (const ELFYAML::Relocation &Rel : *Section.Relocations)1294OffsetMask |= Rel.Offset;1295const int Shift = llvm::countr_zero(OffsetMask);1296if (IsCrel)1297CBA.writeULEB128(Section.Relocations->size() * 8 + ELF::CREL_HDR_ADDEND +1298Shift);1299for (const ELFYAML::Relocation &Rel : *Section.Relocations) {1300const bool IsDynamic = Section.Link && (*Section.Link == ".dynsym");1301uint32_t CurSymIdx =1302Rel.Symbol ? toSymbolIndex(*Rel.Symbol, Section.Name, IsDynamic) : 0;1303if (IsCrel) {1304// The delta offset and flags member may be larger than uint64_t. Special1305// case the first byte (3 flag bits and 4 offset bits). Other ULEB1281306// bytes encode the remaining delta offset bits.1307auto DeltaOffset =1308(static_cast<typename ELFT::uint>(Rel.Offset) - Offset) >> Shift;1309Offset = Rel.Offset;1310uint8_t B =1311DeltaOffset * 8 + (SymIdx != CurSymIdx) + (Type != Rel.Type ? 2 : 0) +1312(Addend != static_cast<typename ELFT::uint>(Rel.Addend) ? 4 : 0);1313if (DeltaOffset < 0x10) {1314CBA.write(B);1315} else {1316CBA.write(B | 0x80);1317CBA.writeULEB128(DeltaOffset >> 4);1318}1319// Delta symidx/type/addend members (SLEB128).1320if (B & 1) {1321CBA.writeSLEB128(1322std::make_signed_t<typename ELFT::uint>(CurSymIdx - SymIdx));1323SymIdx = CurSymIdx;1324}1325if (B & 2) {1326CBA.writeSLEB128(static_cast<int32_t>(Rel.Type - Type));1327Type = Rel.Type;1328}1329if (B & 4) {1330CBA.writeSLEB128(1331std::make_signed_t<typename ELFT::uint>(Rel.Addend - Addend));1332Addend = Rel.Addend;1333}1334} else if (IsRela) {1335Elf_Rela REntry;1336zero(REntry);1337REntry.r_offset = Rel.Offset;1338REntry.r_addend = Rel.Addend;1339REntry.setSymbolAndType(CurSymIdx, Rel.Type, isMips64EL(Doc));1340CBA.write((const char *)&REntry, sizeof(REntry));1341} else {1342Elf_Rel REntry;1343zero(REntry);1344REntry.r_offset = Rel.Offset;1345REntry.setSymbolAndType(CurSymIdx, Rel.Type, isMips64EL(Doc));1346CBA.write((const char *)&REntry, sizeof(REntry));1347}1348}13491350SHeader.sh_size = CBA.getOffset() - CurrentOffset;1351}13521353template <class ELFT>1354void ELFState<ELFT>::writeSectionContent(Elf_Shdr &SHeader,1355const ELFYAML::RelrSection &Section,1356ContiguousBlobAccumulator &CBA) {1357if (!Section.Entries)1358return;13591360for (llvm::yaml::Hex64 E : *Section.Entries) {1361if (!ELFT::Is64Bits && E > UINT32_MAX)1362reportError(Section.Name + ": the value is too large for 32-bits: 0x" +1363Twine::utohexstr(E));1364CBA.write<uintX_t>(E, ELFT::Endianness);1365}13661367SHeader.sh_size = sizeof(uintX_t) * Section.Entries->size();1368}13691370template <class ELFT>1371void ELFState<ELFT>::writeSectionContent(1372Elf_Shdr &SHeader, const ELFYAML::SymtabShndxSection &Shndx,1373ContiguousBlobAccumulator &CBA) {1374if (Shndx.Content || Shndx.Size) {1375SHeader.sh_size = writeContent(CBA, Shndx.Content, Shndx.Size);1376return;1377}13781379if (!Shndx.Entries)1380return;13811382for (uint32_t E : *Shndx.Entries)1383CBA.write<uint32_t>(E, ELFT::Endianness);1384SHeader.sh_size = Shndx.Entries->size() * SHeader.sh_entsize;1385}13861387template <class ELFT>1388void ELFState<ELFT>::writeSectionContent(Elf_Shdr &SHeader,1389const ELFYAML::GroupSection &Section,1390ContiguousBlobAccumulator &CBA) {1391assert(Section.Type == llvm::ELF::SHT_GROUP &&1392"Section type is not SHT_GROUP");13931394if (Section.Signature)1395SHeader.sh_info =1396toSymbolIndex(*Section.Signature, Section.Name, /*IsDynamic=*/false);13971398if (!Section.Members)1399return;14001401for (const ELFYAML::SectionOrType &Member : *Section.Members) {1402unsigned int SectionIndex = 0;1403if (Member.sectionNameOrType == "GRP_COMDAT")1404SectionIndex = llvm::ELF::GRP_COMDAT;1405else1406SectionIndex = toSectionIndex(Member.sectionNameOrType, Section.Name);1407CBA.write<uint32_t>(SectionIndex, ELFT::Endianness);1408}1409SHeader.sh_size = SHeader.sh_entsize * Section.Members->size();1410}14111412template <class ELFT>1413void ELFState<ELFT>::writeSectionContent(Elf_Shdr &SHeader,1414const ELFYAML::SymverSection &Section,1415ContiguousBlobAccumulator &CBA) {1416if (!Section.Entries)1417return;14181419for (uint16_t Version : *Section.Entries)1420CBA.write<uint16_t>(Version, ELFT::Endianness);1421SHeader.sh_size = Section.Entries->size() * SHeader.sh_entsize;1422}14231424template <class ELFT>1425void ELFState<ELFT>::writeSectionContent(1426Elf_Shdr &SHeader, const ELFYAML::StackSizesSection &Section,1427ContiguousBlobAccumulator &CBA) {1428if (!Section.Entries)1429return;14301431for (const ELFYAML::StackSizeEntry &E : *Section.Entries) {1432CBA.write<uintX_t>(E.Address, ELFT::Endianness);1433SHeader.sh_size += sizeof(uintX_t) + CBA.writeULEB128(E.Size);1434}1435}14361437template <class ELFT>1438void ELFState<ELFT>::writeSectionContent(1439Elf_Shdr &SHeader, const ELFYAML::BBAddrMapSection &Section,1440ContiguousBlobAccumulator &CBA) {1441if (!Section.Entries) {1442if (Section.PGOAnalyses)1443WithColor::warning()1444<< "PGOAnalyses should not exist in SHT_LLVM_BB_ADDR_MAP when "1445"Entries does not exist";1446return;1447}14481449const std::vector<ELFYAML::PGOAnalysisMapEntry> *PGOAnalyses = nullptr;1450if (Section.PGOAnalyses) {1451if (Section.Entries->size() != Section.PGOAnalyses->size())1452WithColor::warning() << "PGOAnalyses must be the same length as Entries "1453"in SHT_LLVM_BB_ADDR_MAP";1454else1455PGOAnalyses = &Section.PGOAnalyses.value();1456}14571458for (const auto &[Idx, E] : llvm::enumerate(*Section.Entries)) {1459// Write version and feature values.1460if (Section.Type == llvm::ELF::SHT_LLVM_BB_ADDR_MAP) {1461if (E.Version > 2)1462WithColor::warning() << "unsupported SHT_LLVM_BB_ADDR_MAP version: "1463<< static_cast<int>(E.Version)1464<< "; encoding using the most recent version";1465CBA.write(E.Version);1466CBA.write(E.Feature);1467SHeader.sh_size += 2;1468}1469auto FeatureOrErr = llvm::object::BBAddrMap::Features::decode(E.Feature);1470bool MultiBBRangeFeatureEnabled = false;1471if (!FeatureOrErr)1472WithColor::warning() << toString(FeatureOrErr.takeError());1473else1474MultiBBRangeFeatureEnabled = FeatureOrErr->MultiBBRange;1475bool MultiBBRange =1476MultiBBRangeFeatureEnabled ||1477(E.NumBBRanges.has_value() && E.NumBBRanges.value() != 1) ||1478(E.BBRanges && E.BBRanges->size() != 1);1479if (MultiBBRange && !MultiBBRangeFeatureEnabled)1480WithColor::warning() << "feature value(" << E.Feature1481<< ") does not support multiple BB ranges.";1482if (MultiBBRange) {1483// Write the number of basic block ranges, which is overridden by the1484// 'NumBBRanges' field when specified.1485uint64_t NumBBRanges =1486E.NumBBRanges.value_or(E.BBRanges ? E.BBRanges->size() : 0);1487SHeader.sh_size += CBA.writeULEB128(NumBBRanges);1488}1489if (!E.BBRanges)1490continue;1491uint64_t TotalNumBlocks = 0;1492for (const ELFYAML::BBAddrMapEntry::BBRangeEntry &BBR : *E.BBRanges) {1493// Write the base address of the range.1494CBA.write<uintX_t>(BBR.BaseAddress, ELFT::Endianness);1495// Write number of BBEntries (number of basic blocks in this basic block1496// range). This is overridden by the 'NumBlocks' YAML field when1497// specified.1498uint64_t NumBlocks =1499BBR.NumBlocks.value_or(BBR.BBEntries ? BBR.BBEntries->size() : 0);1500SHeader.sh_size += sizeof(uintX_t) + CBA.writeULEB128(NumBlocks);1501// Write all BBEntries in this BBRange.1502if (!BBR.BBEntries)1503continue;1504for (const ELFYAML::BBAddrMapEntry::BBEntry &BBE : *BBR.BBEntries) {1505++TotalNumBlocks;1506if (Section.Type == llvm::ELF::SHT_LLVM_BB_ADDR_MAP && E.Version > 1)1507SHeader.sh_size += CBA.writeULEB128(BBE.ID);1508SHeader.sh_size += CBA.writeULEB128(BBE.AddressOffset);1509SHeader.sh_size += CBA.writeULEB128(BBE.Size);1510SHeader.sh_size += CBA.writeULEB128(BBE.Metadata);1511}1512}1513if (!PGOAnalyses)1514continue;1515const ELFYAML::PGOAnalysisMapEntry &PGOEntry = PGOAnalyses->at(Idx);15161517if (PGOEntry.FuncEntryCount)1518SHeader.sh_size += CBA.writeULEB128(*PGOEntry.FuncEntryCount);15191520if (!PGOEntry.PGOBBEntries)1521continue;15221523const auto &PGOBBEntries = PGOEntry.PGOBBEntries.value();1524if (TotalNumBlocks != PGOBBEntries.size()) {1525WithColor::warning() << "PBOBBEntries must be the same length as "1526"BBEntries in SHT_LLVM_BB_ADDR_MAP.\n"1527<< "Mismatch on function with address: "1528<< E.getFunctionAddress();1529continue;1530}15311532for (const auto &PGOBBE : PGOBBEntries) {1533if (PGOBBE.BBFreq)1534SHeader.sh_size += CBA.writeULEB128(*PGOBBE.BBFreq);1535if (PGOBBE.Successors) {1536SHeader.sh_size += CBA.writeULEB128(PGOBBE.Successors->size());1537for (const auto &[ID, BrProb] : *PGOBBE.Successors) {1538SHeader.sh_size += CBA.writeULEB128(ID);1539SHeader.sh_size += CBA.writeULEB128(BrProb);1540}1541}1542}1543}1544}15451546template <class ELFT>1547void ELFState<ELFT>::writeSectionContent(1548Elf_Shdr &SHeader, const ELFYAML::LinkerOptionsSection &Section,1549ContiguousBlobAccumulator &CBA) {1550if (!Section.Options)1551return;15521553for (const ELFYAML::LinkerOption &LO : *Section.Options) {1554CBA.write(LO.Key.data(), LO.Key.size());1555CBA.write('\0');1556CBA.write(LO.Value.data(), LO.Value.size());1557CBA.write('\0');1558SHeader.sh_size += (LO.Key.size() + LO.Value.size() + 2);1559}1560}15611562template <class ELFT>1563void ELFState<ELFT>::writeSectionContent(1564Elf_Shdr &SHeader, const ELFYAML::DependentLibrariesSection &Section,1565ContiguousBlobAccumulator &CBA) {1566if (!Section.Libs)1567return;15681569for (StringRef Lib : *Section.Libs) {1570CBA.write(Lib.data(), Lib.size());1571CBA.write('\0');1572SHeader.sh_size += Lib.size() + 1;1573}1574}15751576template <class ELFT>1577uint64_t1578ELFState<ELFT>::alignToOffset(ContiguousBlobAccumulator &CBA, uint64_t Align,1579std::optional<llvm::yaml::Hex64> Offset) {1580uint64_t CurrentOffset = CBA.getOffset();1581uint64_t AlignedOffset;15821583if (Offset) {1584if ((uint64_t)*Offset < CurrentOffset) {1585reportError("the 'Offset' value (0x" +1586Twine::utohexstr((uint64_t)*Offset) + ") goes backward");1587return CurrentOffset;1588}15891590// We ignore an alignment when an explicit offset has been requested.1591AlignedOffset = *Offset;1592} else {1593AlignedOffset = alignTo(CurrentOffset, std::max(Align, (uint64_t)1));1594}15951596CBA.writeZeros(AlignedOffset - CurrentOffset);1597return AlignedOffset;1598}15991600template <class ELFT>1601void ELFState<ELFT>::writeSectionContent(1602Elf_Shdr &SHeader, const ELFYAML::CallGraphProfileSection &Section,1603ContiguousBlobAccumulator &CBA) {1604if (!Section.Entries)1605return;16061607for (const ELFYAML::CallGraphEntryWeight &E : *Section.Entries) {1608CBA.write<uint64_t>(E.Weight, ELFT::Endianness);1609SHeader.sh_size += sizeof(object::Elf_CGProfile_Impl<ELFT>);1610}1611}16121613template <class ELFT>1614void ELFState<ELFT>::writeSectionContent(Elf_Shdr &SHeader,1615const ELFYAML::HashSection &Section,1616ContiguousBlobAccumulator &CBA) {1617if (!Section.Bucket)1618return;16191620CBA.write<uint32_t>(1621Section.NBucket.value_or(llvm::yaml::Hex64(Section.Bucket->size())),1622ELFT::Endianness);1623CBA.write<uint32_t>(1624Section.NChain.value_or(llvm::yaml::Hex64(Section.Chain->size())),1625ELFT::Endianness);16261627for (uint32_t Val : *Section.Bucket)1628CBA.write<uint32_t>(Val, ELFT::Endianness);1629for (uint32_t Val : *Section.Chain)1630CBA.write<uint32_t>(Val, ELFT::Endianness);16311632SHeader.sh_size = (2 + Section.Bucket->size() + Section.Chain->size()) * 4;1633}16341635template <class ELFT>1636void ELFState<ELFT>::writeSectionContent(Elf_Shdr &SHeader,1637const ELFYAML::VerdefSection &Section,1638ContiguousBlobAccumulator &CBA) {16391640if (Section.Info)1641SHeader.sh_info = *Section.Info;1642else if (Section.Entries)1643SHeader.sh_info = Section.Entries->size();16441645if (!Section.Entries)1646return;16471648uint64_t AuxCnt = 0;1649for (size_t I = 0; I < Section.Entries->size(); ++I) {1650const ELFYAML::VerdefEntry &E = (*Section.Entries)[I];16511652Elf_Verdef VerDef;1653VerDef.vd_version = E.Version.value_or(1);1654VerDef.vd_flags = E.Flags.value_or(0);1655VerDef.vd_ndx = E.VersionNdx.value_or(0);1656VerDef.vd_hash = E.Hash.value_or(0);1657VerDef.vd_aux = sizeof(Elf_Verdef);1658VerDef.vd_cnt = E.VerNames.size();1659if (I == Section.Entries->size() - 1)1660VerDef.vd_next = 0;1661else1662VerDef.vd_next =1663sizeof(Elf_Verdef) + E.VerNames.size() * sizeof(Elf_Verdaux);1664CBA.write((const char *)&VerDef, sizeof(Elf_Verdef));16651666for (size_t J = 0; J < E.VerNames.size(); ++J, ++AuxCnt) {1667Elf_Verdaux VernAux;1668VernAux.vda_name = DotDynstr.getOffset(E.VerNames[J]);1669if (J == E.VerNames.size() - 1)1670VernAux.vda_next = 0;1671else1672VernAux.vda_next = sizeof(Elf_Verdaux);1673CBA.write((const char *)&VernAux, sizeof(Elf_Verdaux));1674}1675}16761677SHeader.sh_size = Section.Entries->size() * sizeof(Elf_Verdef) +1678AuxCnt * sizeof(Elf_Verdaux);1679}16801681template <class ELFT>1682void ELFState<ELFT>::writeSectionContent(Elf_Shdr &SHeader,1683const ELFYAML::VerneedSection &Section,1684ContiguousBlobAccumulator &CBA) {1685if (Section.Info)1686SHeader.sh_info = *Section.Info;1687else if (Section.VerneedV)1688SHeader.sh_info = Section.VerneedV->size();16891690if (!Section.VerneedV)1691return;16921693uint64_t AuxCnt = 0;1694for (size_t I = 0; I < Section.VerneedV->size(); ++I) {1695const ELFYAML::VerneedEntry &VE = (*Section.VerneedV)[I];16961697Elf_Verneed VerNeed;1698VerNeed.vn_version = VE.Version;1699VerNeed.vn_file = DotDynstr.getOffset(VE.File);1700if (I == Section.VerneedV->size() - 1)1701VerNeed.vn_next = 0;1702else1703VerNeed.vn_next =1704sizeof(Elf_Verneed) + VE.AuxV.size() * sizeof(Elf_Vernaux);1705VerNeed.vn_cnt = VE.AuxV.size();1706VerNeed.vn_aux = sizeof(Elf_Verneed);1707CBA.write((const char *)&VerNeed, sizeof(Elf_Verneed));17081709for (size_t J = 0; J < VE.AuxV.size(); ++J, ++AuxCnt) {1710const ELFYAML::VernauxEntry &VAuxE = VE.AuxV[J];17111712Elf_Vernaux VernAux;1713VernAux.vna_hash = VAuxE.Hash;1714VernAux.vna_flags = VAuxE.Flags;1715VernAux.vna_other = VAuxE.Other;1716VernAux.vna_name = DotDynstr.getOffset(VAuxE.Name);1717if (J == VE.AuxV.size() - 1)1718VernAux.vna_next = 0;1719else1720VernAux.vna_next = sizeof(Elf_Vernaux);1721CBA.write((const char *)&VernAux, sizeof(Elf_Vernaux));1722}1723}17241725SHeader.sh_size = Section.VerneedV->size() * sizeof(Elf_Verneed) +1726AuxCnt * sizeof(Elf_Vernaux);1727}17281729template <class ELFT>1730void ELFState<ELFT>::writeSectionContent(1731Elf_Shdr &SHeader, const ELFYAML::ARMIndexTableSection &Section,1732ContiguousBlobAccumulator &CBA) {1733if (!Section.Entries)1734return;17351736for (const ELFYAML::ARMIndexTableEntry &E : *Section.Entries) {1737CBA.write<uint32_t>(E.Offset, ELFT::Endianness);1738CBA.write<uint32_t>(E.Value, ELFT::Endianness);1739}1740SHeader.sh_size = Section.Entries->size() * 8;1741}17421743template <class ELFT>1744void ELFState<ELFT>::writeSectionContent(Elf_Shdr &SHeader,1745const ELFYAML::MipsABIFlags &Section,1746ContiguousBlobAccumulator &CBA) {1747assert(Section.Type == llvm::ELF::SHT_MIPS_ABIFLAGS &&1748"Section type is not SHT_MIPS_ABIFLAGS");17491750object::Elf_Mips_ABIFlags<ELFT> Flags;1751zero(Flags);1752SHeader.sh_size = SHeader.sh_entsize;17531754Flags.version = Section.Version;1755Flags.isa_level = Section.ISALevel;1756Flags.isa_rev = Section.ISARevision;1757Flags.gpr_size = Section.GPRSize;1758Flags.cpr1_size = Section.CPR1Size;1759Flags.cpr2_size = Section.CPR2Size;1760Flags.fp_abi = Section.FpABI;1761Flags.isa_ext = Section.ISAExtension;1762Flags.ases = Section.ASEs;1763Flags.flags1 = Section.Flags1;1764Flags.flags2 = Section.Flags2;1765CBA.write((const char *)&Flags, sizeof(Flags));1766}17671768template <class ELFT>1769void ELFState<ELFT>::writeSectionContent(Elf_Shdr &SHeader,1770const ELFYAML::DynamicSection &Section,1771ContiguousBlobAccumulator &CBA) {1772assert(Section.Type == llvm::ELF::SHT_DYNAMIC &&1773"Section type is not SHT_DYNAMIC");17741775if (!Section.Entries)1776return;17771778for (const ELFYAML::DynamicEntry &DE : *Section.Entries) {1779CBA.write<uintX_t>(DE.Tag, ELFT::Endianness);1780CBA.write<uintX_t>(DE.Val, ELFT::Endianness);1781}1782SHeader.sh_size = 2 * sizeof(uintX_t) * Section.Entries->size();1783}17841785template <class ELFT>1786void ELFState<ELFT>::writeSectionContent(Elf_Shdr &SHeader,1787const ELFYAML::AddrsigSection &Section,1788ContiguousBlobAccumulator &CBA) {1789if (!Section.Symbols)1790return;17911792for (StringRef Sym : *Section.Symbols)1793SHeader.sh_size +=1794CBA.writeULEB128(toSymbolIndex(Sym, Section.Name, /*IsDynamic=*/false));1795}17961797template <class ELFT>1798void ELFState<ELFT>::writeSectionContent(Elf_Shdr &SHeader,1799const ELFYAML::NoteSection &Section,1800ContiguousBlobAccumulator &CBA) {1801if (!Section.Notes)1802return;18031804uint64_t Offset = CBA.tell();1805for (const ELFYAML::NoteEntry &NE : *Section.Notes) {1806// Write name size.1807if (NE.Name.empty())1808CBA.write<uint32_t>(0, ELFT::Endianness);1809else1810CBA.write<uint32_t>(NE.Name.size() + 1, ELFT::Endianness);18111812// Write description size.1813if (NE.Desc.binary_size() == 0)1814CBA.write<uint32_t>(0, ELFT::Endianness);1815else1816CBA.write<uint32_t>(NE.Desc.binary_size(), ELFT::Endianness);18171818// Write type.1819CBA.write<uint32_t>(NE.Type, ELFT::Endianness);18201821// Write name, null terminator and padding.1822if (!NE.Name.empty()) {1823CBA.write(NE.Name.data(), NE.Name.size());1824CBA.write('\0');1825CBA.padToAlignment(4);1826}18271828// Write description and padding.1829if (NE.Desc.binary_size() != 0) {1830CBA.writeAsBinary(NE.Desc);1831CBA.padToAlignment(4);1832}1833}18341835SHeader.sh_size = CBA.tell() - Offset;1836}18371838template <class ELFT>1839void ELFState<ELFT>::writeSectionContent(Elf_Shdr &SHeader,1840const ELFYAML::GnuHashSection &Section,1841ContiguousBlobAccumulator &CBA) {1842if (!Section.HashBuckets)1843return;18441845if (!Section.Header)1846return;18471848// We write the header first, starting with the hash buckets count. Normally1849// it is the number of entries in HashBuckets, but the "NBuckets" property can1850// be used to override this field, which is useful for producing broken1851// objects.1852if (Section.Header->NBuckets)1853CBA.write<uint32_t>(*Section.Header->NBuckets, ELFT::Endianness);1854else1855CBA.write<uint32_t>(Section.HashBuckets->size(), ELFT::Endianness);18561857// Write the index of the first symbol in the dynamic symbol table accessible1858// via the hash table.1859CBA.write<uint32_t>(Section.Header->SymNdx, ELFT::Endianness);18601861// Write the number of words in the Bloom filter. As above, the "MaskWords"1862// property can be used to set this field to any value.1863if (Section.Header->MaskWords)1864CBA.write<uint32_t>(*Section.Header->MaskWords, ELFT::Endianness);1865else1866CBA.write<uint32_t>(Section.BloomFilter->size(), ELFT::Endianness);18671868// Write the shift constant used by the Bloom filter.1869CBA.write<uint32_t>(Section.Header->Shift2, ELFT::Endianness);18701871// We've finished writing the header. Now write the Bloom filter.1872for (llvm::yaml::Hex64 Val : *Section.BloomFilter)1873CBA.write<uintX_t>(Val, ELFT::Endianness);18741875// Write an array of hash buckets.1876for (llvm::yaml::Hex32 Val : *Section.HashBuckets)1877CBA.write<uint32_t>(Val, ELFT::Endianness);18781879// Write an array of hash values.1880for (llvm::yaml::Hex32 Val : *Section.HashValues)1881CBA.write<uint32_t>(Val, ELFT::Endianness);18821883SHeader.sh_size = 16 /*Header size*/ +1884Section.BloomFilter->size() * sizeof(typename ELFT::uint) +1885Section.HashBuckets->size() * 4 +1886Section.HashValues->size() * 4;1887}18881889template <class ELFT>1890void ELFState<ELFT>::writeFill(ELFYAML::Fill &Fill,1891ContiguousBlobAccumulator &CBA) {1892size_t PatternSize = Fill.Pattern ? Fill.Pattern->binary_size() : 0;1893if (!PatternSize) {1894CBA.writeZeros(Fill.Size);1895return;1896}18971898// Fill the content with the specified pattern.1899uint64_t Written = 0;1900for (; Written + PatternSize <= Fill.Size; Written += PatternSize)1901CBA.writeAsBinary(*Fill.Pattern);1902CBA.writeAsBinary(*Fill.Pattern, Fill.Size - Written);1903}19041905template <class ELFT>1906DenseMap<StringRef, size_t> ELFState<ELFT>::buildSectionHeaderReorderMap() {1907const ELFYAML::SectionHeaderTable &SectionHeaders =1908Doc.getSectionHeaderTable();1909if (SectionHeaders.IsImplicit || SectionHeaders.NoHeaders ||1910SectionHeaders.isDefault())1911return DenseMap<StringRef, size_t>();19121913DenseMap<StringRef, size_t> Ret;1914size_t SecNdx = 0;1915StringSet<> Seen;19161917auto AddSection = [&](const ELFYAML::SectionHeader &Hdr) {1918if (!Ret.try_emplace(Hdr.Name, ++SecNdx).second)1919reportError("repeated section name: '" + Hdr.Name +1920"' in the section header description");1921Seen.insert(Hdr.Name);1922};19231924if (SectionHeaders.Sections)1925for (const ELFYAML::SectionHeader &Hdr : *SectionHeaders.Sections)1926AddSection(Hdr);19271928if (SectionHeaders.Excluded)1929for (const ELFYAML::SectionHeader &Hdr : *SectionHeaders.Excluded)1930AddSection(Hdr);19311932for (const ELFYAML::Section *S : Doc.getSections()) {1933// Ignore special first SHT_NULL section.1934if (S == Doc.getSections().front())1935continue;1936if (!Seen.count(S->Name))1937reportError("section '" + S->Name +1938"' should be present in the 'Sections' or 'Excluded' lists");1939Seen.erase(S->Name);1940}19411942for (const auto &It : Seen)1943reportError("section header contains undefined section '" + It.getKey() +1944"'");1945return Ret;1946}19471948template <class ELFT> void ELFState<ELFT>::buildSectionIndex() {1949// A YAML description can have an explicit section header declaration that1950// allows to change the order of section headers.1951DenseMap<StringRef, size_t> ReorderMap = buildSectionHeaderReorderMap();19521953if (HasError)1954return;19551956// Build excluded section headers map.1957std::vector<ELFYAML::Section *> Sections = Doc.getSections();1958const ELFYAML::SectionHeaderTable &SectionHeaders =1959Doc.getSectionHeaderTable();1960if (SectionHeaders.Excluded)1961for (const ELFYAML::SectionHeader &Hdr : *SectionHeaders.Excluded)1962if (!ExcludedSectionHeaders.insert(Hdr.Name).second)1963llvm_unreachable("buildSectionIndex() failed");19641965if (SectionHeaders.NoHeaders.value_or(false))1966for (const ELFYAML::Section *S : Sections)1967if (!ExcludedSectionHeaders.insert(S->Name).second)1968llvm_unreachable("buildSectionIndex() failed");19691970size_t SecNdx = -1;1971for (const ELFYAML::Section *S : Sections) {1972++SecNdx;19731974size_t Index = ReorderMap.empty() ? SecNdx : ReorderMap.lookup(S->Name);1975if (!SN2I.addName(S->Name, Index))1976llvm_unreachable("buildSectionIndex() failed");19771978if (!ExcludedSectionHeaders.count(S->Name))1979ShStrtabStrings->add(ELFYAML::dropUniqueSuffix(S->Name));1980}1981}19821983template <class ELFT> void ELFState<ELFT>::buildSymbolIndexes() {1984auto Build = [this](ArrayRef<ELFYAML::Symbol> V, NameToIdxMap &Map) {1985for (size_t I = 0, S = V.size(); I < S; ++I) {1986const ELFYAML::Symbol &Sym = V[I];1987if (!Sym.Name.empty() && !Map.addName(Sym.Name, I + 1))1988reportError("repeated symbol name: '" + Sym.Name + "'");1989}1990};19911992if (Doc.Symbols)1993Build(*Doc.Symbols, SymN2I);1994if (Doc.DynamicSymbols)1995Build(*Doc.DynamicSymbols, DynSymN2I);1996}19971998template <class ELFT> void ELFState<ELFT>::finalizeStrings() {1999// Add the regular symbol names to .strtab section.2000if (Doc.Symbols)2001for (const ELFYAML::Symbol &Sym : *Doc.Symbols)2002DotStrtab.add(ELFYAML::dropUniqueSuffix(Sym.Name));2003DotStrtab.finalize();20042005// Add the dynamic symbol names to .dynstr section.2006if (Doc.DynamicSymbols)2007for (const ELFYAML::Symbol &Sym : *Doc.DynamicSymbols)2008DotDynstr.add(ELFYAML::dropUniqueSuffix(Sym.Name));20092010// SHT_GNU_verdef and SHT_GNU_verneed sections might also2011// add strings to .dynstr section.2012for (const ELFYAML::Chunk *Sec : Doc.getSections()) {2013if (auto VerNeed = dyn_cast<ELFYAML::VerneedSection>(Sec)) {2014if (VerNeed->VerneedV) {2015for (const ELFYAML::VerneedEntry &VE : *VerNeed->VerneedV) {2016DotDynstr.add(VE.File);2017for (const ELFYAML::VernauxEntry &Aux : VE.AuxV)2018DotDynstr.add(Aux.Name);2019}2020}2021} else if (auto VerDef = dyn_cast<ELFYAML::VerdefSection>(Sec)) {2022if (VerDef->Entries)2023for (const ELFYAML::VerdefEntry &E : *VerDef->Entries)2024for (StringRef Name : E.VerNames)2025DotDynstr.add(Name);2026}2027}20282029DotDynstr.finalize();20302031// Don't finalize the section header string table a second time if it has2032// already been finalized due to being one of the symbol string tables.2033if (ShStrtabStrings != &DotStrtab && ShStrtabStrings != &DotDynstr)2034ShStrtabStrings->finalize();2035}20362037template <class ELFT>2038bool ELFState<ELFT>::writeELF(raw_ostream &OS, ELFYAML::Object &Doc,2039yaml::ErrorHandler EH, uint64_t MaxSize) {2040ELFState<ELFT> State(Doc, EH);2041if (State.HasError)2042return false;20432044// Build the section index, which adds sections to the section header string2045// table first, so that we can finalize the section header string table.2046State.buildSectionIndex();2047State.buildSymbolIndexes();20482049// Finalize section header string table and the .strtab and .dynstr sections.2050// We do this early because we want to finalize the string table builders2051// before writing the content of the sections that might want to use them.2052State.finalizeStrings();20532054if (State.HasError)2055return false;20562057std::vector<Elf_Phdr> PHeaders;2058State.initProgramHeaders(PHeaders);20592060// XXX: This offset is tightly coupled with the order that we write2061// things to `OS`.2062const size_t SectionContentBeginOffset =2063sizeof(Elf_Ehdr) + sizeof(Elf_Phdr) * Doc.ProgramHeaders.size();2064// It is quite easy to accidentally create output with yaml2obj that is larger2065// than intended, for example, due to an issue in the YAML description.2066// We limit the maximum allowed output size, but also provide a command line2067// option to change this limitation.2068ContiguousBlobAccumulator CBA(SectionContentBeginOffset, MaxSize);20692070std::vector<Elf_Shdr> SHeaders;2071State.initSectionHeaders(SHeaders, CBA);20722073// Now we can decide segment offsets.2074State.setProgramHeaderLayout(PHeaders, SHeaders);20752076bool ReachedLimit = CBA.getOffset() > MaxSize;2077if (Error E = CBA.takeLimitError()) {2078// We report a custom error message instead below.2079consumeError(std::move(E));2080ReachedLimit = true;2081}20822083if (ReachedLimit)2084State.reportError(2085"the desired output size is greater than permitted. Use the "2086"--max-size option to change the limit");20872088if (State.HasError)2089return false;20902091State.writeELFHeader(OS);2092writeArrayData(OS, ArrayRef(PHeaders));20932094const ELFYAML::SectionHeaderTable &SHT = Doc.getSectionHeaderTable();2095if (!SHT.NoHeaders.value_or(false))2096CBA.updateDataAt(*SHT.Offset, SHeaders.data(),2097SHT.getNumHeaders(SHeaders.size()) * sizeof(Elf_Shdr));20982099CBA.writeBlobToStream(OS);2100return true;2101}21022103namespace llvm {2104namespace yaml {21052106bool yaml2elf(llvm::ELFYAML::Object &Doc, raw_ostream &Out, ErrorHandler EH,2107uint64_t MaxSize) {2108bool IsLE = Doc.Header.Data == ELFYAML::ELF_ELFDATA(ELF::ELFDATA2LSB);2109bool Is64Bit = Doc.Header.Class == ELFYAML::ELF_ELFCLASS(ELF::ELFCLASS64);2110if (Is64Bit) {2111if (IsLE)2112return ELFState<object::ELF64LE>::writeELF(Out, Doc, EH, MaxSize);2113return ELFState<object::ELF64BE>::writeELF(Out, Doc, EH, MaxSize);2114}2115if (IsLE)2116return ELFState<object::ELF32LE>::writeELF(Out, Doc, EH, MaxSize);2117return ELFState<object::ELF32BE>::writeELF(Out, Doc, EH, MaxSize);2118}21192120} // namespace yaml2121} // namespace llvm212221232124