]> granicus.if.org Git - llvm/commitdiff
[llvm-objcopy]Allow llvm-objcopy to be used on an ELF file with no section headers
authorJames Henderson <jh7370@my.bristol.ac.uk>
Tue, 2 Apr 2019 14:11:13 +0000 (14:11 +0000)
committerJames Henderson <jh7370@my.bristol.ac.uk>
Tue, 2 Apr 2019 14:11:13 +0000 (14:11 +0000)
This patch fixes https://bugs.llvm.org/show_bug.cgi?id=41293 and
https://bugs.llvm.org/show_bug.cgi?id=41045. llvm-objcopy assumed that
it could always read a section header string table. This isn't the case
when the sections were previously all stripped, and the e_shstrndx field
was set to 0. This patch fixes this. It also fixes a double space in an
error message relating to this issue, and prevents llvm-objcopy from
adding extra space for non-existent section headers, meaning that
--strip-sections on the output of a previous --strip-sections run
produces identical output, simplifying the test.

Reviewed by: rupprecht, grimar

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

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@357475 91177308-0d34-0410-b5e6-96231b3b80d8

test/tools/llvm-objcopy/ELF/copy-after-strip-sections.test [new file with mode: 0644]
tools/llvm-objcopy/ELF/Object.cpp
tools/llvm-objcopy/ELF/Object.h

diff --git a/test/tools/llvm-objcopy/ELF/copy-after-strip-sections.test b/test/tools/llvm-objcopy/ELF/copy-after-strip-sections.test
new file mode 100644 (file)
index 0000000..3b61649
--- /dev/null
@@ -0,0 +1,26 @@
+# llvm-objcopy's --strip-sections removes the section headers. It should be
+# possible to run the tool on the output after this operation. Performing any
+# subsequent stripping operation, or copying the object, should produce
+# identical output.
+
+# RUN: yaml2obj %s -o %t.in
+# RUN: llvm-objcopy %t.in %t.stripped --strip-sections
+# RUN: llvm-objcopy %t.stripped %t.stripped2 --strip-sections
+# RUN: llvm-objcopy %t.stripped2 %t.out
+# RUN: cmp %t.stripped %t.stripped2
+# RUN: cmp %t.stripped %t.out
+
+--- !ELF
+FileHeader:
+  Class:   ELFCLASS64
+  Data:    ELFDATA2LSB
+  Type:    ET_EXEC
+  Machine: EM_X86_64
+Sections:
+  - Name: .text
+    Type: SHT_PROGBITS
+    Content: 'facefeed'
+ProgramHeaders:
+  - Type: PT_LOAD
+    Sections:
+      - Section: .text
index 321adf6fff0fc9f90906d764b57179ecfb40720a..de51851ecfe508d55e223276d16ee146c0cbb145 100644 (file)
@@ -1212,13 +1212,16 @@ template <class ELFT> void ELFBuilder<ELFT>::build() {
   if (ShstrIndex == SHN_XINDEX)
     ShstrIndex = unwrapOrError(ElfFile.getSection(0))->sh_link;
 
-  Obj.SectionNames =
-      Obj.sections().template getSectionOfType<StringTableSection>(
-          ShstrIndex,
-          "e_shstrndx field value " + Twine(Ehdr.e_shstrndx) +
-              " in elf header " + " is invalid",
-          "e_shstrndx field value " + Twine(Ehdr.e_shstrndx) +
-              " in elf header " + " is not a string table");
+  if (ShstrIndex == SHN_UNDEF)
+    Obj.HadShdrs = false;
+  else
+    Obj.SectionNames =
+        Obj.sections().template getSectionOfType<StringTableSection>(
+            ShstrIndex,
+            "e_shstrndx field value " + Twine(Ehdr.e_shstrndx) +
+                " in elf header is invalid",
+            "e_shstrndx field value " + Twine(Ehdr.e_shstrndx) +
+                " in elf header is not a string table");
 }
 
 Writer::~Writer() {}
@@ -1372,6 +1375,10 @@ template <class ELFT> void ELFWriter<ELFT>::writeSegmentData() {
   }
 }
 
+template <class ELFT>
+ELFWriter<ELFT>::ELFWriter(Object &Obj, Buffer &Buf, bool WSH)
+    : Writer(Obj, Buf), WriteSectionHeaders(WSH && Obj.HadShdrs) {}
+
 Error Object::removeSections(
     std::function<bool(const SectionBase &)> ToRemove) {
 
@@ -1558,9 +1565,10 @@ template <class ELFT> void ELFWriter<ELFT>::assignOffsets() {
 template <class ELFT> size_t ELFWriter<ELFT>::totalSize() const {
   // We already have the section header offset so we can calculate the total
   // size by just adding up the size of each section header.
-  auto NullSectionSize = WriteSectionHeaders ? sizeof(Elf_Shdr) : 0;
-  return Obj.SHOffset + Obj.sections().size() * sizeof(Elf_Shdr) +
-         NullSectionSize;
+  if (!WriteSectionHeaders)
+    return Obj.SHOffset;
+  size_t ShdrCount = Obj.sections().size() + 1; // Includes null shdr.
+  return Obj.SHOffset + ShdrCount * sizeof(Elf_Shdr);
 }
 
 template <class ELFT> Error ELFWriter<ELFT>::write() {
index f85d4b7001855fb0f88c5839d269691e5bed5b98..4e0e23e5f49b8cd8e4ffa48509fa3f70ef9a26b4 100644 (file)
@@ -226,12 +226,11 @@ private:
 
 public:
   virtual ~ELFWriter() {}
-  bool WriteSectionHeaders = true;
+  bool WriteSectionHeaders;
 
   Error finalize() override;
   Error write() override;
-  ELFWriter(Object &Obj, Buffer &Buf, bool WSH)
-      : Writer(Obj, Buf), WriteSectionHeaders(WSH) {}
+  ELFWriter(Object &Obj, Buffer &Buf, bool WSH);
 };
 
 class BinaryWriter : public Writer {
@@ -810,6 +809,7 @@ public:
   uint32_t Version;
   uint32_t Flags;
 
+  bool HadShdrs = true;
   StringTableSection *SectionNames = nullptr;
   SymbolTableSection *SymbolTable = nullptr;
   SectionIndexSection *SectionIndexTable = nullptr;