]> granicus.if.org Git - llvm/commitdiff
[llvm-objcopy]Don't implicitly strip sections in segments
authorJames Henderson <jh7370@my.bristol.ac.uk>
Thu, 14 Mar 2019 10:20:27 +0000 (10:20 +0000)
committerJames Henderson <jh7370@my.bristol.ac.uk>
Thu, 14 Mar 2019 10:20:27 +0000 (10:20 +0000)
This patch changes llvm-objcopy's behaviour to not strip sections that
are in segments, if they otherwise would be due to a stripping operation
(--strip-all, --strip-sections, --strip-non-alloc). This preserves the
segment contents. It does not change the behaviour of --strip-all-gnu
(although we could choose to do so), because GNU objcopy's behaviour in
this case seems to be to strip the section, nor does it prevent removing
of sections in segments with --remove-section (if a user REALLY wants to
remove a section, we should probably let them, although I could be
persuaded that warning might be appropriate). Tests have been added to
show this latter behaviour.

This fixes https://bugs.llvm.org/show_bug.cgi?id=41006.

Reviewed by: grimar, rupprecht, jakehehrlich

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

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

test/tools/llvm-objcopy/ELF/remove-section-in-segment.test [new file with mode: 0644]
test/tools/llvm-objcopy/ELF/strip-all-gnu.test
test/tools/llvm-objcopy/ELF/strip-all.test
test/tools/llvm-objcopy/ELF/strip-non-alloc.test
test/tools/llvm-objcopy/ELF/strip-sections.test
tools/llvm-objcopy/ELF/ELFObjcopy.cpp
tools/llvm-objcopy/ObjcopyOpts.td
tools/llvm-objcopy/StripOpts.td

diff --git a/test/tools/llvm-objcopy/ELF/remove-section-in-segment.test b/test/tools/llvm-objcopy/ELF/remove-section-in-segment.test
new file mode 100644 (file)
index 0000000..d464e0d
--- /dev/null
@@ -0,0 +1,47 @@
+# Show that --remove-section removes sections in segments.
+
+# RUN: yaml2obj %s -o %t
+
+# Validate the offsets for the later parts of the test.
+# RUN: llvm-objcopy %t %t.copy
+# Skip to the start of the sections, which should be immediately after the
+# program header table (i.e. sizeof(Elf64_Ehdr) + sizeof(Elf64_Phdr) == 120).
+# RUN: od %t.copy -t x1 -N 16 -j 120 | FileCheck %s --check-prefix=COPY
+
+# COPY: 11 22 33 44 55 66 77 88
+
+# RUN: llvm-objcopy --remove-section non_alloc %t %t.nonalloc
+# RUN: llvm-readelf --sections %t.nonalloc | FileCheck %s --check-prefix=NONALLOC-SHDRS
+# RUN: od %t.nonalloc -t x1 -N 16 -j 120 | FileCheck %s --check-prefix=NONALLOC-BYTES
+
+# NONALLOC-SHDRS-NOT: non_alloc
+# NONALLOC-BYTES: 11 22 33 44 00 00 00 00
+
+# RUN: llvm-objcopy --remove-section shf_alloc %t %t.alloc
+# RUN: llvm-readelf --sections %t.alloc | FileCheck %s --check-prefix=ALLOC-SHDRS
+# RUN: od %t.alloc -t x1 -N 16 -j 120 | FileCheck %s --check-prefix=ALLOC-BYTES
+
+# ALLOC-SHDRS-NOT: shf_alloc
+# ALLOC-BYTES: 00 00 00 00 55 66 77 88
+
+--- !ELF
+FileHeader:
+  Class:   ELFCLASS64
+  Data:    ELFDATA2LSB
+  Type:    ET_EXEC
+  Machine: EM_X86_64
+Sections:
+  - Name:    shf_alloc
+    Type:    SHT_PROGBITS
+    Flags:   [SHF_ALLOC]
+    Content: '11223344'
+  - Name:    non_alloc
+    Type:    SHT_PROGBITS
+    Flags:   []
+    Content: '55667788'
+ProgramHeaders:
+  # Use an arbitrary segment type to show that the segment type is unimportant.
+  - Type: 0x61234567
+    Sections:
+      - Section: shf_alloc
+      - Section: non_alloc
index 8253526d23c0021b7e681e0e4660803d23120c62..95e7356d02466fc7c874a228405ad58eed1d67d8 100644 (file)
@@ -1,10 +1,15 @@
 # RUN: yaml2obj %s > %t
-# RUN: cp %t %t1
 # RUN: llvm-objcopy --strip-all-gnu %t %t2
 # RUN: llvm-strip --strip-all-gnu %t -o %t3
 # RUN: llvm-readobj --file-headers --sections %t2 | FileCheck %s
 # RUN: cmp %t2 %t3
 
+# Show that the debug section in a segment was removed, to match GNU.
+# First validate that the offset in use is correct.
+# RUN: llvm-objcopy %t %t4
+# RUN: od %t4 -t x1 -N 4 -j 120 | FileCheck %s --check-prefix=COPY-BYTES
+# RUN: od %t2 -t x1 -N 4 -j 120 | FileCheck %s --check-prefix=STRIP-BYTES
+
 !ELF
 FileHeader:
   Class:           ELFCLASS64
@@ -12,6 +17,10 @@ FileHeader:
   Type:            ET_REL
   Machine:         EM_X86_64
 Sections:
+  - Name:            .debug_in_segment
+    Type:            SHT_PROGBITS
+    Flags:           [ ]
+    Content:         "deadbeef"
   - Name:            .dynstr
     Type:            SHT_STRTAB
     Flags:           [ SHF_ALLOC ]
@@ -45,6 +54,11 @@ Sections:
   - Name:            .rela.text
     Type:            SHT_RELA
     Info:            .text
+ProgramHeaders:
+  # Use an arbitrary segment type to show that the segment type is unimportant.
+  - Type: 0x61234567
+    Sections:
+      - Section: .debug_in_segment
 
 # CHECK: SectionHeaderCount: 8
 
@@ -55,3 +69,6 @@ Sections:
 # CHECK:      Name: .comment
 # CHECK:      Name: .random_section_name
 # CHECK:      Name: .shstrtab
+
+# COPY-BYTES:  de ad be ef
+# STRIP-BYTES: 00 00 00 00
index 87388e0974769e2a7dfd5bb1d31aae2889d589a7..32a801d7a6cd236741e76762e52d4fd5ce20e530 100644 (file)
@@ -57,6 +57,10 @@ FileHeader:
   Type:            ET_REL
   Machine:         EM_X86_64
 Sections:
+  - Name:            non_alloc_in_segment
+    Type:            SHT_PROGBITS
+    Flags:           [ ]
+    Size:            4
   - Name:            .bss
     Type:            SHT_NOBITS
     Flags:           [ SHF_ALLOC ]
@@ -68,9 +72,15 @@ Sections:
     Flags:           [ ]
   - Name:            .gnu.warning.foo
     Type:            SHT_PROGBITS
+ProgramHeaders:
+  # Use an arbitrary segment type to show that the segment type is unimportant.
+  - Type: 0x61234567
+    Sections:
+      - Section: non_alloc_in_segment
 
-# CHECK: SectionHeaderCount: 5
+# CHECK: SectionHeaderCount: 6
 
+# CHECK: Name: non_alloc_in_segment
 # CHECK: Name: .bss
 # CHECK: Name: .text
 # CHECK: Name: .gnu.warning.foo
index 8db732147d3632e116644a6f3a760614ba4c6ddd..1f082bf47344df8307dcc413a321ff374a4a9ff3 100644 (file)
@@ -9,6 +9,10 @@ FileHeader:
   Type:            ET_REL
   Machine:         EM_X86_64
 Sections:
+  - Name:            non_alloc_in_segment
+    Type:            SHT_PROGBITS
+    Flags:           [ ]
+    Size:            4
   - Name:            .bss
     Type:            SHT_NOBITS
     Flags:           [ SHF_ALLOC ]
@@ -18,9 +22,15 @@ Sections:
   - Name:            .blarg
     Type:            SHT_PROGBITS
     Flags:           [ ]
+ProgramHeaders:
+  # Use an arbitrary segment type to show that the segment type is unimportant.
+  - Type: 0x61234567
+    Sections:
+      - Section: non_alloc_in_segment
 
-# CHECK: SectionHeaderCount: 4
+# CHECK: SectionHeaderCount: 5
 
+# CHECK: Name: non_alloc_in_segment
 # CHECK: Name: .bss
 # CHECK: Name: .text
 # CHECK: Name: .shstrtab
index 2dee6e2808d452aab8a045e365a9a5aa259b7f92..244cdb31ba9c5338d0b6978daa99ec497cdac7d9 100644 (file)
@@ -15,13 +15,18 @@ Sections:
     Flags:           [ SHF_ALLOC, SHF_EXECINSTR ]
     AddressAlign:    0x0000000000001000
     Content:         "DEADBEEF"
+  - Name:            .non_alloc_in_segment
+    Type:            SHT_PROGBITS
+    Flags:           [ ]
+    Content:         "CAFEBABE"
 ProgramHeaders:
 - Type: PT_LOAD
   Flags: [ PF_X, PF_R ]
   Sections:
     - Section: .text
+    - Section: .non_alloc_in_segment
 
-#DATA: 0010000 de ad be ef
+#DATA: 0010000 de ad be ef ca fe ba be
 
 #CHECK: ElfHeader {
 #CHECK-NEXT:  Ident {
@@ -55,8 +60,8 @@ ProgramHeaders:
 #CHECK-NEXT:    Offset: 0x1000
 #CHECK-NEXT:    VirtualAddress: 0x0
 #CHECK-NEXT:    PhysicalAddress: 0x0
-#CHECK-NEXT:    FileSize: 4
-#CHECK-NEXT:    MemSize: 4
+#CHECK-NEXT:    FileSize: 8
+#CHECK-NEXT:    MemSize: 8
 #CHECK-NEXT:    Flags [ (0x5)
 #CHECK-NEXT:      PF_R (0x4)
 #CHECK-NEXT:      PF_X (0x1)
index cbf6a3d2777f90385207e04133d2cf62a6a24086..250eeea1c81bb8df66d3f93dec15c04769d6fa35 100644 (file)
@@ -403,7 +403,7 @@ static Error handleArgs(const CopyConfig &Config, Object &Obj,
 
   if (Config.StripSections) {
     RemovePred = [RemovePred](const SectionBase &Sec) {
-      return RemovePred(Sec) || (Sec.Flags & SHF_ALLOC) == 0;
+      return RemovePred(Sec) || Sec.ParentSegment == nullptr;
     };
   }
 
@@ -419,7 +419,7 @@ static Error handleArgs(const CopyConfig &Config, Object &Obj,
         return true;
       if (&Sec == Obj.SectionNames)
         return false;
-      return (Sec.Flags & SHF_ALLOC) == 0;
+      return (Sec.Flags & SHF_ALLOC) == 0 && Sec.ParentSegment == nullptr;
     };
 
   if (Config.StripAll)
@@ -430,6 +430,8 @@ static Error handleArgs(const CopyConfig &Config, Object &Obj,
         return false;
       if (StringRef(Sec.Name).startswith(".gnu.warning"))
         return false;
+      if (Sec.ParentSegment != nullptr)
+        return false;
       return (Sec.Flags & SHF_ALLOC) == 0;
     };
 
index 44fd01cf4ab5086bec3fbc39821208e39e0a1434..a5f7119e3284e5a7d18e4daa463659c710831682 100644 (file)
@@ -103,10 +103,9 @@ defm set_section_flags
          "rom, share, contents, merge, strings.">,
       MetaVarName<"section=flag1[,flag2,...]">;
 
-def strip_all
-    : Flag<["-", "--"], "strip-all">,
-      HelpText<
-          "Remove non-allocated sections other than .gnu.warning* sections">;
+def strip_all : Flag<["-", "--"], "strip-all">,
+                HelpText<"Remove non-allocated sections outside segments. "
+                         ".gnu.warning* sections are not removed">;
 def S : Flag<["-"], "S">, Alias<strip_all>;
 def strip_all_gnu : Flag<["-", "--"], "strip-all-gnu">,
                     HelpText<"Compatible with GNU objcopy's --strip-all">;
@@ -116,13 +115,15 @@ def g : Flag<["-"], "g">, Alias<strip_debug>,
         HelpText<"Alias for --strip-debug">;
 def strip_dwo : Flag<["-", "--"], "strip-dwo">,
                 HelpText<"Remove all DWARF .dwo sections from file">;
-def strip_sections : Flag<["-", "--"], "strip-sections">,
-                     HelpText<"Remove all section headers">;
-def strip_non_alloc : Flag<["-", "--"], "strip-non-alloc">,
-                      HelpText<"Remove all non-allocated sections">;
+def strip_sections
+    : Flag<["-", "--"], "strip-sections">,
+      HelpText<"Remove all section headers and all sections not in segments">;
+def strip_non_alloc
+    : Flag<["-", "--"], "strip-non-alloc">,
+      HelpText<"Remove all non-allocated sections outside segments">;
 def strip_unneeded : Flag<["-", "--"], "strip-unneeded">,
                      HelpText<"Remove all symbols not needed by relocations">;
-defm strip_unneeded_symbol 
+defm strip_unneeded_symbol
     : Eq<"strip-unneeded-symbol",
          "Remove symbol <symbol> if it is not needed by relocations">,
       MetaVarName<"symbol">;
index c3f351992a064ce8d15598b65559de93bf6aed42..40b043a7630e840fdb508786c811e7294ce31f42 100644 (file)
@@ -31,10 +31,9 @@ def preserve_dates : Flag<["-", "--"], "preserve-dates">,
                      HelpText<"Preserve access and modification timestamps">;
 def p : Flag<["-"], "p">, Alias<preserve_dates>;
 
-def strip_all
-    : Flag<["-", "--"], "strip-all">,
-      HelpText<
-          "Remove non-allocated sections other than .gnu.warning* sections">;
+def strip_all : Flag<["-", "--"], "strip-all">,
+                HelpText<"Remove non-allocated sections outside segments. "
+                         ".gnu.warning* sections are not removed">;
 def s : Flag<["-"], "s">, Alias<strip_all>;
 
 def strip_all_gnu : Flag<["-", "--"], "strip-all-gnu">,