[llvm-objcopy][COFF] Implement --redefine-sym and --redefine-syms

The parsing error tests in ELF/redefine-symbols.test are not specific to ELF.
Move them to redefine-symbols.test.
Add COFF/redefine-symbols.test for COFF specific tests.

Also fix the documentation regarding --redefine-syms: the old and new
names are separated by whitespace, not an equals sign.

Reviewed By: mstorsjo

Differential Revision: https://reviews.llvm.org/D70036
This commit is contained in:
Fangrui Song 2019-11-08 16:19:33 -08:00
parent 96915495f9
commit 7af6025bd1
5 changed files with 128 additions and 32 deletions

View File

@ -84,6 +84,19 @@ multiple file formats.
For MachO objects, ``<section>`` must be formatted as
``<segment name>,<section name>``.
.. option:: --redefine-sym <old>=<new>
Rename symbols called ``<old>`` to ``<new>`` in the output. Can be specified
multiple times to rename multiple symbols.
.. option:: --redefine-syms <filename>
Rename symbols in the output as described in the file ``<filename>``. In the
file, each line represents a single symbol to rename, with the old name and new
name separated by whitespace. Leading and trailing whitespace is ignored, as is
anything following a '#'. Can be specified multiple times to read names from
multiple files.
.. option:: --regex
If specified, symbol and section names specified by other switches are treated
@ -378,19 +391,6 @@ them.
Preserve access and modification timestamps in the output.
.. option:: --redefine-sym <old>=<new>
Rename symbols called ``<old>`` to ``<new>`` in the output. Can be specified
multiple times to rename multiple symbols.
.. option:: --redefine-syms <filename>
Rename symbols in the output as described in the file ``<filename>``. In the
file, each line represents a single symbol to rename, with the old name and new
name separated by an equals sign. Leading and trailing whitespace is ignored,
as is anything following a '#'. Can be specified multiple times to read names
from multiple files.
.. option:: --rename-section <old>=<new>[,<flag>,...]
Rename sections called ``<old>`` to ``<new>`` in the output, and apply any

View File

@ -0,0 +1,69 @@
# RUN: yaml2obj %s -o %t
## A non-existent symbol does not error.
# RUN: llvm-objcopy --redefine-sym func=cnuf1234 --redefine-sym foo=ba --redefine-sym=notexist= %t %t2 2>&1 | count 0
# RUN: llvm-readobj --symbols %t2 | FileCheck %s
# RUN: echo 'func cnuf1234 #rename func' > %t.rename.txt
# RUN: echo ' foo ba ' >> %t.rename.txt
# RUN: echo 'notexist notexist' >> %t.rename.txt
# RUN: llvm-objcopy --redefine-syms %t.rename.txt %t %t3 2>&1 | count 0
# RUN: cmp %t2 %t3
# CHECK: Symbol {
# CHECK: Symbol {
# CHECK: Symbol {
# CHECK-NEXT: Name: cnuf1234
# CHECK-NEXT: Value: 0
# CHECK-NEXT: Section: .text (1)
# CHECK-NEXT: BaseType: Null (0x0)
# CHECK-NEXT: ComplexType: Function (0x2)
# CHECK-NEXT: StorageClass: External (0x2)
# CHECK-NEXT: AuxSymbolCount: 0
# CHECK-NEXT: }
# CHECK-NEXT: Symbol {
# CHECK-NEXT: Name: ba
# CHECK-NEXT: Value: 0
# CHECK-NEXT: Section: .rdata (2)
# CHECK-NEXT: BaseType: Null (0x0)
# CHECK-NEXT: ComplexType: Null (0x0)
# CHECK-NEXT: StorageClass: External (0x2)
# CHECK-NEXT: AuxSymbolCount: 0
# CHECK-NEXT: }
--- !COFF
header:
Machine: IMAGE_FILE_MACHINE_AMD64
Characteristics: [ ]
sections:
- Name: .text
Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
- Name: .rdata
Characteristics: [ ]
Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ ]
symbols:
- Name: .text
Value: 0
SectionNumber: 1
SimpleType: IMAGE_SYM_TYPE_NULL
ComplexType: IMAGE_SYM_DTYPE_NULL
StorageClass: IMAGE_SYM_CLASS_STATIC
- Name: .rdata
Value: 0
SectionNumber: 2
SimpleType: IMAGE_SYM_TYPE_NULL
ComplexType: IMAGE_SYM_DTYPE_NULL
StorageClass: IMAGE_SYM_CLASS_STATIC
- Name: func
Value: 0
SectionNumber: 1
SimpleType: IMAGE_SYM_TYPE_NULL
ComplexType: IMAGE_SYM_DTYPE_FUNCTION
StorageClass: IMAGE_SYM_CLASS_EXTERNAL
- Name: foo
Value: 0
SectionNumber: 2
SimpleType: IMAGE_SYM_TYPE_NULL
ComplexType: IMAGE_SYM_DTYPE_NULL
StorageClass: IMAGE_SYM_CLASS_EXTERNAL
...

View File

@ -1,16 +1,10 @@
# RUN: yaml2obj %s > %t
# RUN: llvm-objcopy --redefine-sym foo=oof --redefine-sym empty= %t %t2
# RUN: llvm-readobj --symbols %t2 | FileCheck %s
# RUN: not llvm-objcopy --redefine-sym barbar %t %t2 2>&1 | FileCheck %s --check-prefix=BAD-FORMAT
# RUN: not llvm-objcopy --redefine-sym foo=f1 --redefine-sym foo=f2 %t %t2 2>&1 | FileCheck %s --check-prefix=MULTIPLE-REDEFINITION
# RUN: echo " foo oof #rename foo " > %t.rename.txt
# RUN: echo "empty" >> %t.rename.txt
# RUN: not llvm-objcopy --redefine-syms %t.rename.txt %t %t3 2>&1 | FileCheck %s --check-prefix=MISSING-SYM-NAME
# RUN: not llvm-objcopy --redefine-syms %t.rename-none.txt %t %t-none 2>&1 | FileCheck %s --check-prefix=NO-FILE
# RUN: echo " bar rab #rename bar " > %t.rename2.txt
# RUN: echo " foo oof #rename foo " > %t.rename3.txt
# RUN: echo " empty ytpme #rename empty " >> %t.rename3.txt
# RUN: llvm-objcopy --redefine-syms %t.rename2.txt --redefine-syms %t.rename3.txt %t %t4
# RUN: echo " bar rab #rename bar " > %t.rename1.txt
# RUN: echo "foo oof #rename foo " > %t.rename2.txt
# RUN: echo " empty ytpme #rename empty " >> %t.rename2.txt
# RUN: llvm-objcopy --redefine-syms %t.rename1.txt --redefine-syms %t.rename2.txt %t %t4
# RUN: llvm-readobj --symbols %t4 | FileCheck %s --check-prefix=MULTIPLE-FILES
!ELF
@ -88,11 +82,6 @@ Symbols:
#CHECK-NEXT: Section: .text
#CHECK-NEXT: }
#BAD-FORMAT: bad format for --redefine-sym
#MULTIPLE-REDEFINITION: multiple redefinition of symbol 'foo'
#MISSING-SYM-NAME: error: {{.*}}.rename.txt:2: missing new symbol name
#NO-FILE: error: '{{.*}}.rename-none.txt': {{[Nn]}}o such file or directory
#MULTIPLE-FILES: Name: oof
#MULTIPLE-FILES-NEXT: Value: 0x1004
#MULTIPLE-FILES: Name: rab

View File

@ -0,0 +1,33 @@
## Test common parsing errors general to all supported binary formats.
# RUN: yaml2obj %s > %t
# RUN: not llvm-objcopy --redefine-sym bar %t /dev/null 2>&1 | FileCheck %s --check-prefix=BAD-FORMAT
# BAD-FORMAT: bad format for --redefine-sym
# RUN: not llvm-objcopy --redefine-sym foo=f1 --redefine-sym foo=f2 %t /dev/null 2>&1 | FileCheck %s --check-prefix=MULTIPLE-REDEFINITION
# MULTIPLE-REDEFINITION: multiple redefinition of symbol 'foo'
# RUN: echo ' foo oof #rename foo ' > %t.rename.txt
# RUN: echo 'bar' >> %t.rename.txt
# RUN: not llvm-objcopy --redefine-syms %t.rename.txt %t /dev/null 2>&1 | FileCheck %s --check-prefix=MISSING-SYM-NAME
# MISSING-SYM-NAME: error: {{.*}}.rename.txt:2: missing new symbol name
# RUN: not llvm-objcopy --redefine-syms %t.rename-none.txt %t /dev/null 2>&1 | FileCheck %s --check-prefix=NO-FILE
# NO-FILE: error: '{{.*}}.rename-none.txt': {{[Nn]}}o such file or directory
!ELF
FileHeader:
Class: ELFCLASS64
Data: ELFDATA2LSB
Type: ET_EXEC
Machine: EM_X86_64
Sections:
- Name: .text
Type: SHT_PROGBITS
Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
Symbols:
- Name: foo
Section: .text
- Name: bar
Section: .text

View File

@ -131,6 +131,12 @@ static Error handleArgs(const CopyConfig &Config, Object &Obj) {
if (Error E = Obj.markSymbols())
return E;
for (Symbol &Sym : Obj.getMutableSymbols()) {
auto I = Config.SymbolsToRename.find(Sym.Name);
if (I != Config.SymbolsToRename.end())
Sym.Name = I->getValue();
}
// Actually do removals of symbols.
Obj.removeSymbols([&](const Symbol &Sym) {
// For StripAll, all relocations have been stripped and we remove all
@ -200,10 +206,9 @@ static Error handleArgs(const CopyConfig &Config, Object &Obj) {
!Config.SymbolsToLocalize.empty() || !Config.SymbolsToWeaken.empty() ||
!Config.SymbolsToKeepGlobal.empty() || !Config.SectionsToRename.empty() ||
!Config.SetSectionAlignment.empty() || !Config.SetSectionFlags.empty() ||
!Config.SymbolsToRename.empty() || Config.ExtractDWO ||
Config.KeepFileSymbols || Config.LocalizeHidden || Config.PreserveDates ||
Config.StripDWO || Config.StripNonAlloc || Config.StripSections ||
Config.Weaken || Config.DecompressDebugSections ||
Config.ExtractDWO || Config.KeepFileSymbols || Config.LocalizeHidden ||
Config.PreserveDates || Config.StripDWO || Config.StripNonAlloc ||
Config.StripSections || Config.Weaken || Config.DecompressDebugSections ||
Config.DiscardMode == DiscardType::Locals ||
!Config.SymbolsToAdd.empty() || Config.EntryExpr) {
return createStringError(llvm::errc::invalid_argument,