diff options
author | Fangrui Song <maskray@google.com> | 2019-10-24 15:48:32 -0700 |
---|---|---|
committer | Fangrui Song <maskray@google.com> | 2019-11-05 08:56:15 -0800 |
commit | 5ad0103d8a04cb066dfae4fc20b0dfcd9413f4d4 (patch) | |
tree | 65dcbcfccb35bf5353a1bfac0b665bbf7421e1e4 /llvm/test/tools/llvm-objcopy/ELF/only-keep-debug.test | |
parent | ade55d07871040d0e75b94e3d3a1eaecbd704d36 (diff) | |
download | bcm5719-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/ELF/only-keep-debug.test')
-rw-r--r-- | llvm/test/tools/llvm-objcopy/ELF/only-keep-debug.test | 224 |
1 files changed, 224 insertions, 0 deletions
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: [] |