[yaml2obj] - Change how we handle implicit sections.

Instead of having the special list of implicit sections,
that are mixed with the sections read from YAML on late
stages, I just create the placeholders and add them to
the main sections list early.

That allows to significantly simplify the code.

Differential revision: https://reviews.llvm.org/D64999

llvm-svn: 366677
This commit is contained in:
George Rimar 2019-07-22 12:01:52 +00:00
parent 5d4bc1293c
commit 13a364e1cc
2 changed files with 41 additions and 37 deletions

View File

@ -148,7 +148,12 @@ struct Section {
// content written.
Optional<llvm::yaml::Hex64> ShSize;
Section(SectionKind Kind) : Kind(Kind) {}
// Usually sections are not created implicitly, but loaded from YAML.
// When they are, this flag is used to signal about that.
bool IsImplicit;
Section(SectionKind Kind, bool IsImplicit = false)
: Kind(Kind), IsImplicit(IsImplicit) {}
virtual ~Section();
};

View File

@ -17,6 +17,7 @@
#include "llvm/MC/StringTableBuilder.h"
#include "llvm/Object/ELFObjectFile.h"
#include "llvm/ObjectYAML/ELFYAML.h"
#include "llvm/ADT/StringSet.h"
#include "llvm/Support/EndianStream.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/WithColor.h"
@ -130,7 +131,7 @@ class ELFState {
NameToIdxMap SN2I;
NameToIdxMap SymN2I;
const ELFYAML::Object &Doc;
ELFYAML::Object &Doc;
bool buildSectionIndex();
bool buildSymbolIndex(ArrayRef<ELFYAML::Symbol> Symbols);
@ -174,18 +175,40 @@ class ELFState {
bool writeSectionContent(Elf_Shdr &SHeader,
const ELFYAML::DynamicSection &Section,
ContiguousBlobAccumulator &CBA);
std::vector<StringRef> implicitSectionNames() const;
ELFState(const ELFYAML::Object &D) : Doc(D) {}
ELFState(ELFYAML::Object &D);
public:
static int writeELF(raw_ostream &OS, const ELFYAML::Object &Doc);
static int writeELF(raw_ostream &OS, ELFYAML::Object &Doc);
private:
void finalizeStrings();
};
} // end anonymous namespace
template <class ELFT>
ELFState<ELFT>::ELFState(ELFYAML::Object &D) : Doc(D) {
StringSet<> DocSections;
for (std::unique_ptr<ELFYAML::Section> &D : Doc.Sections)
if (!D->Name.empty())
DocSections.insert(D->Name);
std::vector<StringRef> ImplicitSections = {".symtab", ".strtab", ".shstrtab"};
if (!Doc.DynamicSymbols.empty())
ImplicitSections.insert(ImplicitSections.end(), {".dynsym", ".dynstr"});
// Insert placeholders for implicit sections that are not
// defined explicitly in YAML.
for (StringRef SecName : ImplicitSections) {
if (DocSections.count(SecName))
continue;
std::unique_ptr<ELFYAML::Section> Sec = llvm::make_unique<ELFYAML::Section>(
ELFYAML::Section::SectionKind::RawContent, true /*IsImplicit*/);
Sec->Name = SecName;
Doc.Sections.push_back(std::move(Sec));
}
}
template <class ELFT>
void ELFState<ELFT>::initELFHeader(Elf_Ehdr &Header) {
using namespace llvm::ELF;
@ -292,36 +315,28 @@ template <class ELFT>
bool ELFState<ELFT>::initSectionHeaders(ELFState<ELFT> &State,
std::vector<Elf_Shdr> &SHeaders,
ContiguousBlobAccumulator &CBA) {
// Build a list of sections we are going to add implicitly.
std::vector<StringRef> ImplicitSections;
for (StringRef Name : State.implicitSectionNames())
if (State.SN2I.get(Name) > Doc.Sections.size())
ImplicitSections.push_back(Name);
// Ensure SHN_UNDEF entry is present. An all-zero section header is a
// valid SHN_UNDEF entry since SHT_NULL == 0.
SHeaders.resize(Doc.Sections.size() + ImplicitSections.size() + 1);
SHeaders.resize(Doc.Sections.size() + 1);
zero(SHeaders[0]);
for (size_t I = 1; I < Doc.Sections.size() + ImplicitSections.size() + 1; ++I) {
for (size_t I = 1; I < Doc.Sections.size() + 1; ++I) {
Elf_Shdr &SHeader = SHeaders[I];
zero(SHeader);
ELFYAML::Section *Sec =
I > Doc.Sections.size() ? nullptr : Doc.Sections[I - 1].get();
ELFYAML::Section *Sec = Doc.Sections[I - 1].get();
// 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.
StringRef SecName =
Sec ? Sec->Name : ImplicitSections[I - Doc.Sections.size() - 1];
if (initImplicitHeader(State, CBA, SHeader, SecName, Sec))
if (initImplicitHeader(State, CBA, SHeader, Sec->Name,
Sec->IsImplicit ? nullptr : Sec))
continue;
assert(Sec && "It can't be null unless it is an implicit section. But all "
"implicit sections should already have been handled above.");
SHeader.sh_name = DotShStrtab.getOffset(dropUniqueSuffix(SecName));
SHeader.sh_name = DotShStrtab.getOffset(dropUniqueSuffix(Sec->Name));
SHeader.sh_type = Sec->Type;
if (Sec->Flags)
SHeader.sh_flags = *Sec->Flags;
@ -940,15 +955,6 @@ template <class ELFT> bool ELFState<ELFT>::buildSectionIndex() {
}
}
auto SecNo = 1 + Doc.Sections.size();
// Add special sections after input sections, if necessary.
for (StringRef Name : implicitSectionNames())
if (SN2I.addName(Name, SecNo)) {
// Account for this section, since it wasn't in the Doc
++SecNo;
DotShStrtab.add(Name);
}
DotShStrtab.finalize();
return true;
}
@ -1007,7 +1013,7 @@ template <class ELFT> void ELFState<ELFT>::finalizeStrings() {
}
template <class ELFT>
int ELFState<ELFT>::writeELF(raw_ostream &OS, const ELFYAML::Object &Doc) {
int ELFState<ELFT>::writeELF(raw_ostream &OS, ELFYAML::Object &Doc) {
ELFState<ELFT> State(Doc);
// Finalize .strtab and .dynstr sections. We do that early because want to
@ -1050,13 +1056,6 @@ int ELFState<ELFT>::writeELF(raw_ostream &OS, const ELFYAML::Object &Doc) {
return 0;
}
template <class ELFT>
std::vector<StringRef> ELFState<ELFT>::implicitSectionNames() const {
if (Doc.DynamicSymbols.empty())
return {".symtab", ".strtab", ".shstrtab"};
return {".symtab", ".strtab", ".shstrtab", ".dynsym", ".dynstr"};
}
int yaml2elf(llvm::ELFYAML::Object &Doc, raw_ostream &Out) {
bool IsLE = Doc.Header.Data == ELFYAML::ELF_ELFDATA(ELF::ELFDATA2LSB);
bool Is64Bit = Doc.Header.Class == ELFYAML::ELF_ELFCLASS(ELF::ELFCLASS64);