[llvm] f3471dc - [llvm-objcopy] Preserve ARM and AArch64 mapping symbols

Igor Kudrin via llvm-commits llvm-commits at lists.llvm.org
Tue Jan 18 23:43:26 PST 2022


Author: Igor Kudrin
Date: 2022-01-19T14:41:21+07:00
New Revision: f3471dc517696b3dcd9a3f3c2c0642dfff499776

URL: https://github.com/llvm/llvm-project/commit/f3471dc517696b3dcd9a3f3c2c0642dfff499776
DIFF: https://github.com/llvm/llvm-project/commit/f3471dc517696b3dcd9a3f3c2c0642dfff499776.diff

LOG: [llvm-objcopy] Preserve ARM and AArch64 mapping symbols

Mapping symbols are required by ARM/AArch64 ELF ABI. They help to
disassemble files correctly and are also used in linkers. Nonetheless,
for executable files, the symbols can be stripped to better resemble
the behavior of GNU's objcopy.

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

Added: 
    llvm/test/tools/llvm-objcopy/ELF/strip-unneeded-aarch64.test
    llvm/test/tools/llvm-objcopy/ELF/strip-unneeded-arm.test

Modified: 
    llvm/tools/llvm-objcopy/ELF/ELFObjcopy.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/test/tools/llvm-objcopy/ELF/strip-unneeded-aarch64.test b/llvm/test/tools/llvm-objcopy/ELF/strip-unneeded-aarch64.test
new file mode 100644
index 0000000000000..4f8c6215cf5fd
--- /dev/null
+++ b/llvm/test/tools/llvm-objcopy/ELF/strip-unneeded-aarch64.test
@@ -0,0 +1,53 @@
+## Check that llvm-objcopy preserves AArch64 mapping symbols for relocatable files.
+# RUN: yaml2obj %s -o %t.o -DTYPE=REL
+# RUN: llvm-objcopy --strip-unneeded %t.o %t1.o
+# RUN: llvm-nm -j --special-syms %t1.o | FileCheck %s --match-full-lines
+# RUN: llvm-objcopy --discard-all %t.o %t2.o
+# RUN: llvm-nm -j --special-syms %t2.o | FileCheck %s --match-full-lines
+
+# CHECK:      $d
+# CHECK-NEXT: $d.d
+# CHECK-NEXT: $x
+# CHECK-NEXT: $x.x
+
+## A mapping symbol can be deleted if specified explicitly.
+# RUN: llvm-objcopy -w -N '$d*' %t.o %t3.o
+# RUN: llvm-nm --special-syms %t3.o | FileCheck /dev/null --implicit-check-not='$d'
+
+## Mapping symbols are not preserved for executable files
+# RUN: yaml2obj %s -o %t.exec -DTYPE=EXEC
+# RUN: llvm-objcopy --strip-unneeded %t.exec %t1.exec
+# RUN: llvm-nm --special-syms %t1.exec | count 0
+
+# RUN: yaml2obj %s -o %t.so -DTYPE=DYN
+# RUN: llvm-objcopy --strip-unneeded %t.so %t1.so
+# RUN: llvm-nm --special-syms %t1.so | count 0
+
+!ELF
+FileHeader:
+  Class:    ELFCLASS64
+  Data:     ELFDATA2LSB
+  Type:     ET_[[TYPE]]
+  Machine:  EM_AARCH64
+Sections:
+  - Name: .text
+    Type: SHT_PROGBITS
+Symbols:
+  - Name:     $a
+    Section:  .text
+  - Name:     $d
+    Section:  .text
+  - Name:     $dd
+    Section:  .text
+  - Name:     $d.d
+    Section:  .text
+  - Name:     $m
+    Section:  .text
+  - Name:     $t.t
+    Section:  .text
+  - Name:     $x
+    Section:  .text
+  - Name:     $xx
+    Section:  .text
+  - Name:     $x.x
+    Section:  .text

diff  --git a/llvm/test/tools/llvm-objcopy/ELF/strip-unneeded-arm.test b/llvm/test/tools/llvm-objcopy/ELF/strip-unneeded-arm.test
new file mode 100644
index 0000000000000..c6160cf8aff6c
--- /dev/null
+++ b/llvm/test/tools/llvm-objcopy/ELF/strip-unneeded-arm.test
@@ -0,0 +1,60 @@
+## Check that llvm-objcopy preserves ARM mapping symbols for relocatable files.
+# RUN: yaml2obj %s -o %t.o -DTYPE=REL
+# RUN: llvm-objcopy --strip-unneeded %t.o %t1.o
+# RUN: llvm-nm -j --special-syms %t1.o | FileCheck %s --match-full-lines
+# RUN: llvm-objcopy --discard-all %t.o %t2.o
+# RUN: llvm-nm -j --special-syms %t2.o | FileCheck %s --match-full-lines
+
+# CHECK:      $a
+# CHECK-NEXT: $a.a
+# CHECK-NEXT: $d
+# CHECK-NEXT: $d.d
+# CHECK-NEXT: $t
+# CHECK-NEXT: $t.t
+# CHECK-NOT:  $x
+
+## A mapping symbol can be deleted if specified explicitly.
+# RUN: llvm-objcopy -w -N '$d*' %t.o %t3.o
+# RUN: llvm-nm --special-syms %t3.o | FileCheck /dev/null --implicit-check-not='$d'
+
+## Mapping symbols are not preserved for executable files
+# RUN: yaml2obj %s -o %t.exec -DTYPE=EXEC
+# RUN: llvm-objcopy --strip-unneeded %t.exec %t1.exec
+# RUN: llvm-nm --special-syms %t1.exec | count 0
+
+# RUN: yaml2obj %s -o %t.so -DTYPE=DYN
+# RUN: llvm-objcopy --strip-unneeded %t.so %t1.so
+# RUN: llvm-nm --special-syms %t1.so | count 0
+
+!ELF
+FileHeader:
+  Class:    ELFCLASS32
+  Data:     ELFDATA2LSB
+  Type:     ET_[[TYPE]]
+  Machine:  EM_ARM
+Sections:
+  - Name: .text
+    Type: SHT_PROGBITS
+Symbols:
+  - Name:     $a
+    Section:  .text
+  - Name:     $aa
+    Section:  .text
+  - Name:     $a.a
+    Section:  .text
+  - Name:     $d
+    Section:  .text
+  - Name:     $dd
+    Section:  .text
+  - Name:     $d.d
+    Section:  .text
+  - Name:     $m
+    Section:  .text
+  - Name:     $t
+    Section:  .text
+  - Name:     $tt
+    Section:  .text
+  - Name:     $t.t
+    Section:  .text
+  - Name:     $x
+    Section:  .text

diff  --git a/llvm/tools/llvm-objcopy/ELF/ELFObjcopy.cpp b/llvm/tools/llvm-objcopy/ELF/ELFObjcopy.cpp
index 16de84a961b5c..f8521fa0d5b70 100644
--- a/llvm/tools/llvm-objcopy/ELF/ELFObjcopy.cpp
+++ b/llvm/tools/llvm-objcopy/ELF/ELFObjcopy.cpp
@@ -227,6 +227,41 @@ static Error replaceDebugSections(
   return Obj.replaceSections(FromTo);
 }
 
+static bool isAArch64MappingSymbol(const Symbol &Sym) {
+  if (Sym.Binding != STB_LOCAL || Sym.Type != STT_NOTYPE ||
+      Sym.getShndx() == SHN_UNDEF)
+    return false;
+  StringRef Name = Sym.Name;
+  if (!Name.consume_front("$x") && !Name.consume_front("$d"))
+    return false;
+  return Name.empty() || Name.startswith(".");
+}
+
+static bool isArmMappingSymbol(const Symbol &Sym) {
+  if (Sym.Binding != STB_LOCAL || Sym.Type != STT_NOTYPE ||
+      Sym.getShndx() == SHN_UNDEF)
+    return false;
+  StringRef Name = Sym.Name;
+  if (!Name.consume_front("$a") && !Name.consume_front("$d") &&
+      !Name.consume_front("$t"))
+    return false;
+  return Name.empty() || Name.startswith(".");
+}
+
+// Check if the symbol should be preserved because it is required by ABI.
+static bool isRequiredByABISymbol(const Object &Obj, const Symbol &Sym) {
+  switch (Obj.Machine) {
+  case EM_AARCH64:
+    // Mapping symbols should be preserved for a relocatable object file.
+    return Obj.isRelocatable() && isAArch64MappingSymbol(Sym);
+  case EM_ARM:
+    // Mapping symbols should be preserved for a relocatable object file.
+    return Obj.isRelocatable() && isArmMappingSymbol(Sym);
+  default:
+    return false;
+  }
+}
+
 static bool isUnneededSymbol(const Symbol &Sym) {
   return !Sym.Referenced &&
          (Sym.Binding == STB_LOCAL || Sym.getShndx() == SHN_UNDEF) &&
@@ -297,20 +332,23 @@ static Error updateAndRemoveSymbols(const CommonConfig &Config,
         (ELFConfig.KeepFileSymbols && Sym.Type == STT_FILE))
       return false;
 
-    if ((Config.DiscardMode == DiscardType::All ||
-         (Config.DiscardMode == DiscardType::Locals &&
-          StringRef(Sym.Name).startswith(".L"))) &&
-        Sym.Binding == STB_LOCAL && Sym.getShndx() != SHN_UNDEF &&
-        Sym.Type != STT_FILE && Sym.Type != STT_SECTION)
+    if (Config.SymbolsToRemove.matches(Sym.Name))
       return true;
 
     if (Config.StripAll || Config.StripAllGNU)
       return true;
 
+    if (isRequiredByABISymbol(Obj, Sym))
+      return false;
+
     if (Config.StripDebug && Sym.Type == STT_FILE)
       return true;
 
-    if (Config.SymbolsToRemove.matches(Sym.Name))
+    if ((Config.DiscardMode == DiscardType::All ||
+         (Config.DiscardMode == DiscardType::Locals &&
+          StringRef(Sym.Name).startswith(".L"))) &&
+        Sym.Binding == STB_LOCAL && Sym.getShndx() != SHN_UNDEF &&
+        Sym.Type != STT_FILE && Sym.Type != STT_SECTION)
       return true;
 
     if ((Config.StripUnneeded ||


        


More information about the llvm-commits mailing list