aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/ObjectYAML/ELFEmitter.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/ObjectYAML/ELFEmitter.cpp')
-rw-r--r--llvm/lib/ObjectYAML/ELFEmitter.cpp135
1 files changed, 90 insertions, 45 deletions
diff --git a/llvm/lib/ObjectYAML/ELFEmitter.cpp b/llvm/lib/ObjectYAML/ELFEmitter.cpp
index e477a1b2b8f2..f8f2f0c12020 100644
--- a/llvm/lib/ObjectYAML/ELFEmitter.cpp
+++ b/llvm/lib/ObjectYAML/ELFEmitter.cpp
@@ -18,6 +18,7 @@
#include "llvm/BinaryFormat/ELF.h"
#include "llvm/MC/StringTableBuilder.h"
#include "llvm/Object/ELFObjectFile.h"
+#include "llvm/Object/ELFTypes.h"
#include "llvm/ObjectYAML/DWARFEmitter.h"
#include "llvm/ObjectYAML/DWARFYAML.h"
#include "llvm/ObjectYAML/ELFYAML.h"
@@ -177,15 +178,24 @@ template <class ELFT> class ELFState {
enum class SymtabType { Static, Dynamic };
- /// The future ".strtab" section.
+ /// The future symbol table string section.
StringTableBuilder DotStrtab{StringTableBuilder::ELF};
- /// The future ".shstrtab" section.
+ /// The future section header string table section, if a unique string table
+ /// is needed. Don't reference this variable direectly: use the
+ /// ShStrtabStrings member instead.
StringTableBuilder DotShStrtab{StringTableBuilder::ELF};
- /// The future ".dynstr" section.
+ /// The future dynamic symbol string section.
StringTableBuilder DotDynstr{StringTableBuilder::ELF};
+ /// The name of the section header string table section. If it is .strtab or
+ /// .dynstr, the section header strings will be written to the same string
+ /// table as the static/dynamic symbols respectively. Otherwise a dedicated
+ /// section will be created with that name.
+ StringRef SectionHeaderStringTableName = ".shstrtab";
+ StringTableBuilder *ShStrtabStrings = &DotShStrtab;
+
NameToIdxMap SN2I;
NameToIdxMap SymN2I;
NameToIdxMap DynSymN2I;
@@ -327,6 +337,18 @@ template <class T> static void zero(T &Obj) { memset(&Obj, 0, sizeof(Obj)); }
template <class ELFT>
ELFState<ELFT>::ELFState(ELFYAML::Object &D, yaml::ErrorHandler EH)
: Doc(D), ErrHandler(EH) {
+ // The input may explicitly request to store the section header table strings
+ // in the same string table as dynamic or static symbol names. Set the
+ // ShStrtabStrings member accordingly.
+ if (Doc.Header.SectionHeaderStringTable) {
+ SectionHeaderStringTableName = *Doc.Header.SectionHeaderStringTable;
+ if (*Doc.Header.SectionHeaderStringTable == ".strtab")
+ ShStrtabStrings = &DotStrtab;
+ else if (*Doc.Header.SectionHeaderStringTable == ".dynstr")
+ ShStrtabStrings = &DotDynstr;
+ // Otherwise, the unique table will be used.
+ }
+
std::vector<ELFYAML::Section *> Sections = Doc.getSections();
// Insert SHT_NULL section implicitly when it is not defined in YAML.
if (Sections.empty() || Sections.front()->Type != ELF::SHT_NULL)
@@ -363,19 +385,35 @@ ELFState<ELFT>::ELFState(ELFYAML::Object &D, yaml::ErrorHandler EH)
"' at YAML section/fill number " + Twine(I));
}
- std::vector<StringRef> ImplicitSections;
- if (Doc.DynamicSymbols)
- ImplicitSections.insert(ImplicitSections.end(), {".dynsym", ".dynstr"});
- if (Doc.Symbols)
- ImplicitSections.push_back(".symtab");
+ SmallSetVector<StringRef, 8> ImplicitSections;
+ if (Doc.DynamicSymbols) {
+ if (SectionHeaderStringTableName == ".dynsym")
+ reportError("cannot use '.dynsym' as the section header name table when "
+ "there are dynamic symbols");
+ ImplicitSections.insert(".dynsym");
+ ImplicitSections.insert(".dynstr");
+ }
+ if (Doc.Symbols) {
+ if (SectionHeaderStringTableName == ".symtab")
+ reportError("cannot use '.symtab' as the section header name table when "
+ "there are symbols");
+ ImplicitSections.insert(".symtab");
+ }
if (Doc.DWARF)
for (StringRef DebugSecName : Doc.DWARF->getNonEmptySectionNames()) {
std::string SecName = ("." + DebugSecName).str();
- ImplicitSections.push_back(StringRef(SecName).copy(StringAlloc));
+ // TODO: For .debug_str it should be possible to share the string table,
+ // in the same manner as the symbol string tables.
+ if (SectionHeaderStringTableName == SecName)
+ reportError("cannot use '" + SecName +
+ "' as the section header name table when it is needed for "
+ "DWARF output");
+ ImplicitSections.insert(StringRef(SecName).copy(StringAlloc));
}
- ImplicitSections.insert(ImplicitSections.end(), {".strtab"});
+ // TODO: Only create the .strtab here if any symbols have been requested.
+ ImplicitSections.insert(".strtab");
if (!SecHdrTable || !SecHdrTable->NoHeaders.getValueOr(false))
- ImplicitSections.insert(ImplicitSections.end(), {".shstrtab"});
+ ImplicitSections.insert(SectionHeaderStringTableName);
// Insert placeholders for implicit sections that are not
// defined explicitly in YAML.
@@ -387,7 +425,9 @@ ELFState<ELFT>::ELFState(ELFYAML::Object &D, yaml::ErrorHandler EH)
ELFYAML::Chunk::ChunkKind::RawContent, true /*IsImplicit*/);
Sec->Name = SecName;
- if (SecName == ".dynsym")
+ if (SecName == SectionHeaderStringTableName)
+ Sec->Type = ELF::SHT_STRTAB;
+ else if (SecName == ".dynsym")
Sec->Type = ELF::SHT_DYNSYM;
else if (SecName == ".symtab")
Sec->Type = ELF::SHT_SYMTAB;
@@ -480,8 +520,9 @@ void ELFState<ELFT>::writeELFHeader(raw_ostream &OS) {
if (Doc.Header.EShStrNdx)
Header.e_shstrndx = *Doc.Header.EShStrNdx;
- else if (SectionHeaders.Offset && !ExcludedSectionHeaders.count(".shstrtab"))
- Header.e_shstrndx = SN2I.get(".shstrtab");
+ else if (SectionHeaders.Offset &&
+ !ExcludedSectionHeaders.count(SectionHeaderStringTableName))
+ Header.e_shstrndx = SN2I.get(SectionHeaderStringTableName);
else
Header.e_shstrndx = 0;
@@ -555,14 +596,15 @@ unsigned ELFState<ELFT>::toSectionIndex(StringRef S, StringRef LocSec,
const ELFYAML::SectionHeaderTable &SectionHeaders =
Doc.getSectionHeaderTable();
if (SectionHeaders.IsImplicit ||
- (SectionHeaders.NoHeaders && !SectionHeaders.NoHeaders.getValue()))
+ (SectionHeaders.NoHeaders && !SectionHeaders.NoHeaders.getValue()) ||
+ SectionHeaders.isDefault())
return Index;
assert(!SectionHeaders.NoHeaders.getValueOr(false) ||
!SectionHeaders.Sections);
size_t FirstExcluded =
SectionHeaders.Sections ? SectionHeaders.Sections->size() : 0;
- if (Index >= FirstExcluded) {
+ if (Index > FirstExcluded) {
if (LocSym.empty())
reportError("unable to link '" + LocSec + "' to excluded section '" + S +
"'");
@@ -614,16 +656,16 @@ bool ELFState<ELFT>::initImplicitHeader(ContiguousBlobAccumulator &CBA,
if (Header.sh_offset)
return false;
- if (SecName == ".symtab")
- initSymtabSectionHeader(Header, SymtabType::Static, CBA, YAMLSec);
- else if (SecName == ".strtab")
+ if (SecName == ".strtab")
initStrtabSectionHeader(Header, SecName, DotStrtab, CBA, YAMLSec);
- else if (SecName == ".shstrtab")
- initStrtabSectionHeader(Header, SecName, DotShStrtab, CBA, YAMLSec);
- else if (SecName == ".dynsym")
- initSymtabSectionHeader(Header, SymtabType::Dynamic, CBA, YAMLSec);
else if (SecName == ".dynstr")
initStrtabSectionHeader(Header, SecName, DotDynstr, CBA, YAMLSec);
+ else if (SecName == SectionHeaderStringTableName)
+ initStrtabSectionHeader(Header, SecName, *ShStrtabStrings, CBA, YAMLSec);
+ else if (SecName == ".symtab")
+ initSymtabSectionHeader(Header, SymtabType::Static, CBA, YAMLSec);
+ else if (SecName == ".dynsym")
+ initSymtabSectionHeader(Header, SymtabType::Dynamic, CBA, YAMLSec);
else if (SecName.startswith(".debug_")) {
// If a ".debug_*" section's type is a preserved one, e.g., SHT_DYNAMIC, we
// will not treat it as a debug section.
@@ -670,7 +712,7 @@ uint64_t ELFState<ELFT>::getSectionNameOffset(StringRef Name) {
// the string table.
if (ExcludedSectionHeaders.count(Name))
return 0;
- return DotShStrtab.getOffset(Name);
+ return ShStrtabStrings->getOffset(Name);
}
static uint64_t writeContent(ContiguousBlobAccumulator &CBA,
@@ -994,7 +1036,7 @@ void ELFState<ELFT>::initStrtabSectionHeader(Elf_Shdr &SHeader, StringRef Name,
StringTableBuilder &STB,
ContiguousBlobAccumulator &CBA,
ELFYAML::Section *YAMLSec) {
- SHeader.sh_name = getSectionNameOffset(Name);
+ SHeader.sh_name = getSectionNameOffset(ELFYAML::dropUniqueSuffix(Name));
SHeader.sh_type = YAMLSec ? YAMLSec->Type : ELF::SHT_STRTAB;
SHeader.sh_addralign = YAMLSec ? (uint64_t)YAMLSec->AddressAlign : 1;
@@ -1357,12 +1399,14 @@ void ELFState<ELFT>::writeSectionContent(
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;
+ // Write number of BBEntries (number of basic blocks in the function). This
+ // is overridden by the 'NumBlocks' YAML field when specified.
+ uint64_t NumBlocks =
+ E.NumBlocks.getValueOr(E.BBEntries ? E.BBEntries->size() : 0);
SHeader.sh_size += sizeof(uintX_t) + CBA.writeULEB128(NumBlocks);
- if (!NumBlocks)
- continue;
// Write all BBEntries.
+ if (!E.BBEntries)
+ continue;
for (const ELFYAML::BBAddrMapEntry::BBEntry &BBE : *E.BBEntries)
SHeader.sh_size += CBA.writeULEB128(BBE.AddressOffset) +
CBA.writeULEB128(BBE.Size) +
@@ -1431,14 +1475,9 @@ void ELFState<ELFT>::writeSectionContent(
if (!Section.Entries)
return;
- for (const ELFYAML::CallGraphEntry &E : *Section.Entries) {
- unsigned From = toSymbolIndex(E.From, Section.Name, /*IsDynamic=*/false);
- unsigned To = toSymbolIndex(E.To, Section.Name, /*IsDynamic=*/false);
-
- CBA.write<uint32_t>(From, ELFT::TargetEndianness);
- CBA.write<uint32_t>(To, ELFT::TargetEndianness);
+ for (const ELFYAML::CallGraphEntryWeight &E : *Section.Entries) {
CBA.write<uint64_t>(E.Weight, ELFT::TargetEndianness);
- SHeader.sh_size += 16;
+ SHeader.sh_size += sizeof(object::Elf_CGProfile_Impl<ELFT>);
}
}
@@ -1744,7 +1783,8 @@ template <class ELFT>
DenseMap<StringRef, size_t> ELFState<ELFT>::buildSectionHeaderReorderMap() {
const ELFYAML::SectionHeaderTable &SectionHeaders =
Doc.getSectionHeaderTable();
- if (SectionHeaders.IsImplicit || SectionHeaders.NoHeaders)
+ if (SectionHeaders.IsImplicit || SectionHeaders.NoHeaders ||
+ SectionHeaders.isDefault())
return DenseMap<StringRef, size_t>();
DenseMap<StringRef, size_t> Ret;
@@ -1813,10 +1853,8 @@ template <class ELFT> void ELFState<ELFT>::buildSectionIndex() {
llvm_unreachable("buildSectionIndex() failed");
if (!ExcludedSectionHeaders.count(S->Name))
- DotShStrtab.add(ELFYAML::dropUniqueSuffix(S->Name));
+ ShStrtabStrings->add(ELFYAML::dropUniqueSuffix(S->Name));
}
-
- DotShStrtab.finalize();
}
template <class ELFT> void ELFState<ELFT>::buildSymbolIndexes() {
@@ -1866,6 +1904,11 @@ template <class ELFT> void ELFState<ELFT>::finalizeStrings() {
}
DotDynstr.finalize();
+
+ // Don't finalize the section header string table a second time if it has
+ // already been finalized due to being one of the symbol string tables.
+ if (ShStrtabStrings != &DotStrtab && ShStrtabStrings != &DotDynstr)
+ ShStrtabStrings->finalize();
}
template <class ELFT>
@@ -1875,14 +1918,16 @@ bool ELFState<ELFT>::writeELF(raw_ostream &OS, ELFYAML::Object &Doc,
if (State.HasError)
return false;
- // Finalize .strtab and .dynstr sections. We do that early because want to
- // finalize the string table builders before writing the content of the
- // sections that might want to use them.
- State.finalizeStrings();
-
+ // Build the section index, which adds sections to the section header string
+ // table first, so that we can finalize the section header string table.
State.buildSectionIndex();
State.buildSymbolIndexes();
+ // Finalize section header string table and the .strtab and .dynstr sections.
+ // We do this early because we want to finalize the string table builders
+ // before writing the content of the sections that might want to use them.
+ State.finalizeStrings();
+
if (State.HasError)
return false;