[llvm-objcopy][COFF] Implement --redefine-sym and --redefine-syms
authorFangrui Song <maskray@google.com>
Sat, 9 Nov 2019 00:19:33 +0000 (16:19 -0800)
committerFangrui Song <maskray@google.com>
Tue, 12 Nov 2019 19:28:00 +0000 (11:28 -0800)
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

llvm/docs/CommandGuide/llvm-objcopy.rst
llvm/test/tools/llvm-objcopy/COFF/redefine-symbol.test [new file with mode: 0644]
llvm/test/tools/llvm-objcopy/ELF/redefine-symbol.test
llvm/test/tools/llvm-objcopy/redefine-symbols.test [new file with mode: 0644]
llvm/tools/llvm-objcopy/COFF/COFFObjcopy.cpp

index e9b58d2..9d7cab9 100644 (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
diff --git a/llvm/test/tools/llvm-objcopy/COFF/redefine-symbol.test b/llvm/test/tools/llvm-objcopy/COFF/redefine-symbol.test
new file mode 100644 (file)
index 0000000..263d6f3
--- /dev/null
@@ -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
+...
index e6d52f8..f5927bd 100644 (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
diff --git a/llvm/test/tools/llvm-objcopy/redefine-symbols.test b/llvm/test/tools/llvm-objcopy/redefine-symbols.test
new file mode 100644 (file)
index 0000000..837294d
--- /dev/null
@@ -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
index 2a8d816..b172fae 100644 (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,