summaryrefslogtreecommitdiffstats
path: root/llvm/test/tools/llvm-objcopy
diff options
context:
space:
mode:
authorFangrui Song <maskray@google.com>2019-10-24 15:48:32 -0700
committerFangrui Song <maskray@google.com>2019-11-05 08:56:15 -0800
commit5ad0103d8a04cb066dfae4fc20b0dfcd9413f4d4 (patch)
tree65dcbcfccb35bf5353a1bfac0b665bbf7421e1e4 /llvm/test/tools/llvm-objcopy
parentade55d07871040d0e75b94e3d3a1eaecbd704d36 (diff)
downloadbcm5719-llvm-5ad0103d8a04cb066dfae4fc20b0dfcd9413f4d4.tar.gz
bcm5719-llvm-5ad0103d8a04cb066dfae4fc20b0dfcd9413f4d4.zip
[llvm-objcopy][ELF] Implement --only-keep-debug
--only-keep-debug produces a debug file as the output that only preserves contents of sections useful for debugging purposes (the binutils implementation preserves SHT_NOTE and non-SHF_ALLOC sections), by changing their section types to SHT_NOBITS and rewritting file offsets. See https://sourceware.org/gdb/onlinedocs/gdb/Separate-Debug-Files.html The intended use case is: ``` llvm-objcopy --only-keep-debug a a.dbg llvm-objcopy --strip-debug a b llvm-objcopy --add-gnu-debuglink=a.dbg b ``` The current layout algorithm is incapable of deleting contents and shrinking segments, so it is not suitable for implementing the functionality. This patch adds a new algorithm which assigns sh_offset to sections first, then modifies p_offset/p_filesz of program headers. It bears a resemblance to lld/ELF/Writer.cpp. Reviewed By: jhenderson, jakehehrlich Differential Revision: https://reviews.llvm.org/D67137
Diffstat (limited to 'llvm/test/tools/llvm-objcopy')
-rw-r--r--llvm/test/tools/llvm-objcopy/ELF/basic-only-keep-debug.test22
-rw-r--r--llvm/test/tools/llvm-objcopy/ELF/only-keep-debug.test224
2 files changed, 224 insertions, 22 deletions
diff --git a/llvm/test/tools/llvm-objcopy/ELF/basic-only-keep-debug.test b/llvm/test/tools/llvm-objcopy/ELF/basic-only-keep-debug.test
deleted file mode 100644
index 95cd07d0c26..00000000000
--- a/llvm/test/tools/llvm-objcopy/ELF/basic-only-keep-debug.test
+++ /dev/null
@@ -1,22 +0,0 @@
-# NOTE: This test is only intended to be valid as long as --only-keep-debug is
-# implemented as a NOP. This test should fail when that changes and you
-# will need to update this test.
-
-# RUN: yaml2obj %s > %t
-# RUN: llvm-objcopy %t %t2
-# RUN: llvm-objcopy --only-keep-debug %t %t3
-# RUN: cmp %t2 %t3
-# RUN: llvm-strip --only-keep-debug --no-strip-all %t -o %t4
-# RUN: cmp %t2 %t4
-
-!ELF
-FileHeader:
- Class: ELFCLASS64
- Data: ELFDATA2LSB
- Type: ET_EXEC
- Machine: EM_X86_64
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- Content: "DEADBEEF"
diff --git a/llvm/test/tools/llvm-objcopy/ELF/only-keep-debug.test b/llvm/test/tools/llvm-objcopy/ELF/only-keep-debug.test
new file mode 100644
index 00000000000..1dc29c97365
--- /dev/null
+++ b/llvm/test/tools/llvm-objcopy/ELF/only-keep-debug.test
@@ -0,0 +1,224 @@
+# RUN: yaml2obj --docnum=1 %s -o %t1
+# RUN: llvm-objcopy --only-keep-debug %t1 %t1.dbg
+# RUN: llvm-readelf -S -l -x .note1 -x .note2 -x .debug_abbrev -x .debug_frame -x .debug_info %t1.dbg | FileCheck %s
+
+## Check that SHT_NOTE and .debug* are kept, but others are changed to SHT_NOBITS.
+## SHT_NOBITS sections do not occupy space in the output.
+
+# CHECK: [Nr] Name Type Address Off Size ES Flg Lk Inf Al
+# CHECK: [ 1] .note1 NOTE 0000000000000400 000400 000001 00 A 0 0 1024
+# CHECK-NEXT: [ 2] .note2 NOTE 0000000000000401 000401 000001 00 A 0 0 0
+# CHECK-NEXT: [ 3] .text NOBITS 0000000000000402 000402 000001 00 AX 0 0 0
+# CHECK-NEXT: [ 4] .tdata NOBITS 0000000000001480 000480 000007 00 WAT 0 0 128
+# CHECK-NEXT: [ 5] .tbss NOBITS 0000000000001487 000480 000005 00 WAT 0 0 0
+# CHECK-NEXT: [ 6] .bss NOBITS 00000000000014a0 000480 00003f 00 WA 0 0 32
+## objcopy sets sh_offset to 0x402. We don't do this to keep sh_offset non-decreasing.
+# CHECK-NEXT: [ 7] .debug_abbrev PROGBITS 0000000000000000 000480 000001 00 0 0 0
+# CHECK-NEXT: [ 8] .debug_frame PROGBITS 0000000000000000 000488 000001 00 0 0 8
+# CHECK-NEXT: [ 9] .debug_info PROGBITS 0000000000000000 000489 000001 00 0 0 0
+# CHECK-NEXT: [10] .strtab STRTAB 0000000000000000 00048a 000001 00 0 0 1
+# CHECK-NEXT: [11] .shstrtab STRTAB 0000000000000000 00048b 000060 00 0 0 1
+
+# CHECK: Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
+# CHECK-NEXT: LOAD 0x000000 0x0000000000000000 0x0000000000000000 0x000402 0x000403 R E 0x1000
+# CHECK-NEXT: LOAD 0x000480 0x0000000000001480 0x0000000000000000 0x000000 0x00005f RW 0x1000
+# CHECK-NEXT: TLS 0x000480 0x0000000000001480 0x0000000000000000 0x000000 0x00000c RW 0x80
+# CHECK-NEXT: NOTE 0x000400 0x0000000000000400 0x0000000000000000 0x000002 0x000002 0x400
+
+## Contents of SHT_NOTE and .debug* are kept.
+
+# CHECK: Hex dump of section '.note1':
+# CHECK-NEXT: 0x00000400 01
+# CHECK: Hex dump of section '.note2':
+# CHECK-NEXT: 0x00000401 02
+# CHECK: Hex dump of section '.debug_abbrev':
+# CHECK-NEXT: 0x00000000 03
+# CHECK: Hex dump of section '.debug_frame':
+# CHECK-NEXT: 0x00000000 04
+# CHECK: Hex dump of section '.debug_info':
+# CHECK-NEXT: 0x00000000 05
+
+--- !ELF
+FileHeader:
+ Class: ELFCLASS64
+ Data: ELFDATA2LSB
+ Type: ET_DYN
+ Machine: EM_X86_64
+Sections:
+ - Name: .note1
+ Type: SHT_NOTE
+ Flags: [ SHF_ALLOC ]
+ Address: 0x400
+ AddressAlign: 0x400
+ Content: 01
+ - Name: .note2
+ Type: SHT_NOTE
+ Flags: [ SHF_ALLOC ]
+ Address: 0x401
+ Content: 02
+ - Name: .text
+ Type: SHT_PROGBITS
+ Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
+ Address: 0x402
+ Content: c3
+ - Name: .tdata
+ Type: SHT_PROGBITS
+ Flags: [ SHF_ALLOC, SHF_WRITE, SHF_TLS ]
+ Address: 0x1480 # Ensure Address=0x1000+Offset
+ AddressAlign: 0x80
+ # An arbitrary non-zero Size tests that .tdata does not occupy space
+ # and we can rewrite p_filesz of PT_TLS.
+ Size: 7
+ - Name: .tbss
+ Type: SHT_NOBITS
+ Flags: [ SHF_ALLOC, SHF_WRITE, SHF_TLS ]
+ Address: 0x1487 # Ensure Address=0x1000+Offset
+ Size: 5
+ - Name: .bss
+ Type: SHT_NOBITS
+ Flags: [ SHF_ALLOC, SHF_WRITE ]
+ Address: 0x14a0 # Ensure Address=0x1000+Offset
+ AddressAlign: 0x20
+ # An arbitrary non-zero Size tests that .bss does not occupy space.
+ Size: 63
+ - Name: .debug_abbrev
+ Type: SHT_PROGBITS
+ Content: 03
+ - Name: .debug_frame
+ Type: SHT_PROGBITS
+ # AddressAlign tests the file offset assignment leaves a gap.
+ AddressAlign: 0x8
+ Content: 04
+ - Name: .debug_info
+ Type: SHT_PROGBITS
+ Content: 05
+ProgramHeaders:
+ - Type: PT_LOAD
+ Flags: [ PF_R, PF_X ]
+ Offset: 0
+ Align: 0x1000
+ Sections:
+ - Section: .note1
+ - Section: .note2
+ - Section: .text
+ - Type: PT_LOAD
+ Flags: [ PF_R, PF_W ]
+ VAddr: 0x1480 # Ensure Offset=VAddr (mod Align) if Offset changes
+ Align: 0x1000
+ Sections:
+ - Section: .tdata
+ - Section: .bss
+ - Type: PT_TLS
+ Flags: [ PF_R, PF_W ]
+ VAddr: 0x1480 # Ensure Offset=VAddr (mod Align) if Offset changes
+ Sections:
+ - Section: .tdata
+ - Section: .tbss
+ - Type: PT_NOTE
+ VAddr: 0x400
+ Sections:
+ - Section: .note1
+ - Section: .note2
+...
+
+# RUN: yaml2obj --docnum=2 %s -o %t2
+# RUN: llvm-objcopy --only-keep-debug %t2 %t2.dbg
+# RUN: llvm-readelf -S -l %t2.dbg | FileCheck --check-prefix=CHECK2 %s
+
+## Only the tail of a segment can be trimmed. .text still occupies space because
+## it is followed by .note which is not SHT_NOBITS.
+# CHECK2: [Nr] Name Type Address Off Size ES Flg Lk Inf Al
+# CHECK2: [ 1] .text NOBITS 0000000000000200 000200 000001 00 AX 0 0 512
+# CHECK2-NEXT: [ 2] .note NOTE 0000000000000201 000201 000001 00 A 0 0 0
+# CHECK2-NEXT: [ 3] .debug_info PROGBITS 0000000000000000 000220 000001 00 0 0 32
+# CHECK2-NEXT: [ 4] .strtab STRTAB 0000000000000000 000221 000001 00 0 0 1
+# CHECK2-NEXT: [ 5] .shstrtab STRTAB 0000000000000000 000222 00002b 00 0 0 1
+
+## Check that p_offset or p_filesz of empty segments or PT_PHDR are not modified.
+# CHECK2: Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
+# CHECK2-NEXT: PHDR 0x000040 0x0000000000000040 0x0000000000000000 0x0000a8 0x0000a8 R 0x8
+# CHECK2-NEXT: LOAD 0x000000 0x0000000000000000 0x0000000000000000 0x000202 0x000202 R E 0x1000
+# CHECK2-NEXT: LOAD 0x000202 0x0000000000000202 0x0000000000000000 0x00000e 0x00000e RW 0x1
+
+--- !ELF
+FileHeader:
+ Class: ELFCLASS64
+ Data: ELFDATA2LSB
+ Type: ET_DYN
+ Machine: EM_X86_64
+Sections:
+ - Name: .text
+ Type: SHT_PROGBITS
+ Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
+ Address: 0x200
+ AddressAlign: 0x200
+ Content: c3
+ - Name: .note
+ Type: SHT_NOTE
+ Flags: [ SHF_ALLOC ]
+ Address: 0x201
+ Content: 01
+ - Name: .debug_info
+ Type: SHT_PROGBITS
+ AddressAlign: 0x20
+ Content: 02
+ProgramHeaders:
+ - Type: PT_PHDR
+ Flags: [ PF_R ]
+ Offset: 0x40
+ VAddr: 0x40
+ # 3 * sizeof(Elf64_Phdr) = 0xa8
+ FileSize: 0xa8
+ MemSize: 0xa8
+ Align: 8
+ - Type: PT_LOAD
+ Flags: [ PF_R, PF_X ]
+ Offset: 0
+ Align: 4096
+ Sections:
+ - Section: .text
+ - Section: .note
+ - Type: PT_LOAD
+ Flags: [ PF_R, PF_W ]
+ Offset: 0x202
+ VAddr: 0x202
+ FileSize: 14
+ MemSize: 14
+...
+
+## If .symtab or .strtab has the SHF_ALLOC flag, it will be changed to SHT_NOBITS.
+# RUN: yaml2obj --docnum=3 %s -o %t3
+# RUN: llvm-objcopy --only-keep-debug %t3 %t3.dbg
+# RUN: llvm-readelf -S -l %t3.dbg | FileCheck --check-prefix=CHECK3 %s
+
+# CHECK3: [Nr] Name Type Address Off Size ES Flg Lk Inf Al
+# CHECK3: [ 1] .dynsym NOBITS 0000000000000000 000040 000018 18 A 2 1 1024
+# CHECK3-NEXT: [ 2] .dynstr NOBITS 0000000000000000 000040 000001 00 A 0 0 0
+# CHECK3-NEXT: [ 3] .symtab NOBITS 0000000000000000 000040 000018 18 A 4 1 0
+# CHECK3-NEXT: [ 4] .strtab NOBITS 0000000000000000 000040 000001 00 A 0 0 0
+# CHECK3-NEXT: [ 5] .shstrtab STRTAB 0000000000000000 000040 00002b 00 0 0 1
+
+--- !ELF
+FileHeader:
+ Class: ELFCLASS64
+ Data: ELFDATA2LSB
+ Type: ET_DYN
+ Machine: EM_X86_64
+Sections:
+ - Name: .dynsym
+ Type: SHT_DYNSYM
+ Flags: [ SHF_ALLOC ]
+ Link: .dynstr
+ AddressAlign: 0x400
+ - Name: .dynstr
+ Type: SHT_STRTAB
+ Flags: [ SHF_ALLOC ]
+ - Name: .symtab
+ Type: SHT_STRTAB
+ Flags: [ SHF_ALLOC ]
+ Link: .strtab
+ - Name: .strtab
+ Type: SHT_STRTAB
+ Flags: [ SHF_ALLOC ]
+DynamicSymbols: []
+Symbols: []
OpenPOWER on IntegriCloud