diff --git a/llvm/include/llvm/Object/ELFObjectFile.h b/llvm/include/llvm/Object/ELFObjectFile.h --- a/llvm/include/llvm/Object/ELFObjectFile.h +++ b/llvm/include/llvm/Object/ELFObjectFile.h @@ -716,7 +716,16 @@ // TODO: Test this error. return SymbolsOrErr.takeError(); - if (EF.getHeader().e_machine == ELF::EM_ARM) { + if (EF.getHeader().e_machine == ELF::EM_AARCH64) { + if (Expected NameOrErr = getSymbolName(Sym)) { + StringRef Name = *NameOrErr; + if (Name.startswith("$d") || Name.startswith("$x")) + Result |= SymbolRef::SF_FormatSpecific; + } else { + // TODO: Actually report errors helpfully. + consumeError(NameOrErr.takeError()); + } + } else if (EF.getHeader().e_machine == ELF::EM_ARM) { if (Expected NameOrErr = getSymbolName(Sym)) { StringRef Name = *NameOrErr; if (Name.startswith("$d") || Name.startswith("$t") || diff --git a/llvm/test/DebugInfo/Symbolize/ELF/aarch64-mapping-symbol.s b/llvm/test/DebugInfo/Symbolize/ELF/aarch64-mapping-symbol.s new file mode 100644 --- /dev/null +++ b/llvm/test/DebugInfo/Symbolize/ELF/aarch64-mapping-symbol.s @@ -0,0 +1,31 @@ +# REQUIRES: aarch64-registered-target +## Ignore AArch64 mapping symbols (with a prefix of $d or $x). + +# RUN: llvm-mc -filetype=obj -triple=aarch64 %s -o %t + +## Verify that mapping symbols are actually present in the object at expected +## addresses. +# RUN: llvm-nm --special-syms %t | FileCheck %s -check-prefix MAPPING_SYM + +# MAPPING_SYM: 0000000000000000 t $d.0 +# MAPPING_SYM-NEXT: 000000000000000c t $d.2 +# MAPPING_SYM-NEXT: 0000000000000004 t $x.1 +# MAPPING_SYM-NEXT: 0000000000000000 T foo + +# RUN: llvm-symbolizer --obj=%t 0 4 0xc | FileCheck %s -check-prefix SYMBOL + +# SYMBOL: foo +# SYMBOL-NEXT: ??:0:0 +# SYMBOL-EMPTY: +# SYMBOL: foo +# SYMBOL-NEXT: ??:0:0 +# SYMBOL-EMPTY: +# SYMBOL: foo +# SYMBOL-NEXT: ??:0:0 + + .global foo +foo: + .word 32 + nop + nop + .word 42 diff --git a/llvm/test/DebugInfo/Symbolize/ELF/arm-mapping-symbol.s b/llvm/test/DebugInfo/Symbolize/ELF/arm-mapping-symbol.s --- a/llvm/test/DebugInfo/Symbolize/ELF/arm-mapping-symbol.s +++ b/llvm/test/DebugInfo/Symbolize/ELF/arm-mapping-symbol.s @@ -2,15 +2,32 @@ ## Ignore ARM mapping symbols (with a prefix of $a, $d or $t). # RUN: llvm-mc -filetype=obj -triple=armv7-none-linux %s -o %t -# RUN: llvm-symbolizer --obj=%t 4 8 | FileCheck %s + +## Verify that mapping symbols are actually present in the object at expected +## addresses. +# RUN: llvm-nm --special-syms %t | FileCheck %s -check-prefix MAPPING_A + +# MAPPING_A: 00000004 t $a.1 +# MAPPING_A-NEXT: 00000000 t $d.0 +# MAPPING_A-NEXT: 00000008 t $d.2 +# MAPPING_A-NEXT: 00000000 T foo + # RUN: llvm-mc -filetype=obj -triple=thumbv7-none-linux %s -o %tthumb -# RUN: llvm-symbolizer --obj=%tthumb 4 8 | FileCheck %s +# RUN: llvm-nm --special-syms %tthumb | FileCheck %s -check-prefix MAPPING_T + +# MAPPING_T: 00000000 t $d.0 +# MAPPING_T-NEXT: 00000006 t $d.2 +# MAPPING_T-NEXT: 00000004 t $t.1 +# MAPPING_T-NEXT: 00000000 T foo + +# RUN: llvm-symbolizer --obj=%t 4 8 | FileCheck %s -check-prefix SYMBOL +# RUN: llvm-symbolizer --obj=%tthumb 4 8 | FileCheck %s -check-prefix SYMBOL -# CHECK: foo -# CHECK-NEXT: ??:0:0 -# CHECK-EMPTY: -# CHECK-NEXT: foo -# CHECK-NEXT: ??:0:0 +# SYMBOL: foo +# SYMBOL-NEXT: ??:0:0 +# SYMBOL-EMPTY: +# SYMBOL-NEXT: foo +# SYMBOL-NEXT: ??:0:0 .globl foo foo: diff --git a/llvm/test/tools/llvm-nm/ARM/special-syms.test b/llvm/test/tools/llvm-nm/ARM/special-syms.test new file mode 100644 --- /dev/null +++ b/llvm/test/tools/llvm-nm/ARM/special-syms.test @@ -0,0 +1,30 @@ +## Test --special-syms flag for ARM mapping symbols used to mark transitions +## between ARM code, THUMB code and data ($a, $t, $t). +# +# RUN: yaml2obj %s -o %t +# RUN: llvm-nm %t | count 0 +# RUN: llvm-nm --special-syms %t | FileCheck %s + +!ELF +FileHeader: + Class: ELFCLASS32 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_ARM + Flags: [ EF_ARM_EABI_VER5 ] +Sections: + - Name: .text + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC, SHF_EXECINSTR ] + AddressAlign: 0x4 +Symbols: + - Name: '$d.0' + Section: .text + - Name: '$a.1' + Section: .text + - Name: '$t.1' + Section: .text + +# CHECK: 00000000 t $a.1 +# CHECK: 00000000 t $d.0 +# CHECK: 00000000 t $t.1 diff --git a/llvm/test/tools/llvm-nm/debug-syms.test b/llvm/test/tools/llvm-nm/debug-syms.test --- a/llvm/test/tools/llvm-nm/debug-syms.test +++ b/llvm/test/tools/llvm-nm/debug-syms.test @@ -1,6 +1,6 @@ # RUN: yaml2obj %s -o %t.o -# RUN: llvm-nm --special-syms --debug-syms %t.o | FileCheck %s --implicit-check-not {{.}} --check-prefix SYMBOL -# RUN: llvm-nm --special-syms -a %t.o | FileCheck %s --implicit-check-not {{.}} --check-prefix SYMBOL +# RUN: llvm-nm --debug-syms %t.o | FileCheck %s --implicit-check-not {{.}} --check-prefix SYMBOL +# RUN: llvm-nm -a %t.o | FileCheck %s --implicit-check-not {{.}} --check-prefix SYMBOL # SYMBOL: 0000000000000000 n $a # SYMBOL-NEXT: 0000000000000000 n $d diff --git a/llvm/tools/llvm-nm/llvm-nm.cpp b/llvm/tools/llvm-nm/llvm-nm.cpp --- a/llvm/tools/llvm-nm/llvm-nm.cpp +++ b/llvm/tools/llvm-nm/llvm-nm.cpp @@ -742,16 +742,6 @@ } } -static bool isSpecialSym(SymbolicFile &Obj, StringRef Name) { - auto *ELFObj = dyn_cast(&Obj); - if (!ELFObj) - return false; - uint16_t EMachine = ELFObj->getEMachine(); - if (EMachine != ELF::EM_ARM && EMachine != ELF::EM_AARCH64) - return false; - return !Name.empty() && Name[0] == '$'; -} - static void sortAndPrintSymbolList(SymbolicFile &Obj, bool printName, StringRef ArchiveName, StringRef ArchitectureName) { @@ -840,9 +830,10 @@ bool Undefined = SymFlags & SymbolRef::SF_Undefined; bool Global = SymFlags & SymbolRef::SF_Global; bool Weak = SymFlags & SymbolRef::SF_Weak; + bool FormatSpecific = SymFlags & SymbolRef::SF_FormatSpecific; if ((!Undefined && UndefinedOnly) || (Undefined && DefinedOnly) || (!Global && ExternalOnly) || (Weak && NoWeakSymbols) || - (!SpecialSyms && isSpecialSym(Obj, Name))) + (FormatSpecific && !(SpecialSyms || DebugSyms))) continue; if (PrintFileName) writeFileName(outs(), ArchiveName, ArchitectureName); @@ -1812,7 +1803,14 @@ error(SymFlagsOrErr.takeError(), Obj.getFileName()); return; } - if (!DebugSyms && (*SymFlagsOrErr & SymbolRef::SF_FormatSpecific)) + + // Don't drop format specifc symbols for ARM and AArch64 ELF targets, they + // are used to repesent mapping symbols and needed to honor the + // --special-syms option. + auto *ELFObj = dyn_cast(&Obj); + if ((!ELFObj || (ELFObj->getEMachine() != ELF::EM_ARM && + ELFObj->getEMachine() != ELF::EM_AARCH64)) && + !DebugSyms && (*SymFlagsOrErr & SymbolRef::SF_FormatSpecific)) continue; if (WithoutAliases && (*SymFlagsOrErr & SymbolRef::SF_Indirect)) continue;