[objcopy] make objcopy follow program header standards
authorJulie Hockett <juliehockett@google.com>
Wed, 12 Sep 2018 17:56:31 +0000 (17:56 +0000)
committerJulie Hockett <juliehockett@google.com>
Wed, 12 Sep 2018 17:56:31 +0000 (17:56 +0000)
Submitted on behalf of Armando Montanez (amontanez@google.com).

Objects with unused program headers copied by objcopy would always have
nonzero values for program header offset and program header entry size.
While technically valid, this atypical behavior triggers warnings in some
tools. This change sets the two fields to zero when the program header is
unused, better fitting the general expectations for unused program header
data.

Section headers behaved somewhat similarly (though only with the entry size),
and are fixed in this revision as well.

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

llvm-svn: 342065

llvm/test/tools/llvm-objcopy/binary-input-arch.test
llvm/test/tools/llvm-objcopy/many-sections.test
llvm/test/tools/llvm-objcopy/relocatable-phdr.test [new file with mode: 0644]
llvm/test/tools/llvm-objcopy/strip-sections.test
llvm/tools/llvm-objcopy/Object.cpp

index 3cca192..08f02da 100644 (file)
@@ -65,8 +65,8 @@
 # CHECK-NEXT:     ]
 # 32-NEXT:        HeaderSize: 52
 # 64-NEXT:        HeaderSize: 64
-# 32-NEXT:        ProgramHeaderEntrySize: 32
-# 64-NEXT:        ProgramHeaderEntrySize: 56
+# 32-NEXT:        ProgramHeaderEntrySize: 0
+# 64-NEXT:        ProgramHeaderEntrySize: 0
 # CHECK-NEXT:     ProgramHeaderCount: 0
 # 32-NEXT:        SectionHeaderEntrySize: 40
 # 64-NEXT:        SectionHeaderEntrySize: 64
index 7aaa3a7..e9e12cf 100644 (file)
@@ -22,12 +22,12 @@ EHDR-NEXT:   Type: Relocatable (0x1)
 EHDR-NEXT:   Machine: EM_X86_64 (0x3E)
 EHDR-NEXT:   Version: 1
 EHDR-NEXT:   Entry: 0x0
-EHDR-NEXT:   ProgramHeaderOffset: 0x40
+EHDR-NEXT:   ProgramHeaderOffset: 0x0
 EHDR-NEXT:   SectionHeaderOffset:
 EHDR-NEXT:   Flags [ (0x0)
 EHDR-NEXT:   ]
 EHDR-NEXT:   HeaderSize: 64
-EHDR-NEXT:   ProgramHeaderEntrySize: 56
+EHDR-NEXT:   ProgramHeaderEntrySize: 0
 EHDR-NEXT:   ProgramHeaderCount: 0
 EHDR-NEXT:   SectionHeaderEntrySize: 64
 EHDR-NEXT:   SectionHeaderCount: 0
diff --git a/llvm/test/tools/llvm-objcopy/relocatable-phdr.test b/llvm/test/tools/llvm-objcopy/relocatable-phdr.test
new file mode 100644 (file)
index 0000000..b621895
--- /dev/null
@@ -0,0 +1,16 @@
+# This test ensures an object without a program header will retain zero values
+# for offset and header size when copied with llvm-objcopy.
+# RUN: yaml2obj %s > %t
+# RUN: llvm-objcopy %t %t2
+# RUN: llvm-readobj -file-headers %t2 | FileCheck %s
+
+!ELF
+FileHeader:
+  Class:           ELFCLASS64
+  Data:            ELFDATA2LSB
+  Type:            ET_EXEC
+  Machine:         EM_X86_64
+
+# CHECK:      ProgramHeaderOffset: 0x0
+# CHECK:      ProgramHeaderEntrySize: 0
+# CHECK-NEXT: ProgramHeaderCount: 0
index 66cb34e..fd8e224 100644 (file)
@@ -44,7 +44,7 @@ ProgramHeaders:
 #CHECK-NEXT:   HeaderSize: 64
 #CHECK-NEXT:   ProgramHeaderEntrySize: 56
 #CHECK-NEXT:   ProgramHeaderCount: 1
-#CHECK-NEXT:   SectionHeaderEntrySize: 64
+#CHECK-NEXT:   SectionHeaderEntrySize: 0
 #CHECK-NEXT:   SectionHeaderCount: 0
 #CHECK-NEXT:   StringTableSectionIndex: 0
 #CHECK-NEXT: }
index aaefcf9..e57a626 100644 (file)
@@ -1121,15 +1121,13 @@ template <class ELFT> void ELFWriter<ELFT>::writeEhdr() {
   Ehdr.e_machine = Obj.Machine;
   Ehdr.e_version = Obj.Version;
   Ehdr.e_entry = Obj.Entry;
-  // TODO: Only set phoff when a program header exists, to avoid tools
-  // thinking this is corrupt data.
-  Ehdr.e_phoff = Obj.ProgramHdrSegment.Offset;
+  Ehdr.e_phnum = size(Obj.segments());
+  Ehdr.e_phoff = (Ehdr.e_phnum != 0) ? Obj.ProgramHdrSegment.Offset : 0;
+  Ehdr.e_phentsize = (Ehdr.e_phnum != 0) ? sizeof(Elf_Phdr) : 0;
   Ehdr.e_flags = Obj.Flags;
   Ehdr.e_ehsize = sizeof(Elf_Ehdr);
-  Ehdr.e_phentsize = sizeof(Elf_Phdr);
-  Ehdr.e_phnum = size(Obj.segments());
-  Ehdr.e_shentsize = sizeof(Elf_Shdr);
-  if (WriteSectionHeaders) {
+  if (WriteSectionHeaders && size(Obj.sections()) != 0) {
+    Ehdr.e_shentsize = sizeof(Elf_Shdr);
     Ehdr.e_shoff = Obj.SHOffset;
     // """
     // If the number of sections is greater than or equal to
@@ -1153,6 +1151,7 @@ template <class ELFT> void ELFWriter<ELFT>::writeEhdr() {
     else
       Ehdr.e_shstrndx = Obj.SectionNames->Index;
   } else {
+    Ehdr.e_shentsize = 0;
     Ehdr.e_shoff = 0;
     Ehdr.e_shnum = 0;
     Ehdr.e_shstrndx = 0;