Skip to content

Commit

Permalink
Allow yaml2obj to order implicit sections for ELF
Browse files Browse the repository at this point in the history
Summary:
This change allows yaml input to control the order of implicitly added sections
(`.symtab`, `.strtab`, `.shstrtab`). The order is controlled by adding a
placeholder section of the given name to the Sections field.

This change is to support changes in D39582, where it is desirable to control
the location of the `.dynsym` section.

Reviewers: compnerd, jakehehrlich

Reviewed By: jakehehrlich

Subscribers: llvm-commits

Differential Revision: https://reviews.llvm.org/D39749

llvm-svn: 317622
  • Loading branch information
kastiglione committed Nov 7, 2017
1 parent bbe51d8 commit 3ae8dfd
Show file tree
Hide file tree
Showing 3 changed files with 71 additions and 38 deletions.
2 changes: 1 addition & 1 deletion llvm/lib/ObjectYAML/ELFYAML.cpp
Expand Up @@ -388,7 +388,7 @@ void ScalarEnumerationTraits<ELFYAML::ELF_SHT>::enumeration(
#define ECase(X) IO.enumCase(Value, #X, ELF::X)
ECase(SHT_NULL);
ECase(SHT_PROGBITS);
// No SHT_SYMTAB. Use the top-level `Symbols` key instead.
ECase(SHT_SYMTAB);
// FIXME: Issue a diagnostic with this information.
ECase(SHT_STRTAB);
ECase(SHT_RELA);
Expand Down
29 changes: 29 additions & 0 deletions llvm/test/tools/yaml2obj/section-ordering.yaml
@@ -0,0 +1,29 @@
# Ensures that implicitly added sections can be ordered within Sections.
# RUN: yaml2obj %s -o %t
# RUN: llvm-readobj -sections %t | FileCheck %s

!ELF
FileHeader:
Class: ELFCLASS64
Data: ELFDATA2LSB
Type: ET_EXEC
Machine: EM_X86_64
Sections:
- Name: .text
Type: SHT_PROGBITS
Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- Name: .symtab
Type: SHT_SYMTAB
- Name: .data
Type: SHT_PROGBITS
Flags: [ SHF_ALLOC, SHF_WRITE ]
- Name: .shstrtab
Type: SHT_STRTAB
- Name: .strtab
Type: SHT_STRTAB

# CHECK: Name: .text
# CHECK: Name: .symtab
# CHECK: Name: .data
# CHECK: Name: .shstrtab
# CHECK: Name: .strtab
78 changes: 41 additions & 37 deletions llvm/tools/yaml2obj/yaml2elf.cpp
Expand Up @@ -74,6 +74,13 @@ class NameToIdxMap {
Idx = I->getValue();
return false;
}
/// asserts if name is not present in the map
unsigned get(StringRef Name) const {
unsigned Idx;
assert(!lookup(Name, Idx) && "Expected section not found in index");
return Idx;
}
unsigned size() const { return Map.size(); }
};
} // end anonymous namespace

Expand Down Expand Up @@ -144,19 +151,21 @@ class ELFState {
ContiguousBlobAccumulator &CBA);

// - SHT_NULL entry (placed first, i.e. 0'th entry)
// - symbol table (.symtab) (placed third to last)
// - string table (.strtab) (placed second to last)
// - section header string table (.shstrtab) (placed last)
unsigned getDotSymTabSecNo() const { return Doc.Sections.size() + 1; }
unsigned getDotStrTabSecNo() const { return Doc.Sections.size() + 2; }
unsigned getDotShStrTabSecNo() const { return Doc.Sections.size() + 3; }
unsigned getSectionCount() const { return Doc.Sections.size() + 4; }
// - symbol table (.symtab) (defaults to third to last)
// - string table (.strtab) (defaults to second to last)
// - section header string table (.shstrtab) (defaults to last)
unsigned getDotSymTabSecNo() const { return SN2I.get(".symtab"); }
unsigned getDotStrTabSecNo() const { return SN2I.get(".strtab"); }
unsigned getDotShStrTabSecNo() const { return SN2I.get(".shstrtab"); }
unsigned getSectionCount() const { return SN2I.size() + 1; }

ELFState(const ELFYAML::Object &D) : Doc(D) {}

public:
static int writeELF(raw_ostream &OS, const ELFYAML::Object &Doc);
};

static const char * const ImplicitSecNames[] = {".symtab", ".strtab", ".shstrtab"};
} // end anonymous namespace

template <class ELFT>
Expand Down Expand Up @@ -211,10 +220,6 @@ bool ELFState<ELFT>::initSectionHeaders(std::vector<Elf_Shdr> &SHeaders,
zero(SHeader);
SHeaders.push_back(SHeader);

for (const auto &Sec : Doc.Sections)
DotShStrtab.add(Sec->Name);
DotShStrtab.finalize();

for (const auto &Sec : Doc.Sections) {
zero(SHeader);
SHeader.sh_name = DotShStrtab.getOffset(Sec->Name);
Expand Down Expand Up @@ -547,10 +552,6 @@ bool ELFState<ELFT>::writeSectionContent(Elf_Shdr &SHeader,
}

template <class ELFT> bool ELFState<ELFT>::buildSectionIndex() {
SN2I.addName(".symtab", getDotSymTabSecNo());
SN2I.addName(".strtab", getDotStrTabSecNo());
SN2I.addName(".shstrtab", getDotShStrTabSecNo());

for (unsigned i = 0, e = Doc.Sections.size(); i != e; ++i) {
StringRef Name = Doc.Sections[i]->Name;
if (Name.empty())
Expand All @@ -561,7 +562,19 @@ template <class ELFT> bool ELFState<ELFT>::buildSectionIndex() {
<< "' at YAML section number " << i << ".\n";
return false;
}
DotShStrtab.add(Name);
}

auto SecNo = 1 + Doc.Sections.size();
// Add special sections after input sections, if necessary.
for (const auto &Name : ImplicitSecNames)
if (!SN2I.addName(Name, SecNo)) {
// Account for this section, since it wasn't in the Doc
++SecNo;
DotShStrtab.add(Name);
}

DotShStrtab.finalize();
return true;
}

Expand Down Expand Up @@ -608,32 +621,23 @@ int ELFState<ELFT>::writeELF(raw_ostream &OS, const ELFYAML::Object &Doc) {
Header.e_shentsize * Header.e_shnum;
ContiguousBlobAccumulator CBA(SectionContentBeginOffset);

// Doc might not contain .symtab, .strtab and .shstrtab sections,
// but we will emit them, so make sure to add them to ShStrTabSHeader.
State.DotShStrtab.add(".symtab");
State.DotShStrtab.add(".strtab");
State.DotShStrtab.add(".shstrtab");

std::vector<Elf_Shdr> SHeaders;
SHeaders.reserve(State.SN2I.size());
if(!State.initSectionHeaders(SHeaders, CBA))
return 1;

// .symtab section.
Elf_Shdr SymtabSHeader;
State.initSymtabSectionHeader(SymtabSHeader, CBA);
SHeaders.push_back(SymtabSHeader);

// .strtab string table header.
Elf_Shdr DotStrTabSHeader;
State.initStrtabSectionHeader(DotStrTabSHeader, ".strtab", State.DotStrtab,
CBA);
SHeaders.push_back(DotStrTabSHeader);

// .shstrtab string table header.
Elf_Shdr ShStrTabSHeader;
State.initStrtabSectionHeader(ShStrTabSHeader, ".shstrtab", State.DotShStrtab,
CBA);
SHeaders.push_back(ShStrTabSHeader);
// Populate SHeaders with implicit sections not present in the Doc
for (const auto &Name : ImplicitSecNames)
if (State.SN2I.get(Name) >= SHeaders.size())
SHeaders.push_back({});

// Initialize the implicit sections
auto Index = State.SN2I.get(".symtab");
State.initSymtabSectionHeader(SHeaders[Index], CBA);
Index = State.SN2I.get(".strtab");
State.initStrtabSectionHeader(SHeaders[Index], ".strtab", State.DotStrtab, CBA);
Index = State.SN2I.get(".shstrtab");
State.initStrtabSectionHeader(SHeaders[Index], ".shstrtab", State.DotShStrtab, CBA);

// Now we can decide segment offsets
State.setProgramHeaderLayout(PHeaders, SHeaders);
Expand Down

0 comments on commit 3ae8dfd

Please sign in to comment.