[llvm-objcopy] Add support for removing sections

This change adds support for removing sections using the -R field (as
GNU objcopy does as well). This change should let us add many helpful
tests and is a proper stepping stone for adding more general kinds of
stripping.

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

llvm-svn: 315346
diff --git a/llvm/test/tools/llvm-objcopy/dynsym-error-remove-strtab.test b/llvm/test/tools/llvm-objcopy/dynsym-error-remove-strtab.test
new file mode 100644
index 0000000..ef6ef24
--- /dev/null
+++ b/llvm/test/tools/llvm-objcopy/dynsym-error-remove-strtab.test
@@ -0,0 +1,3 @@
+# RUN: not llvm-objcopy -R .dynstr %p/Inputs/dynsym.so %t 2>&1 >/dev/null | FileCheck %s
+
+# CHECK: String table .dynstr cannot be removed because it is referenced by the section .dynsym
diff --git a/llvm/test/tools/llvm-objcopy/reloc-error-remove-symtab.test b/llvm/test/tools/llvm-objcopy/reloc-error-remove-symtab.test
new file mode 100644
index 0000000..539e6ea
--- /dev/null
+++ b/llvm/test/tools/llvm-objcopy/reloc-error-remove-symtab.test
@@ -0,0 +1,32 @@
+# RUN: yaml2obj %s > %t
+# RUN: not llvm-objcopy -R .symtab %t %t2 2>&1 >/dev/null | FileCheck %s
+
+!ELF
+FileHeader:
+  Class:           ELFCLASS64
+  Data:            ELFDATA2LSB
+  Type:            ET_REL
+  Machine:         EM_X86_64
+Sections:
+  - Name:            .text
+    Type:            SHT_PROGBITS
+    Flags:           [ SHF_ALLOC, SHF_EXECINSTR ]
+    Address:         0x1000
+    AddressAlign:    0x0000000000000010
+    Content:         "0000000000000000"
+  - Name:            .rel.text
+    Type:            SHT_REL
+    Link:            .symtab
+    Info:            .text
+    Relocations:
+      - Offset: 0x1000
+        Symbol: foo
+        Type:   R_X86_64_PC32
+
+Symbols:
+  Global:
+    - Name:     foo
+      Type:     STT_FUNC
+      Size:     4
+
+# CHECK: Symbol table .symtab cannot be removed because it is referenced by the relocation section .rel.text.
diff --git a/llvm/test/tools/llvm-objcopy/remove-section-with-symbol.test b/llvm/test/tools/llvm-objcopy/remove-section-with-symbol.test
new file mode 100644
index 0000000..067c0b2
--- /dev/null
+++ b/llvm/test/tools/llvm-objcopy/remove-section-with-symbol.test
@@ -0,0 +1,54 @@
+# RUN: yaml2obj %s > %t
+# RUN: llvm-objcopy -R .test %t %t2
+# RUN: llvm-readobj -file-headers -symbols %t2 | FileCheck %s
+
+!ELF
+FileHeader:
+  Class:           ELFCLASS64
+  Data:            ELFDATA2LSB
+  Type:            ET_REL
+  Machine:         EM_X86_64
+Sections:
+  - Name:            .test
+    Type:            SHT_PROGBITS
+    Flags:           [ SHF_ALLOC ]
+  - Name:            .test2
+    Type:            SHT_PROGBITS
+    Flags:           [ SHF_ALLOC ]
+Symbols:
+  Global:
+    - Name:     test
+      Type:     STT_FUNC
+      Section:  .test
+      Value:    0x1000
+      Size:     4
+    - Name:     test2
+      Type:     STT_FUNC
+      Section:  .test2
+      Value:    0x1000
+      Size:     4
+
+# The sections counted here should be .test, .symtab, .strtab, and .shstrtab.
+# The 5th section is the null section.
+#CHECK: SectionHeaderCount: 5
+
+#CHECK: Symbols [
+#CHECK-NEXT:  Symbol {
+#CHECK-NEXT:    Name:
+#CHECK-NEXT:    Value: 0x0
+#CHECK-NEXT:    Size: 0
+#CHECK-NEXT:    Binding: Local
+#CHECK-NEXT:    Type: None
+#CHECK-NEXT:    Other: 0
+#CHECK-NEXT:    Section: Undefined
+#CHECK-NEXT:  }
+#CHECK-NEXT:  Symbol {
+#CHECK-NEXT:    Name: test2
+#CHECK-NEXT:    Value: 0x1000
+#CHECK-NEXT:    Size: 4
+#CHECK-NEXT:    Binding: Global
+#CHECK-NEXT:    Type: Function
+#CHECK-NEXT:    Other: 0
+#CHECK-NEXT:    Section: .test2
+#CHECK-NEXT:  }
+#CHECK-NEXT:]
diff --git a/llvm/test/tools/llvm-objcopy/remove-section.test b/llvm/test/tools/llvm-objcopy/remove-section.test
new file mode 100644
index 0000000..0fa26bc
--- /dev/null
+++ b/llvm/test/tools/llvm-objcopy/remove-section.test
@@ -0,0 +1,109 @@
+# RUN: yaml2obj %s > %t
+# RUN: llvm-objcopy -R=.test2 %t %t2
+# RUN: llvm-readobj -file-headers -sections %t2 | FileCheck %s
+
+!ELF
+FileHeader:
+  Class:           ELFCLASS64
+  Data:            ELFDATA2LSB
+  Type:            ET_REL
+  Machine:         EM_X86_64
+Sections:
+  - Name:            .test1
+    Type:            SHT_PROGBITS
+    Flags:           [ ]
+  - Name:            .test2
+    Type:            SHT_PROGBITS
+    Flags:           [ ]
+  - Name:            .test3
+    Type:            SHT_PROGBITS
+    Flags:           [ ]
+
+# CHECK: SectionHeaderCount: 6
+
+# CHECK: Sections [
+# CHECK:   Section {
+# CHECK:     Index: 0
+# CHECK:     Name:  (0)
+# CHECK:     Type: SHT_NULL (0x0)
+# CHECK:     Flags [ (0x0)
+# CHECK:     ]
+# CHECK:     Address: 0x0
+# CHECK:     Offset:
+# CHECK:     Size:
+# CHECK:     Link: 0
+# CHECK:     Info: 0
+# CHECK:     AddressAlignment: 0
+# CHECK:     EntrySize: 0
+# CHECK:   }
+# CHECK:   Section {
+# CHECK:     Index: 1
+# CHECK:     Name: .test1
+# CHECK:     Type: SHT_PROGBITS (0x1)
+# CHECK:     Flags [ (0x0)
+# CHECK:     ]
+# CHECK:     Address: 0x0
+# CHECK:     Offset:
+# CHECK:     Size:
+# CHECK:     Link: 0
+# CHECK:     Info: 0
+# CHECK:     AddressAlignment: 0
+# CHECK:     EntrySize: 0
+# CHECK:   }
+# CHECK:   Section {
+# CHECK:     Index: 2
+# CHECK:     Name: .test3
+# CHECK:     Type: SHT_PROGBITS (0x1)
+# CHECK:     Flags [ (0x0)
+# CHECK:     ]
+# CHECK:     Address: 0x0
+# CHECK:     Offset:
+# CHECK:     Size:
+# CHECK:     Link: 0
+# CHECK:     Info: 0
+# CHECK:     AddressAlignment: 0
+# CHECK:     EntrySize: 0
+# CHECK:   }
+# CHECK:   Section {
+# CHECK:     Index: 3
+# CHECK:     Name: .symtab
+# CHECK:     Type: SHT_SYMTAB (0x2)
+# CHECK:     Flags [ (0x0)
+# CHECK:     ]
+# CHECK:     Address: 0x0
+# CHECK:     Offset:
+# CHECK:     Size:
+# CHECK:     Link: 4
+# CHECK:     Info: 1
+# CHECK:     AddressAlignment: 8
+# CHECK:     EntrySize: 24
+# CHECK:   }
+# CHECK:   Section {
+# CHECK:     Index: 4
+# CHECK:     Name: .strtab
+# CHECK:     Type: SHT_STRTAB (0x3)
+# CHECK:     Flags [ (0x0)
+# CHECK:     ]
+# CHECK:     Address: 0x0
+# CHECK:     Offset:
+# CHECK:     Size:
+# CHECK:     Link: 0
+# CHECK:     Info: 0
+# CHECK:     AddressAlignment: 1
+# CHECK:     EntrySize: 0
+# CHECK:   }
+# CHECK:   Section {
+# CHECK:     Index: 5
+# CHECK:     Name: .shstrtab
+# CHECK:     Type: SHT_STRTAB (0x3)
+# CHECK:     Flags [ (0x0)
+# CHECK:     ]
+# CHECK:     Address: 0x0
+# CHECK:     Offset:
+# CHECK:     Size:
+# CHECK:     Link: 0
+# CHECK:     Info: 0
+# CHECK:     AddressAlignment: 1
+# CHECK:     EntrySize: 0
+# CHECK:   }
+# CHECK: ]
diff --git a/llvm/test/tools/llvm-objcopy/remove-shstrtab-error.test b/llvm/test/tools/llvm-objcopy/remove-shstrtab-error.test
new file mode 100644
index 0000000..7d297ef
--- /dev/null
+++ b/llvm/test/tools/llvm-objcopy/remove-shstrtab-error.test
@@ -0,0 +1,11 @@
+# RUN: yaml2obj %s > %t
+# RUN: not llvm-objcopy -R .shstrtab %t %t2 2>&1 >/dev/null | FileCheck %s
+
+!ELF
+FileHeader:
+  Class:           ELFCLASS64
+  Data:            ELFDATA2LSB
+  Type:            ET_REL
+  Machine:         EM_X86_64
+
+# CHECK: Cannot remove .shstrtab because it is the section header string table.
diff --git a/llvm/test/tools/llvm-objcopy/remove-symtab.test b/llvm/test/tools/llvm-objcopy/remove-symtab.test
new file mode 100644
index 0000000..0e3f82b
--- /dev/null
+++ b/llvm/test/tools/llvm-objcopy/remove-symtab.test
@@ -0,0 +1,57 @@
+# RUN: yaml2obj %s > %t
+# RUN: llvm-objcopy -R .symtab %t %t2
+# RUN: llvm-readobj -file-headers -sections %t2 | FileCheck %s
+
+!ELF
+FileHeader:
+  Class:           ELFCLASS64
+  Data:            ELFDATA2LSB
+  Type:            ET_REL
+  Machine:         EM_X86_64
+
+#CHECK: SectionHeaderCount: 3
+
+#CHECK:        Sections [
+#CHECK-NEXT:     Section {
+#CHECK-NEXT:       Index: 0
+#CHECK-NEXT:       Name:  (0)
+#CHECK-NEXT:       Type: SHT_NULL (0x0)
+#CHECK-NEXT:       Flags [ (0x0)
+#CHECK-NEXT:       ]
+#CHECK-NEXT:       Address: 0x0
+#CHECK-NEXT:       Offset: 0x0
+#CHECK-NEXT:       Size: 0
+#CHECK-NEXT:       Link: 0
+#CHECK-NEXT:       Info: 0
+#CHECK-NEXT:       AddressAlignment: 0
+#CHECK-NEXT:       EntrySize: 0
+#CHECK-NEXT:     }
+#CHECK-NEXT:     Section {
+#CHECK-NEXT:       Index: 1
+#CHECK-NEXT:       Name: .strtab
+#CHECK-NEXT:       Type: SHT_STRTAB (0x3)
+#CHECK-NEXT:       Flags [ (0x0)
+#CHECK-NEXT:       ]
+#CHECK-NEXT:       Address: 0x0
+#CHECK-NEXT:       Offset:
+#CHECK-NEXT:       Size: 1
+#CHECK-NEXT:       Link: 0
+#CHECK-NEXT:       Info: 0
+#CHECK-NEXT:       AddressAlignment: 1
+#CHECK-NEXT:       EntrySize: 0
+#CHECK-NEXT:     }
+#CHECK-NEXT:     Section {
+#CHECK-NEXT:       Index: 2
+#CHECK-NEXT:       Name: .shstrtab (1)
+#CHECK-NEXT:       Type: SHT_STRTAB (0x3)
+#CHECK-NEXT:       Flags [ (0x0)
+#CHECK-NEXT:       ]
+#CHECK-NEXT:       Address: 0x0
+#CHECK-NEXT:       Offset:
+#CHECK-NEXT:       Size:
+#CHECK-NEXT:       Link: 0
+#CHECK-NEXT:       Info: 0
+#CHECK-NEXT:       AddressAlignment: 1
+#CHECK-NEXT:       EntrySize: 0
+#CHECK-NEXT:     }
+#CHECK-NEXT:   ]
diff --git a/llvm/test/tools/llvm-objcopy/segment-shift-section-remove.test b/llvm/test/tools/llvm-objcopy/segment-shift-section-remove.test
new file mode 100644
index 0000000..caeb559
--- /dev/null
+++ b/llvm/test/tools/llvm-objcopy/segment-shift-section-remove.test
@@ -0,0 +1,164 @@
+# RUN: yaml2obj %s -o %t
+# RUN: llvm-objcopy -R .text2 %t %t2
+# RUN: llvm-readobj -file-headers -sections -program-headers %t2 | 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 ]
+    Address:         0x1000
+    AddressAlign:    0x1000
+    Size:            0x1000
+  - Name:            .text2
+    Type:            SHT_PROGBITS
+    Flags:           [ SHF_ALLOC, SHF_EXECINSTR ]
+    Address:         0x2000
+    AddressAlign:    0x1000
+    Size:            0x1000
+  - Name:            .text3
+    Type:            SHT_PROGBITS
+    Flags:           [ SHF_ALLOC, SHF_EXECINSTR ]
+    Address:         0x3000
+    AddressAlign:    0x1000
+    Size:            0x1000
+ProgramHeaders:
+  - Type: PT_LOAD
+    Flags: [ PF_R ]
+    VAddr: 0x1000
+    PAddr: 0x1000
+    Sections:
+      - Section: .text
+  - Type: PT_LOAD
+    Flags: [ PF_X, PF_R ]
+    VAddr: 0x3000
+    PAddr: 0x3000
+    Sections:
+      - Section: .text3
+
+#CHECK: SectionHeaderCount: 6
+
+# CHECK:           Sections [
+# CHECK-NEXT:        Section {
+# CHECK-NEXT:          Index: 0
+# CHECK-NEXT:          Name:  (0)
+# CHECK-NEXT:          Type: SHT_NULL (0x0)
+# CHECK-NEXT:          Flags [ (0x0)
+# CHECK-NEXT:          ]
+# CHECK-NEXT:          Address: 0x0
+# CHECK-NEXT:          Offset: 0x0
+# CHECK-NEXT:          Size: 0
+# CHECK-NEXT:          Link: 0
+# CHECK-NEXT:          Info: 0
+# CHECK-NEXT:          AddressAlignment: 0
+# CHECK-NEXT:          EntrySize: 0
+# CHECK-NEXT:        }
+# CHECK-NEXT:        Section {
+# CHECK-NEXT:          Index: 1
+# CHECK-NEXT:          Name: .text
+# CHECK-NEXT:          Type: SHT_PROGBITS (0x1)
+# CHECK-NEXT:          Flags [ (0x6)
+# CHECK-NEXT:            SHF_ALLOC (0x2)
+# CHECK-NEXT:            SHF_EXECINSTR (0x4)
+# CHECK-NEXT:          ]
+# CHECK-NEXT:          Address: 0x1000
+# CHECK-NEXT:          Offset: 0x1000
+# CHECK-NEXT:          Size: 4096
+# CHECK-NEXT:          Link: 0
+# CHECK-NEXT:          Info: 0
+# CHECK-NEXT:          AddressAlignment: 4096
+# CHECK-NEXT:          EntrySize: 0
+# CHECK-NEXT:        }
+# CHECK-NEXT:        Section {
+# CHECK-NEXT:          Index: 2
+# CHECK-NEXT:          Name: .text3
+# CHECK-NEXT:          Type: SHT_PROGBITS (0x1)
+# CHECK-NEXT:          Flags [ (0x6)
+# CHECK-NEXT:            SHF_ALLOC (0x2)
+# CHECK-NEXT:            SHF_EXECINSTR (0x4)
+# CHECK-NEXT:          ]
+# CHECK-NEXT:          Address: 0x3000
+# CHECK-NEXT:          Offset: 0x2000
+# CHECK-NEXT:          Size: 4096
+# CHECK-NEXT:          Link: 0
+# CHECK-NEXT:          Info: 0
+# CHECK-NEXT:          AddressAlignment: 4096
+# CHECK-NEXT:          EntrySize: 0
+# CHECK-NEXT:        }
+# CHECK-NEXT:        Section {
+# CHECK-NEXT:          Index: 3
+# CHECK-NEXT:          Name: .symtab
+# CHECK-NEXT:          Type: SHT_SYMTAB (0x2)
+# CHECK-NEXT:          Flags [ (0x0)
+# CHECK-NEXT:          ]
+# CHECK-NEXT:          Address: 0x0
+# CHECK-NEXT:          Offset: 0x3000
+# CHECK-NEXT:          Size: 24
+# CHECK-NEXT:          Link: 4
+# CHECK-NEXT:          Info: 1
+# CHECK-NEXT:          AddressAlignment: 8
+# CHECK-NEXT:          EntrySize: 24
+# CHECK-NEXT:        }
+# CHECK-NEXT:        Section {
+# CHECK-NEXT:          Index: 4
+# CHECK-NEXT:          Name: .strtab
+# CHECK-NEXT:          Type: SHT_STRTAB (0x3)
+# CHECK-NEXT:          Flags [ (0x0)
+# CHECK-NEXT:          ]
+# CHECK-NEXT:          Address: 0x0
+# CHECK-NEXT:          Offset: 0x3018
+# CHECK-NEXT:          Size:
+# CHECK-NEXT:          Link: 0
+# CHECK-NEXT:          Info: 0
+# CHECK-NEXT:          AddressAlignment: 1
+# CHECK-NEXT:          EntrySize: 0
+# CHECK-NEXT:        }
+# CHECK-NEXT:        Section {
+# CHECK-NEXT:          Index: 5
+# CHECK-NEXT:          Name: .shstrtab
+# CHECK-NEXT:          Type: SHT_STRTAB (0x3)
+# CHECK-NEXT:          Flags [ (0x0)
+# CHECK-NEXT:          ]
+# CHECK-NEXT:          Address: 0x0
+# CHECK-NEXT:          Offset:
+# CHECK-NEXT:          Size:
+# CHECK-NEXT:          Link: 0
+# CHECK-NEXT:          Info: 0
+# CHECK-NEXT:          AddressAlignment: 1
+# CHECK-NEXT:          EntrySize: 0
+# CHECK-NEXT:        }
+# CHECK-NEXT:      ]
+
+
+# CHECK:     ProgramHeaders [
+# CHECK-NEXT:  ProgramHeader {
+# CHECK-NEXT:    Type: PT_LOAD (0x1)
+# CHECK-NEXT:    Offset: 0x1000
+# CHECK-NEXT:    VirtualAddress: 0x1000
+# CHECK-NEXT:    PhysicalAddress: 0x1000
+# CHECK-NEXT:    FileSize: 4096
+# CHECK-NEXT:    MemSize: 4096
+# CHECK-NEXT:    Flags [ (0x4)
+# CHECK-NEXT:      PF_R (0x4)
+# CHECK-NEXT:    ]
+# CHECK-NEXT:    Alignment: 4096
+# CHECK-NEXT:  }
+# CHECK-NEXT:  ProgramHeader {
+# CHECK-NEXT:    Type: PT_LOAD (0x1)
+# CHECK-NEXT:    Offset: 0x2000
+# CHECK-NEXT:    VirtualAddress: 0x3000
+# CHECK-NEXT:    PhysicalAddress: 0x3000
+# CHECK-NEXT:    FileSize: 4096
+# CHECK-NEXT:    MemSize: 4096
+# CHECK-NEXT:    Flags [ (0x5)
+# CHECK-NEXT:      PF_R (0x4)
+# CHECK-NEXT:      PF_X (0x1)
+# CHECK-NEXT:    ]
+# CHECK-NEXT:    Alignment: 4096
+# CHECK-NEXT:  }
+# CHECK-NEXT:]
diff --git a/llvm/test/tools/llvm-objcopy/segment-test-remove-section.test b/llvm/test/tools/llvm-objcopy/segment-test-remove-section.test
new file mode 100644
index 0000000..9b98dc8
--- /dev/null
+++ b/llvm/test/tools/llvm-objcopy/segment-test-remove-section.test
@@ -0,0 +1,156 @@
+# This test is checking to ensure that if a section is removed in the presence
+# of a segment that the segment maintains its shape and properties and that any
+# section inside that segment maintains the relative positioning it had in the
+# segment. Note worthy is that .text3 keeps its offset despite it being
+# possible to place it after .text when .text2 is removed.
+
+# RUN: yaml2obj %s -o %t
+# RUN: llvm-objcopy -R .text2 %t %t2
+# RUN: llvm-readobj -file-headers -program-headers -sections %t2 | FileCheck %s
+# RUN: od -t x1 -j 8192 %t2 | FileCheck %s --check-prefix=DATA
+
+!ELF
+FileHeader:
+  Class:           ELFCLASS64
+  Data:            ELFDATA2LSB
+  Type:            ET_EXEC
+  Machine:         EM_X86_64
+Sections:
+  - Name:            .text
+    Type:            SHT_PROGBITS
+    Flags:           [ SHF_ALLOC, SHF_EXECINSTR ]
+    Address:         0x1000
+    AddressAlign:    0x1000
+    Size:            4096
+  - Name:            .text2
+    Type:            SHT_PROGBITS
+    Flags:           [ SHF_ALLOC, SHF_EXECINSTR ]
+    Address:         0x2000
+    AddressAlign:    0x1000
+    Size:            4096
+    Content:         "DEADBEEF"
+  - Name:            .text3
+    Type:            SHT_PROGBITS
+    Flags:           [ SHF_ALLOC, SHF_EXECINSTR ]
+    Address:         0x3000
+    AddressAlign:    0x1000
+    Size:            4096
+ProgramHeaders:
+  - Type: PT_LOAD
+    Flags: [ PF_X, PF_R ]
+    Sections:
+      - Section: .text
+      - Section: .text2
+      - Section: .text3
+
+# Make sure that when we remove a section we overwrite it with zeros
+# DATA: 0020000 00 00 00 00
+
+#CHECK: SectionHeaderCount: 6
+
+# CHECK: Sections [
+# CHECK:   Section {
+# CHECK-NEXT:     Index: 0
+# CHECK-NEXT:     Name:  (0)
+# CHECK-NEXT:     Type: SHT_NULL (0x0)
+# CHECK-NEXT:     Flags [ (0x0)
+# CHECK-NEXT:     ]
+# CHECK-NEXT:     Address: 0x0
+# CHECK-NEXT:     Offset:
+# CHECK-NEXT:     Size:
+# CHECK-NEXT:     Link: 0
+# CHECK-NEXT:     Info: 0
+# CHECK-NEXT:     AddressAlignment: 0
+# CHECK-NEXT:     EntrySize: 0
+# CHECK-NEXT:   }
+# CHECK-NEXT:   Section {
+# CHECK-NEXT:     Index: 1
+# CHECK-NEXT:     Name: .text
+# CHECK-NEXT:     Type: SHT_PROGBITS
+# CHECK-NEXT:     Flags [
+# CHECK-NEXT:       SHF_ALLOC
+# CHECK-NEXT:       SHF_EXECINSTR
+# CHECK-NEXT:     ]
+# CHECK-NEXT:     Address: 0x1000
+# CHECK-NEXT:     Offset: 0x1000
+# CHECK-NEXT:     Size:
+# CHECK-NEXT:     Link: 0
+# CHECK-NEXT:     Info: 0
+# CHECK-NEXT:     AddressAlignment: 4096
+# CHECK-NEXT:     EntrySize: 0
+# CHECK-NEXT:   }
+# CHECK-NEXT:   Section {
+# CHECK-NEXT:     Index: 2
+# CHECK-NEXT:     Name: .text3
+# CHECK-NEXT:     Type: SHT_PROGBITS (0x1)
+# CHECK-NEXT:     Flags [
+# CHECK-NEXT:       SHF_ALLOC
+# CHECK-NEXT:       SHF_EXECINSTR
+# CHECK-NEXT:     ]
+# CHECK-NEXT:     Address: 0x3000
+# CHECK-NEXT:     Offset: 0x3000
+# CHECK-NEXT:     Size:
+# CHECK-NEXT:     Link: 0
+# CHECK-NEXT:     Info: 0
+# CHECK-NEXT:     AddressAlignment: 4096
+# CHECK-NEXT:     EntrySize: 0
+# CHECK-NEXT:   }
+# CHECK-NEXT:   Section {
+# CHECK-NEXT:     Index: 3
+# CHECK-NEXT:     Name: .symtab
+# CHECK-NEXT:     Type: SHT_SYMTAB (0x2)
+# CHECK-NEXT:     Flags [ (0x0)
+# CHECK-NEXT:     ]
+# CHECK-NEXT:     Address: 0x0
+# CHECK-NEXT:     Offset:
+# CHECK-NEXT:     Size:
+# CHECK-NEXT:     Link: 4
+# CHECK-NEXT:     Info: 1
+# CHECK-NEXT:     AddressAlignment: 8
+# CHECK-NEXT:     EntrySize: 24
+# CHECK-NEXT:   }
+# CHECK-NEXT:   Section {
+# CHECK-NEXT:     Index: 4
+# CHECK-NEXT:     Name: .strtab
+# CHECK-NEXT:     Type: SHT_STRTAB (0x3)
+# CHECK-NEXT:     Flags [ (0x0)
+# CHECK-NEXT:     ]
+# CHECK-NEXT:     Address: 0x0
+# CHECK-NEXT:     Offset:
+# CHECK-NEXT:     Size:
+# CHECK-NEXT:     Link: 0
+# CHECK-NEXT:     Info: 0
+# CHECK-NEXT:     AddressAlignment: 1
+# CHECK-NEXT:     EntrySize: 0
+# CHECK-NEXT:   }
+# CHECK-NEXT:   Section {
+# CHECK-NEXT:     Index: 5
+# CHECK-NEXT:     Name: .shstrtab
+# CHECK-NEXT:     Type: SHT_STRTAB (0x3)
+# CHECK-NEXT:     Flags [ (0x0)
+# CHECK-NEXT:     ]
+# CHECK-NEXT:     Address: 0x0
+# CHECK-NEXT:     Offset:
+# CHECK-NEXT:     Size:
+# CHECK-NEXT:     Link: 0
+# CHECK-NEXT:     Info: 0
+# CHECK-NEXT:     AddressAlignment: 1
+# CHECK-NEXT:     EntrySize: 0
+# CHECK-NEXT:   }
+# CHECK-NEXT: ]
+
+#CHECK:     ProgramHeaders [
+#CHECK-NEXT:  ProgramHeader {
+#CHECK-NEXT:    Type: PT_LOAD (0x1)
+#CHECK-NEXT:    Offset: 0x1000
+#CHECK-NEXT:    VirtualAddress: 0x0
+#CHECK-NEXT:    PhysicalAddress: 0x0
+#CHECK-NEXT:    FileSize: 12288
+#CHECK-NEXT:    MemSize: 12288
+#CHECK-NEXT:    Flags [ (0x5)
+#CHECK-NEXT:      PF_R (0x4)
+#CHECK-NEXT:      PF_X (0x1)
+#CHECK-NEXT:    ]
+#CHECK-NEXT:    Alignment: 4096
+#CHECK-NEXT:  }
+#CHECK-NEXT:]
diff --git a/llvm/test/tools/llvm-objcopy/symtab-error-on-remove-strtab.test b/llvm/test/tools/llvm-objcopy/symtab-error-on-remove-strtab.test
new file mode 100644
index 0000000..d960399
--- /dev/null
+++ b/llvm/test/tools/llvm-objcopy/symtab-error-on-remove-strtab.test
@@ -0,0 +1,11 @@
+# RUN: yaml2obj %s > %t
+# RUN: not llvm-objcopy -R .strtab %t %t2 2>&1 >/dev/null | FileCheck %s
+
+!ELF
+FileHeader:
+  Class:           ELFCLASS64
+  Data:            ELFDATA2LSB
+  Type:            ET_REL
+  Machine:         EM_X86_64
+
+# CHECK: String table .strtab cannot be removed because it is referenced by the symbol table .symtab