[llvm-objcopy][llvm-strip] Add switch to allow removing referenced sections

llvm-objcopy currently emits an error if a section to be removed is
referenced by another section. This is a reasonable thing to do, but is
different to GNU objcopy. We should allow users who know what they are
doing to have a way to produce the invalid ELF. This change adds a new
switch --allow-broken-links to both llvm-strip and llvm-objcopy to do
precisely that. The corresponding sh_link field is then set to 0 instead
of an error being emitted.

I cannot use llvm-readelf/readobj to test the link fields because they
emit an error if any sections, like the .dynsym, cannot be properly
loaded.

Reviewed by: rupprecht, grimar

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

llvm-svn: 358649
diff --git a/llvm/test/tools/llvm-objcopy/ELF/dynsym-error-remove-strtab.test b/llvm/test/tools/llvm-objcopy/ELF/dynsym-error-remove-strtab.test
index a6df5df..6e63c23 100644
--- a/llvm/test/tools/llvm-objcopy/ELF/dynsym-error-remove-strtab.test
+++ b/llvm/test/tools/llvm-objcopy/ELF/dynsym-error-remove-strtab.test
@@ -1,3 +1,16 @@
-# RUN: not llvm-objcopy -R .dynstr %p/Inputs/dynsym.so %t 2>&1 >/dev/null | FileCheck %s
+# RUN: not llvm-objcopy -R .dynstr %p/Inputs/dynsym.so %t 2>&1 >/dev/null | FileCheck %s --check-prefix=ERR
+# RUN: cp  %p/Inputs/dynsym.so %t2
+## Use --strip-debug to suppress the default --strip-all behavior of llvm-strip.
+## TODO: Implement a better way to suppress --strip-all behavior.
+# RUN: not llvm-strip --strip-debug -R .dynstr %t2 2>&1 >/dev/null | FileCheck %s --check-prefix=ERR
 
-# CHECK: Section .dynstr cannot be removed because it is referenced by the section .dynsym
+# ERR: Section .dynstr cannot be removed because it is referenced by the section .dynsym
+
+# RUN: llvm-objcopy --allow-broken-links -R .dynstr %p/Inputs/dynsym.so %t3
+# RUN: llvm-objdump --section-headers %t3 | FileCheck %s --check-prefix=SECTIONS --implicit-check-not=.dynstr
+# RUN: cp  %p/Inputs/dynsym.so %t4
+# RUN: llvm-strip --strip-debug --allow-broken-links -R .dynstr %t4
+# RUN: llvm-objdump --section-headers %t4 | FileCheck %s --check-prefix=SECTIONS --implicit-check-not=.dynstr
+
+# SECTIONS: .dynsym
+# SECTIONS: .dynamic
diff --git a/llvm/test/tools/llvm-objcopy/ELF/reloc-error-remove-symtab.test b/llvm/test/tools/llvm-objcopy/ELF/reloc-error-remove-symtab.test
index ff05778..9b6d611 100644
--- a/llvm/test/tools/llvm-objcopy/ELF/reloc-error-remove-symtab.test
+++ b/llvm/test/tools/llvm-objcopy/ELF/reloc-error-remove-symtab.test
@@ -1,5 +1,9 @@
 # RUN: yaml2obj %s > %t
-# RUN: not llvm-objcopy -R .symtab %t %t2 2>&1 >/dev/null | FileCheck %s
+# RUN: not llvm-objcopy -R .symtab %t %t2 2>&1 >/dev/null | FileCheck %s --check-prefix=ERR
+# RUN: cp %t %t3
+## Use --strip-debug to suppress the default --strip-all behavior of llvm-strip.
+## TODO: Implement a better way to suppress --strip-all behavior.
+# RUN: not llvm-strip --strip-debug -R .symtab %t3 2>&1 >/dev/null | FileCheck %s --check-prefix=ERR
 
 !ELF
 FileHeader:
@@ -29,4 +33,14 @@
     Size:     4
     Binding:  STB_GLOBAL
 
-# CHECK: Symbol table .symtab cannot be removed because it is referenced by the relocation section .rel.text.
+# ERR: Symbol table .symtab cannot be removed because it is referenced by the relocation section .rel.text.
+
+# RUN: llvm-objcopy --allow-broken-links -R .symtab %t %t4
+# RUN: llvm-readobj --sections %t4 | FileCheck %s --check-prefix=SECTIONS --implicit-check-not=.symtab
+# RUN: cp %t %t5
+# RUN: llvm-strip --strip-debug --allow-broken-links -R .symtab %t5
+# RUN: llvm-readobj --sections %t5 | FileCheck %s --check-prefix=SECTIONS --implicit-check-not=.symtab
+
+# SECTIONS:        Name: .rel.text
+# SECTIONS:        Link
+# SECTIONS-SAME: : 0
diff --git a/llvm/test/tools/llvm-objcopy/ELF/remove-linked-section.test b/llvm/test/tools/llvm-objcopy/ELF/remove-linked-section.test
new file mode 100644
index 0000000..63ba9d1
--- /dev/null
+++ b/llvm/test/tools/llvm-objcopy/ELF/remove-linked-section.test
@@ -0,0 +1,31 @@
+# RUN: yaml2obj %s -o %t.o
+# RUN: not llvm-objcopy -R .foo %t.o %t1 2>&1 >/dev/null | FileCheck %s --check-prefix=ERR
+# RUN: cp %t.o %t2
+## Use --strip-debug to suppress the default --strip-all behavior of llvm-strip.
+## TODO: Implement a better way to suppress --strip-all behavior.
+# RUN: not llvm-strip --strip-debug -R .foo %t2 2>&1 >/dev/null | FileCheck %s --check-prefix=ERR
+
+--- !ELF
+FileHeader:
+  Class:           ELFCLASS64
+  Data:            ELFDATA2LSB
+  Type:            ET_REL
+  Machine:         EM_X86_64
+Sections:
+  - Name:            .foo
+    Type:            SHT_PROGBITS
+  - Name:            .bar
+    Type:            SHT_PROGBITS
+    Link:            .foo
+
+# ERR: Section .foo cannot be removed because it is referenced by the section .bar
+
+# RUN: llvm-objcopy --allow-broken-links -R .foo %t.o %t3
+# RUN: llvm-readobj --sections %t3 | FileCheck %s --check-prefix=SECTIONS --implicit-check-not=.foo
+# RUN: cp %t.o %t4
+# RUN: llvm-strip --strip-debug --allow-broken-links -R .foo %t4
+# RUN: llvm-readobj --sections %t4 | FileCheck %s --check-prefix=SECTIONS --implicit-check-not=.foo
+
+# SECTIONS:      Name: .bar
+# SECTIONS:      Link
+# SECTIONS-SAME: : 0
diff --git a/llvm/test/tools/llvm-objcopy/ELF/symtab-error-on-remove-strtab.test b/llvm/test/tools/llvm-objcopy/ELF/symtab-error-on-remove-strtab.test
index d960399..2115358 100644
--- a/llvm/test/tools/llvm-objcopy/ELF/symtab-error-on-remove-strtab.test
+++ b/llvm/test/tools/llvm-objcopy/ELF/symtab-error-on-remove-strtab.test
@@ -1,5 +1,9 @@
 # RUN: yaml2obj %s > %t
-# RUN: not llvm-objcopy -R .strtab %t %t2 2>&1 >/dev/null | FileCheck %s
+# RUN: not llvm-objcopy -R .strtab %t %t2 2>&1 >/dev/null | FileCheck %s --check-prefix=ERR
+# RUN: cp %t %t3
+## Use --strip-debug to suppress the default --strip-all behavior of llvm-strip.
+## TODO: Implement a better way to suppress --strip-all behavior.
+# RUN: not llvm-strip --strip-debug -R .strtab %t3 2>&1 >/dev/null | FileCheck %s --check-prefix=ERR
 
 !ELF
 FileHeader:
@@ -8,4 +12,12 @@
   Type:            ET_REL
   Machine:         EM_X86_64
 
-# CHECK: String table .strtab cannot be removed because it is referenced by the symbol table .symtab
+# ERR: String table .strtab cannot be removed because it is referenced by the symbol table .symtab
+
+# RUN: llvm-objcopy --allow-broken-links -R .strtab %t %t4
+# RUN: llvm-objdump --section-headers %t4 | FileCheck %s --check-prefix=SECTIONS --implicit-check-not=.strtab
+# RUN: cp %t %t5
+# RUN: llvm-strip --strip-debug --allow-broken-links -R .strtab %t %t5
+# RUN: llvm-objdump --section-headers %t5 | FileCheck %s --check-prefix=SECTIONS --implicit-check-not=.strtab
+
+# SECTIONS: .symtab