[llvm-objcopy] Add additional testing for various cases

This patch adds a number of tests to test various cases not covered by
existing tests. All of them work correctly, with no need to change
llvm-objcopy itself, although some do indicate possible areas for
improvement.

Reviewed by: MaskRay

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


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@360422 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
James Henderson
2019-05-10 12:58:52 +00:00
parent 06b700153b
commit e8d332f233
10 changed files with 497 additions and 41 deletions
@@ -0,0 +1,31 @@
## If the e_phoff field is set to a value either past the end of the file, or
## such that e_phoff + e_phnum * sizeof(Elf_Phdr) is past the end of the file,
## we should emit an error. This test checks that the emitted error is sensible.
# RUN: yaml2obj %s -o %t.o
## Remove the default section headers so that the section header table is not invalid.
# RUN: llvm-objcopy --strip-sections %t.o
# RUN: cp %t.o %t2.o
## Sanity check that the phdr table is at offset 64:
# RUN: llvm-readobj --file-headers %t.o | FileCheck %s --check-prefix=VALIDATE
# VALIDATE: ProgramHeaderOffset: 0x40{{$}}
## Truncate the file to end before the program header table ends.
# RUN: %python -c "with open('%/t.o', 'r+b') as input: input.truncate(65)"
# RUN: not llvm-objcopy %t.o 2>&1 | FileCheck %s
## Set the e_phoff field to a value much larger than the object file size.
# RUN: %python -c "with open('%/t2.o', 'r+b') as input: import struct; bytes = struct.pack('<Q', 0x40000000); input.seek(32); input.write(bytes)"
# RUN: not llvm-objcopy %t2.o 2>&1 | FileCheck %s
--- !ELF
FileHeader:
Class: ELFCLASS64
Data: ELFDATA2LSB
Type: ET_EXEC
Machine: EM_X86_64
ProgramHeaders:
- Type: PT_LOAD
# CHECK: error: program headers longer than binary
@@ -0,0 +1,30 @@
## If the e_shoff field is set to a value either past the end of the file, or
## such that e_shoff + e_shnum * sizeof(Elf_Shdr) is past the end of the file,
## we should emit an error. This test checks that the emitted error is sensible.
# RUN: yaml2obj %s -o %t.o
# RUN: cp %t.o %t2.o
## Sanity check that the section header table is at offset 64:
# RUN: llvm-readobj --file-headers %t.o | FileCheck %s --check-prefix=VALIDATE
# VALIDATE: SectionHeaderOffset: 0x40{{$}}
## Truncate the file to end before the section header table ends.
# RUN: %python -c "with open('%/t.o', 'r+b') as input: input.truncate(65)"
# RUN: not llvm-objcopy %t.o 2>&1 | FileCheck %s -DINPUT=%t.o
## Set the e_shoff field to a value much larger than the object file size.
# RUN: %python -c "with open('%/t2.o', 'r+b') as input: import struct; bytes = struct.pack('<Q', 0x40000000); input.seek(40); input.write(bytes)"
# RUN: not llvm-objcopy %t2.o 2>&1 | FileCheck %s -DINPUT=%t2.o
--- !ELF
FileHeader:
Class: ELFCLASS64
Data: ELFDATA2LSB
Type: ET_EXEC
Machine: EM_X86_64
Sections:
- Name: .foo
Type: SHT_PROGBITS
# CHECK: error: '[[INPUT]]': section header table goes past the end of the file
@@ -0,0 +1,29 @@
## This test checks that if a section has a sh_link field, and one or more
## sections are removed such that the target section index changes, then
## llvm-objcopy correctly updates the sh_link field.
# RUN: yaml2obj %s -o %t.o
# RUN: llvm-objcopy --remove-section .foo %t.o %t2.o
# RUN: llvm-readobj --section-headers %t2.o | FileCheck %s
--- !ELF
FileHeader:
Class: ELFCLASS64
Data: ELFDATA2LSB
Type: ET_EXEC
Machine: EM_X86_64
Sections:
- Name: .foo
Type: SHT_PROGBITS
- Name: .bar
Type: SHT_PROGBITS
- Name: .baz
Type: SHT_PROGBITS
Link: .bar
# CHECK: Index: 1
# CHECK-NEXT: Name: .bar
# CHECK: Name: .baz
## Find the next "Link" line, then check the value is exactly the index of .bar.
# CHECK: Link
# CHECK-SAME: : 1{{$}}
@@ -0,0 +1,56 @@
## This test shows that llvm-objcopy does not baulk at overlapping sections
## where such sections are within segments.
## These don't really make sense, but the tool should still handle invalid
## inputs somehow.
# RUN: yaml2obj %s -o %t.o
## First, check that the section header table appears immediately after the program
## header table.
# RUN: llvm-readobj --file-headers %t.o | FileCheck %s --check-prefix=SHDRS-OFFSET
# SHDRS-OFFSET: SectionHeaderOffset: 0x78{{$}}
## Binary edit the section header sh_offset field of the second section to
## overlap the first one.
# RUN: %python -c "with open('%/t.o', 'r+b') as input: import struct; bytes = struct.pack('<Q', 0x1001); input.seek(272); input.write(bytes)"
## Sanity check that the binary editing modified the correct field.
# RUN: llvm-readobj --section-headers %t.o | FileCheck %s
## Check that the contents are as expected before the copy.
# RUN: llvm-readobj -x .first -x .second %t.o | FileCheck %s --check-prefix=CONTENTS
## Now check that the section contents are still correct after the copy and show that
## llvm-objcopy hasn't "unoverlapped" these sections because they are in segments.
# RUN: llvm-objcopy %t.o %t2.o
# RUN: llvm-readobj --section-headers %t2.o | FileCheck %s
# RUN: llvm-readobj -x .first -x .second %t2.o | FileCheck %s --check-prefix=CONTENTS
# CHECK: Name: .first
# CHECK: Offset: 0x1000
# CHECK: Name: .second
# CHECK: Offset: 0x1001
# CONTENTS: Hex dump of section '.first':
# CONTENTS-NEXT: 0x00000000 01234567
# CONTENTS-NEXT: Hex dump of section '.second':
# CONTENTS-NEXT: 0x00000000 23456789
--- !ELF
FileHeader:
Class: ELFCLASS64
Data: ELFDATA2LSB
Type: ET_EXEC
Machine: EM_X86_64
Sections:
- Name: .first
Type: SHT_PROGBITS
Content: '01234567'
AddressAlign: 0x1000
- Name: .second
Type: SHT_PROGBITS
Content: '89abcdef'
ProgramHeaders:
- Type: PT_LOAD
FileSize: 5
Offset: 0x1000
Align: 0x1000
@@ -0,0 +1,56 @@
## This test shows that llvm-objcopy does not baulk at overlapping sections.
## These don't really make sense, but the tool should still handle invalid
## inputs somehow.
# RUN: yaml2obj %s -o %t.o
## First, check that the section header table appears immediately after the ELF
## header.
# RUN: llvm-readobj --file-headers %t.o | FileCheck %s --check-prefix=SHDRS-OFFSET
# SHDRS-OFFSET: SectionHeaderOffset: 0x40{{$}}
## Binary edit the section header sh_offset field of the second section to
## overlap the first one.
# RUN: %python -c "with open('%/t.o', 'r+b') as input: import struct; bytes = struct.pack('<Q', 0x1001); input.seek(216); input.write(bytes)"
## Sanity check that the binary editing modified the correct field.
# RUN: llvm-readobj --section-headers %t.o | FileCheck %s --check-prefix=VALIDATE
# VALIDATE: Name: .first
# VALIDATE: Offset: 0x1000
# VALIDATE: Name: .second
# VALIDATE: Offset: 0x1001
## Check that the contents are as expected before the copy.
# RUN: llvm-readobj -x .first -x .second %t.o | FileCheck %s --check-prefix=CONTENTS
## Now check that the section contents are still correct after the copy.
## Also characterize the behavior of llvm-objcopy in that it "unoverlaps" the
## two sections.
# RUN: llvm-objcopy %t.o %t2.o
# RUN: llvm-readobj --section-headers %t2.o | FileCheck %s
# RUN: llvm-readobj -x .first -x .second %t2.o | FileCheck %s --check-prefix=CONTENTS
# CHECK: Name: .first
# CHECK: Offset: 0x1000
# CHECK: Name: .second
# CHECK: Offset: 0x1004
# CONTENTS: Hex dump of section '.first':
# CONTENTS-NEXT: 0x00000000 01234567
# CONTENTS-NEXT: Hex dump of section '.second':
# CONTENTS-NEXT: 0x00000000 23456789
--- !ELF
FileHeader:
Class: ELFCLASS64
Data: ELFDATA2LSB
Type: ET_EXEC
Machine: EM_X86_64
Sections:
- Name: .first
Type: SHT_PROGBITS
Content: '01234567'
AddressAlign: 0x1000
- Name: .second
Type: SHT_PROGBITS
Content: '89abcdef'
@@ -0,0 +1,30 @@
## When multiple sections have the same name, and --rename-section is specified,
## GNU objcopy renames all these sections. This test shows that llvm-objcopy
## does the same.
## Note: we have to do this test in two stages because yaml2obj cannot handle
## multiple sections with the same name. This has the benefit of showing that
## we can rename to an already existing name.
# RUN: yaml2obj %s -o %t.o
## First make two sections with the same name...
# RUN: llvm-objcopy --rename-section=.foo=.bar %t.o %t2.o
## ... then rename them both.
# RUN: llvm-objcopy --rename-section=.bar=.baz %t2.o %t3.o
# RUN: llvm-readobj --sections %t3.o | FileCheck %s
--- !ELF
FileHeader:
Class: ELFCLASS64
Data: ELFDATA2LSB
Type: ET_REL
Machine: EM_X86_64
Sections:
- Name: .foo
Type: SHT_PROGBITS
Flags: [ SHF_ALLOC ]
- Name: .bar
Type: SHT_PROGBITS
# CHECK: Name: .baz
# CHECK: Name: .baz
@@ -0,0 +1,24 @@
## This test verifies that llvm-objcopy can handle renaming a section to and
## from an empty string.
# RUN: yaml2obj %s -o %t.o
# RUN: llvm-objcopy %t.o %t2.o --rename-section=.foo=
# RUN: llvm-readobj --sections %t2.o | FileCheck %s --check-prefix=TO
# RUN: llvm-objcopy %t2.o %t3.o --rename-section==.bar
# RUN: llvm-readobj --sections %t3.o | FileCheck %s --check-prefix=FROM
--- !ELF
FileHeader:
Class: ELFCLASS64
Data: ELFDATA2LSB
Type: ET_REL
Machine: EM_X86_64
Sections:
- Name: .foo
Type: SHT_PROGBITS
# TO: Index: 1
# TO-NEXT: Name: (0)
# FROM: Index: 1
# FROM-NEXT: Name: .bar (
@@ -0,0 +1,106 @@
# REQUIRES: x86-registered-target
## It is possible for the section header table and symbol table to share the
## same string table for storing section and symbol names. This test shows that
## under various circumstances, the names are still correct after llvm-objcopy
## has copied such an object file, and that the name table is still shared.
## This test uses the assembler rather than yaml2obj because yaml2obj generates
## separate string tables, whereas the assembler shares them.
# RUN: llvm-mc -filetype=obj -triple x86_64-pc-linux %s -o %t.o
## Sanity check that the string tables are shared:
# RUN: llvm-readobj --section-headers %t.o \
# RUN: | FileCheck %s --check-prefix=VALIDATE --implicit-check-not=.shstrtab
# VALIDATE: Name: .strtab
## Case 1: basic copy.
# RUN: llvm-objcopy %t.o %t.basic
# RUN: llvm-readobj --section-headers --symbols %t.basic \
# RUN: | FileCheck %s --check-prefix=BASIC --implicit-check-not=.shstrtab
# BASIC: Sections [
# BASIC: Name: .foo (
# BASIC: Name: .strtab (
# BASIC: Symbols [
# BASIC: Name: foo (
## Case 2: renaming a section.
# RUN: llvm-objcopy %t.o %t.rename-section --rename-section .foo=.oof
# RUN: llvm-readobj --section-headers --symbols %t.rename-section \
# RUN: | FileCheck %s --check-prefix=SECTION-RENAME --implicit-check-not=.shstrtab
# SECTION-RENAME: Sections [
# SECTION-RENAME: Name: .oof (
# SECTION-RENAME: Name: .strtab (
# SECTION-RENAME: Symbols [
# SECTION-RENAME: Name: foo (
## Case 3: renaming a symbol.
# RUN: llvm-objcopy %t.o %t.redefine-symbol --redefine-sym foo=oof
# RUN: llvm-readobj --section-headers --symbols %t.redefine-symbol \
# RUN: | FileCheck %s --check-prefix=SYMBOL-RENAME --implicit-check-not=.shstrtab
# SYMBOL-RENAME: Sections [
# SYMBOL-RENAME: Name: .foo (
# SYMBOL-RENAME: Name: .strtab (
# SYMBOL-RENAME: Symbols [
# SYMBOL-RENAME: Name: oof (
## Case 4: removing a section.
# RUN: llvm-objcopy %t.o %t.remove-section -R .foo
# RUN: llvm-readobj --section-headers --symbols %t.remove-section \
# RUN: | FileCheck %s --check-prefix=SECTION-REMOVE --implicit-check-not=.shstrtab --implicit-check-not=.foo
# SECTION-REMOVE: Sections [
# SECTION-REMOVE: Name: .strtab (
# SECTION-REMOVE: Symbols [
# SECTION-REMOVE: Name: foo (
## Case 5: removing a symbol.
# RUN: llvm-objcopy %t.o %t.remove-symbol -N foo
# RUN: llvm-readobj --section-headers --symbols %t.remove-symbol \
# RUN: | FileCheck %s --check-prefix=SYMBOL-REMOVE --implicit-check-not=.shstrtab --implicit-check-not=foo
# SYMBOL-REMOVE: Sections [
# SYMBOL-REMOVE: Name: .foo (
# SYMBOL-REMOVE: Name: .strtab (
# SYMBOL-REMOVE: Symbols [
## Case 6: adding a section.
# RUN: llvm-objcopy %t.o %t.add-section --add-section .bar=%s
# RUN: llvm-readobj --section-headers --symbols %t.add-section \
# RUN: | FileCheck %s --check-prefix=SECTION-ADD --implicit-check-not=.shstrtab
# SECTION-ADD: Sections [
# SECTION-ADD: Name: .foo (
# SECTION-ADD: Name: .strtab (
# SECTION-ADD: Name: .bar (
# SECTION-ADD: Symbols [
# SECTION-ADD: Name: foo (
## Case 7: adding a symbol.
# RUN: llvm-objcopy %t.o %t.add-symbol --add-symbol bar=0x1234
# RUN: llvm-readobj --section-headers --symbols %t.add-symbol \
# RUN: | FileCheck %s --check-prefix=SYMBOL-ADD --implicit-check-not=.shstrtab
# SYMBOL-ADD: Sections [
# SYMBOL-ADD: Name: .foo (
# SYMBOL-ADD: Name: .strtab (
# SYMBOL-ADD: Symbols [
# SYMBOL-ADD: Name: foo (
# SYMBOL-ADD: Name: bar (
## Case 8: removing all symbols.
# RUN: llvm-objcopy %t.o %t.strip-all --strip-all
# RUN: llvm-readobj --section-headers --symbols %t.strip-all \
# RUN: | FileCheck %s --check-prefix=STRIP-ALL --implicit-check-not=.shstrtab
# STRIP-ALL: Sections [
# STRIP-ALL: Name: .foo (
# STRIP-ALL: Name: .strtab (
# STRIP-ALL: Symbols [
# STRIP-ALL-NEXT: ]
.section .foo,"a",@progbits
foo = 0x4321
+53 -41
View File
@@ -3,6 +3,11 @@
# RUN: llvm-readobj --file-headers --program-headers %t2 | FileCheck %s
# RUN: od -t x1 -j 4096 %t2 | FileCheck %s --check-prefix=DATA
## Sanity check the DATA-NOT line by showing that "fe ed fa ce" appears
## if --strip-sections is not specified.
# RUN: llvm-objcopy %t %t3
# RUN: od -t x1 -j 4096 %t3 | FileCheck %s --check-prefix=VALIDATE
!ELF
FileHeader:
Class: ELFCLASS64
@@ -19,6 +24,10 @@ Sections:
Type: SHT_PROGBITS
Flags: [ ]
Content: "CAFEBABE"
- Name: .non_alloc_not_in_segment
Type: SHT_PROGBITS
Flags: [ ]
Content: "FEEDFACE"
ProgramHeaders:
- Type: PT_LOAD
Flags: [ PF_X, PF_R ]
@@ -26,46 +35,49 @@ ProgramHeaders:
- Section: .text
- Section: .non_alloc_in_segment
#DATA: 0010000 de ad be ef ca fe ba be
# DATA: 0010000 de ad be ef ca fe ba be
# DATA-NOT: fe ed fa ce
#CHECK: ElfHeader {
#CHECK-NEXT: Ident {
#CHECK-NEXT: Magic: (7F 45 4C 46)
#CHECK-NEXT: Class: 64-bit (0x2)
#CHECK-NEXT: DataEncoding: LittleEndian (0x1)
#CHECK-NEXT: FileVersion: 1
#CHECK-NEXT: OS/ABI: SystemV (0x0)
#CHECK-NEXT: ABIVersion: 0
#CHECK-NEXT: Unused: (00 00 00 00 00 00 00)
#CHECK-NEXT: }
#CHECK-NEXT: Type: Executable (0x2)
#CHECK-NEXT: Machine: EM_X86_64 (0x3E)
#CHECK-NEXT: Version: 1
#CHECK-NEXT: Entry: 0x0
#CHECK-NEXT: ProgramHeaderOffset: 0x40
#CHECK-NEXT: SectionHeaderOffset: 0x0
#CHECK-NEXT: Flags [ (0x0)
#CHECK-NEXT: ]
#CHECK-NEXT: HeaderSize: 64
#CHECK-NEXT: ProgramHeaderEntrySize: 56
#CHECK-NEXT: ProgramHeaderCount: 1
#CHECK-NEXT: SectionHeaderEntrySize: 0
#CHECK-NEXT: SectionHeaderCount: 0
#CHECK-NEXT: StringTableSectionIndex: 0
#CHECK-NEXT: }
# VALIDATE: 0010000 de ad be ef ca fe ba be fe ed fa ce
#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: 8
#CHECK-NEXT: MemSize: 8
#CHECK-NEXT: Flags [ (0x5)
#CHECK-NEXT: PF_R (0x4)
#CHECK-NEXT: PF_X (0x1)
#CHECK-NEXT: ]
#CHECK-NEXT: Alignment: 4096
#CHECK-NEXT: }
#CHECK-NEXT:]
# CHECK: ElfHeader {
# CHECK-NEXT: Ident {
# CHECK-NEXT: Magic: (7F 45 4C 46)
# CHECK-NEXT: Class: 64-bit (0x2)
# CHECK-NEXT: DataEncoding: LittleEndian (0x1)
# CHECK-NEXT: FileVersion: 1
# CHECK-NEXT: OS/ABI: SystemV (0x0)
# CHECK-NEXT: ABIVersion: 0
# CHECK-NEXT: Unused: (00 00 00 00 00 00 00)
# CHECK-NEXT: }
# CHECK-NEXT: Type: Executable (0x2)
# CHECK-NEXT: Machine: EM_X86_64 (0x3E)
# CHECK-NEXT: Version: 1
# CHECK-NEXT: Entry: 0x0
# CHECK-NEXT: ProgramHeaderOffset: 0x40
# CHECK-NEXT: SectionHeaderOffset: 0x0
# CHECK-NEXT: Flags [ (0x0)
# CHECK-NEXT: ]
# CHECK-NEXT: HeaderSize: 64
# CHECK-NEXT: ProgramHeaderEntrySize: 56
# CHECK-NEXT: ProgramHeaderCount: 1
# CHECK-NEXT: SectionHeaderEntrySize: 0
# CHECK-NEXT: SectionHeaderCount: 0
# CHECK-NEXT: StringTableSectionIndex: 0
# 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: 8
# CHECK-NEXT: MemSize: 8
# CHECK-NEXT: Flags [ (0x5)
# CHECK-NEXT: PF_R (0x4)
# CHECK-NEXT: PF_X (0x1)
# CHECK-NEXT: ]
# CHECK-NEXT: Alignment: 4096
# CHECK-NEXT: }
# CHECK-NEXT: ]
@@ -0,0 +1,82 @@
## This test shows that when symbol/section names are optimized in the string
## table to share the same entry, due to tail merging, llvm-objcopy operations
## function correctly without corrupting the names of unchanged sections/symbols.
# RUN: yaml2obj %s -o %t.o
## Sanity check that the strings have been pooled.
# RUN: llvm-readobj %t.o --string-dump .strtab --string-dump .shstrtab \
# RUN: | FileCheck %s --check-prefix=VALIDATE --implicit-check-not=bar --implicit-check-not=.blag
# VALIDATE: String dump of section '.strtab':
# VALIDATE: bazfoobar
# VALIDATE: String dump of section '.shstrtab':
# VALIDATE: .blam.blah.blag
## Case 1: Basic copy.
# RUN: llvm-objcopy %t.o %t.copy
# RUN: llvm-readobj --section-headers --symbols %t.copy | FileCheck %s --check-prefix=COPY
# COPY: Sections [
# COPY: Name: .blam.blah.blag (
# COPY: Name: .blah.blag (
# COPY: Name: .blag (
# COPY: Symbols [
# COPY: Name: bar (
# COPY: Name: foobar (
# COPY: Name: bazfoobar (
## Case 2: Rename section.
# RUN: llvm-objcopy %t.o %t.rename-section --rename-section .blah.blag=.blob.blab
# RUN: llvm-readobj --section-headers %t.rename-section \
# RUN: | FileCheck %s --check-prefix=RENAME-SECTION
# RENAME-SECTION: Sections [
# RENAME-SECTION: Name: .blam.blah.blag (
# RENAME-SECTION: Name: .blob.blab (
# RENAME-SECTION: Name: .blag (
## Case 3: Rename symbol.
# RUN: llvm-objcopy %t.o %t.rename-symbol --redefine-sym foobar=raboof
# RUN: llvm-readobj --symbols %t.rename-symbol \
# RUN: | FileCheck %s --check-prefix=RENAME-SYMBOL
# RENAME-SYMBOL: Symbols [
# RENAME-SYMBOL: Name: bar (
# RENAME-SYMBOL: Name: raboof (
# RENAME-SYMBOL: Name: bazfoobar (
## Case 4: Remove section.
# RUN: llvm-objcopy %t.o %t.remove-section -R .blah.blag
# RUN: llvm-readobj --section-headers %t.remove-section \
# RUN: | FileCheck %s --check-prefix=REMOVE-SECTION --implicit-check-not .blah.blag
# REMOVE-SECTION: Sections [
# REMOVE-SECTION: Name: .blam.blah.blag (
# REMOVE-SECTION: Name: .blag (
## Case 5: Remove symbol.
# RUN: llvm-objcopy %t.o %t.remove-symbol -N foobar
# RUN: llvm-readobj --symbols %t.remove-symbol \
# RUN: | FileCheck %s --check-prefix=REMOVE-SYMBOL --implicit-check-not foobar
# REMOVE-SYMBOL: Symbols [
# REMOVE-SYMBOL: Name: bar (
# REMOVE-SYMBOL: Name: bazfoobar (
--- !ELF
FileHeader:
Class: ELFCLASS64
Data: ELFDATA2LSB
Type: ET_EXEC
Machine: EM_X86_64
Sections:
- Name: .blam.blah.blag
Type: SHT_PROGBITS
- Name: .blah.blag
Type: SHT_PROGBITS
- Name: .blag
Type: SHT_PROGBITS
Symbols:
- Name: bar
- Name: foobar
- Name: bazfoobar