aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDave Lee <davelee.com@gmail.com>2017-11-08 00:58:50 +0000
committerDave Lee <davelee.com@gmail.com>2017-11-08 00:58:50 +0000
commit9fd7184f642d45311e2b514e7a8ba70821d2095f (patch)
tree64ac35eb7e231a9741364e252f44af0838a6afda
parenta932c3f118f553c461d9d38fc00feb72d7784487 (diff)
Reapply: Allow yaml2obj to order implicit sections for ELF
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. This reapplied version fixes: 1. use of a function call within an assert 2. failing lld test which has an unnamed section Additionally, one more test to cover the unnamed section failure. Reviewers: compnerd, jakehehrlich Reviewed By: jakehehrlich Subscribers: llvm-commits Differential Revision: https://reviews.llvm.org/D39749 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@317646 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/ObjectYAML/ELFYAML.cpp2
-rw-r--r--test/tools/yaml2obj/section-ordering.yaml29
-rw-r--r--test/tools/yaml2obj/unnamed-section.yaml14
-rw-r--r--tools/yaml2obj/yaml2elf.cpp79
4 files changed, 86 insertions, 38 deletions
diff --git a/lib/ObjectYAML/ELFYAML.cpp b/lib/ObjectYAML/ELFYAML.cpp
index ada9ff89b8e..38940376de2 100644
--- a/lib/ObjectYAML/ELFYAML.cpp
+++ b/lib/ObjectYAML/ELFYAML.cpp
@@ -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);
diff --git a/test/tools/yaml2obj/section-ordering.yaml b/test/tools/yaml2obj/section-ordering.yaml
new file mode 100644
index 00000000000..885b28a2c09
--- /dev/null
+++ b/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
diff --git a/test/tools/yaml2obj/unnamed-section.yaml b/test/tools/yaml2obj/unnamed-section.yaml
new file mode 100644
index 00000000000..b62bfe7859f
--- /dev/null
+++ b/test/tools/yaml2obj/unnamed-section.yaml
@@ -0,0 +1,14 @@
+# Ensure yaml2obj doesn't crash on unnamed sections
+# RUN: yaml2obj %s
+
+!ELF
+FileHeader:
+ Class: ELFCLASS64
+ Data: ELFDATA2LSB
+ Type: ET_EXEC
+ Machine: EM_X86_64
+Sections:
+ - Type: SHT_PROGBITS
+ - Name: .text
+ Type: SHT_PROGBITS
+ Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
diff --git a/tools/yaml2obj/yaml2elf.cpp b/tools/yaml2obj/yaml2elf.cpp
index 913f19050dc..81edab0dc6a 100644
--- a/tools/yaml2obj/yaml2elf.cpp
+++ b/tools/yaml2obj/yaml2elf.cpp
@@ -74,6 +74,14 @@ public:
Idx = I->getValue();
return false;
}
+ /// asserts if name is not present in the map
+ unsigned get(StringRef Name) const {
+ unsigned Idx = 0;
+ auto missing = lookup(Name, Idx);
+ assert(!missing && "Expected section not found in index");
+ return Idx;
+ }
+ unsigned size() const { return Map.size(); }
};
} // end anonymous namespace
@@ -144,19 +152,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>
@@ -211,10 +221,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);
@@ -547,12 +553,9 @@ 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;
+ DotShStrtab.add(Name);
if (Name.empty())
continue;
// "+ 1" to take into account the SHT_NULL entry.
@@ -562,6 +565,17 @@ template <class ELFT> bool ELFState<ELFT>::buildSectionIndex() {
return false;
}
}
+
+ 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;
}
@@ -608,32 +622,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);