# 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 ## --only-keep-debug suppresses the default --strip-all. # RUN: llvm-strip --only-keep-debug %t1 # RUN: llvm-readelf -S -l -x .note1 -x .note2 -x .debug_abbrev -x .debug_frame -x .debug_info %t1 | 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 0x0000000000001480 0x000000 0x00005f RW 0x1000 # CHECK-NEXT: TLS 0x000480 0x0000000000001480 0x0000000000001480 0x000000 0x00000c RW 0x80 # CHECK-NEXT: NOTE 0x000400 0x0000000000000400 0x0000000000000400 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 FirstSec: .note1 LastSec: .text - Type: PT_LOAD Flags: [ PF_R, PF_W ] VAddr: 0x1480 # Ensure Offset=VAddr (mod Align) if Offset changes Align: 0x1000 FirstSec: .tdata LastSec: .bss - Type: PT_TLS Flags: [ PF_R, PF_W ] VAddr: 0x1480 # Ensure Offset=VAddr (mod Align) if Offset changes FirstSec: .tdata LastSec: .tbss - Type: PT_NOTE VAddr: 0x400 FirstSec: .note1 LastSec: .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 PT_PHDR are not modified. # CHECK2: Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align # CHECK2-NEXT: PHDR 0x000040 0x0000000000000040 0x0000000000000040 0x0000a8 0x0000a8 R 0x8 # CHECK2-NEXT: LOAD 0x000000 0x0000000000000000 0x0000000000000000 0x000202 0x000202 R E 0x1000 # CHECK2-NEXT: LOAD 0x000000 0x0000000000000202 0x0000000000000202 0x000000 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 FirstSec: .text LastSec: .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 0000000000000018 000040 000001 00 A 0 0 0 # CHECK3-NEXT: [ 3] .symtab NOBITS 0000000000000019 000040 000018 00 A 4 1 0 # CHECK3-NEXT: [ 4] .strtab NOBITS 0000000000000031 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 ## TODO: this should be SHT_SYMTAB, but currently llvm-objcopy reports an error: ## error: Symbol table has link index of 4 which is not a string table Type: SHT_STRTAB Flags: [ SHF_ALLOC ] Link: .strtab - Name: .strtab Type: SHT_STRTAB Flags: [ SHF_ALLOC ] DynamicSymbols: [] Symbols: [] ## PT_TLS and .tdata are empty. Test that we set its p_offset to the parent ## segment's p_offset. If we don't rewrite the p_offset of PT_TLS and the deleted ## bytes are large, p_offset can be larger than the file size, and trigger ## validation errors with subsequent tools. # RUN: yaml2obj --docnum=4 %s -o %t4 # RUN: llvm-objcopy --only-keep-debug %t4 %t4.dbg # RUN: llvm-readelf -S -l %t4.dbg | FileCheck --check-prefix=CHECK4 %s # CHECK4: [Nr] Name Type Address Off Size ES Flg Lk Inf Al # CHECK4: [ 1] .text NOBITS 0000000000000200 000200 000001 00 AX 0 0 0 # CHECK4-NEXT: [ 2] .tdata NOBITS 0000000000001240 000240 000000 00 WAT 0 0 64 # CHECK4-NEXT: [ 3] .got NOBITS 0000000000001240 000240 000008 00 WA 0 0 0 # CHECK4: Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align # CHECK4-NEXT: LOAD 0x000200 0x0000000000000200 0x0000000000000200 0x000000 0x000001 R E 0x1000 # CHECK4-NEXT: LOAD 0x000240 0x0000000000001240 0x0000000000001240 0x000000 0x000008 RW 0x1000 # CHECK4-NEXT: TLS 0x000240 0x0000000000001240 0x0000000000001240 0x000000 0x000000 R 0x40 --- !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 Size: 1 - Name: .tdata Type: SHT_PROGBITS Flags: [ SHF_ALLOC, SHF_WRITE, SHF_TLS ] Address: 0x1240 # Ensure Address=0x1000+Offset AddressAlign: 0x40 - Name: .got Type: SHT_PROGBITS Flags: [ SHF_ALLOC, SHF_WRITE ] Size: 8 ProgramHeaders: - Type: PT_LOAD Flags: [ PF_R, PF_X ] VAddr: 0x200 Align: 0x1000 FirstSec: .text LastSec: .text ## Add .got so that the PT_LOAD does not have zero p_memsz. We don't add ## sections to zero-sized segments so zero-sized segments may have strange ## offsets. In practice, the Linux kernel errors when mmapping a p_memsz ## PT_LOAD,so for practical so this assumption can generally be made. - Type: PT_LOAD Flags: [ PF_R, PF_W ] VAddr: 0x1240 Align: 0x1000 FirstSec: .tdata LastSec: .got - Type: PT_TLS Flags: [ PF_R ] VAddr: 0x1240 FirstSec: .tdata LastSec: .tdata ## The offset and size fields of segments which contain no section and have no ## parent segment are set to zeros, so that we can decrease the file size. Such ## segments are not useful for debugging. # RUN: yaml2obj --docnum=5 %s -o %t5 # RUN: llvm-objcopy --only-keep-debug %t5 %t5.dbg # RUN: llvm-readelf -S -l %t5.dbg | FileCheck --check-prefix=CHECK5 %s # RUN: llvm-objcopy --strip-sections %t5 %t5s # RUN: llvm-objcopy --only-keep-debug %t5s %t5s.dbg # RUN: llvm-readelf -S -l %t5s.dbg | FileCheck --check-prefix=CHECK5S %s # CHECK5: [Nr] Name Type Address Off Size ES Flg Lk Inf Al # CHECK5: [ 1] .foo NOBITS 0000000000000000 000078 001000 00 A 0 0 0 # CHECK5-NEXT: [ 2] .strtab STRTAB 0000000000000000 000078 000001 00 0 0 1 # CHECK5-NEXT: [ 3] .shstrtab STRTAB 0000000000000000 000079 000018 00 0 0 1 # CHECK5: Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align # CHECK5-NEXT: NULL 0x000000 0x0000000000000000 0x0000000000000000 0x000078 0x001000 0x1 # CHECK5-EMPTY: # CHECK5S: Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align # CHECK5S-NEXT: NULL 0x000000 0x0000000000000000 0x0000000000000000 0x000078 0x001000 0x1 # CHECK5S-EMPTY: --- !ELF FileHeader: Class: ELFCLASS64 Data: ELFDATA2LSB Type: ET_DYN Sections: - Name: .foo Type: SHT_PROGBITS Flags: [ SHF_ALLOC ] Size: 0x01000 ProgramHeaders: - Type: PT_NULL Flags: [] FileSize: 0x01000 MemSize: 0x01000 ## Check that sections are placed correctly in a case when their order in the ## section header table is different from their layout. # RUN: yaml2obj --docnum=6 %s -o %t6 # RUN: llvm-objcopy --only-keep-debug %t6 %t6.dbg # RUN: llvm-readelf -S -l %t6.dbg | FileCheck --check-prefix=CHECK6 %s # CHECK6: [Nr] Name Type Address Off Size ES Flg Lk Inf Al # CHECK6: [ 1] foo NOBITS 0000000000000008 001000 000008 00 A 0 0 4 # CHECK6-NEXT: [ 2] bar NOBITS 0000000000000000 001000 000008 00 A 0 0 4 # CHECK6-NEXT: [ 3] baz NOTE 0000000000000018 001008 000008 00 A 0 0 0 # CHECK6-NEXT: [ 4] qux NOTE 0000000000000010 001000 000008 00 A 0 0 0 # CHECK6: Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align # CHECK6-NEXT: LOAD 0x001000 0x0000000000000000 0x0000000000000000 0x000000 0x000010 R 0x1000 # CHECK6-NEXT: LOAD 0x001000 0x0000000000000010 0x0000000000000010 0x000010 0x000010 R 0x1 # CHECK6-EMPTY: --- !ELF FileHeader: Class: ELFCLASS64 Data: ELFDATA2LSB Type: ET_DYN Machine: EM_X86_64 ProgramHeaders: - Type: PT_LOAD Flags: [ PF_R ] Offset: 0x1000 VAddr: 0x0 Align: 0x1000 FileSize: 0x10 MemSize: 0x10 - Type: PT_LOAD Flags: [ PF_R ] Offset: 0x1010 VAddr: 0x10 FileSize: 0x10 MemSize: 0x10 Sections: - Name: bar Type: SHT_PROGBITS Flags: [ SHF_ALLOC ] Address: 0x0 AddressAlign: 0x4 Offset: 0x1000 Content: 0000000000000000 - Name: foo Type: SHT_PROGBITS Flags: [ SHF_ALLOC ] Address: 0x8 AddressAlign: 0x4 Offset: 0x1008 Content: 0000000000000000 - Name: qux Type: SHT_NOTE Flags: [ SHF_ALLOC ] Address: 0x10 Offset: 0x1010 Content: 0000000000000000 - Name: baz Type: SHT_NOTE Flags: [ SHF_ALLOC ] Address: 0x18 Offset: 0x1018 Content: 0000000000000000 - Type: SectionHeaderTable Sections: ## Note: the order of section headers differs from their layout. - Name: foo - Name: bar - Name: baz - Name: qux - Name: .shstrtab - Name: .strtab