summaryrefslogtreecommitdiff
path: root/llvm/lib/ObjectYAML/ELFEmitter.cpp
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2021-02-16 20:13:02 +0000
committerDimitry Andric <dim@FreeBSD.org>2021-02-16 20:13:02 +0000
commitb60736ec1405bb0a8dd40989f67ef4c93da068ab (patch)
tree5c43fbb7c9fc45f0f87e0e6795a86267dbd12f9d /llvm/lib/ObjectYAML/ELFEmitter.cpp
parentcfca06d7963fa0909f90483b42a6d7d194d01e08 (diff)
Diffstat (limited to 'llvm/lib/ObjectYAML/ELFEmitter.cpp')
-rw-r--r--llvm/lib/ObjectYAML/ELFEmitter.cpp675
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;
}