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,20 @@ +# 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 +# RUN: llvm-symbolizer --obj=%t 0 4 0xc + + .global foo +foo: + .word 32 + nop + nop + .word 42 + +# CHECK: foo +# CHECK-NEXT: ??:0:0 +# CHECK-EMPTY: +# CHECK: foo +# CHECK-NEXT: ??:0:0 +# CHECK-EMPTY: +# CHECK: foo +# CHECK-NEXT: ??:0:0 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,27 @@ +# 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/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 --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;