diff options
Diffstat (limited to 'llvm/tools/llvm-nm/llvm-nm.cpp')
-rw-r--r-- | llvm/tools/llvm-nm/llvm-nm.cpp | 156 |
1 files changed, 112 insertions, 44 deletions
diff --git a/llvm/tools/llvm-nm/llvm-nm.cpp b/llvm/tools/llvm-nm/llvm-nm.cpp index 107d62b1f2b9..ecd1e21e15bf 100644 --- a/llvm/tools/llvm-nm/llvm-nm.cpp +++ b/llvm/tools/llvm-nm/llvm-nm.cpp @@ -28,6 +28,8 @@ #include "llvm/Object/MachO.h" #include "llvm/Object/MachOUniversal.h" #include "llvm/Object/ObjectFile.h" +#include "llvm/Object/TapiFile.h" +#include "llvm/Object/TapiUniversal.h" #include "llvm/Object/Wasm.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/FileSystem.h" @@ -180,8 +182,10 @@ cl::opt<bool> JustSymbolName("just-symbol-name", cl::alias JustSymbolNames("j", cl::desc("Alias for --just-symbol-name"), cl::aliasopt(JustSymbolName), cl::Grouping); -cl::opt<bool> SpecialSyms("special-syms", - cl::desc("No-op. Used for GNU compatibility only")); +cl::opt<bool> + SpecialSyms("special-syms", + cl::desc("Do not filter special symbols from the output"), + cl::cat(NMCat)); cl::list<std::string> SegSect("s", cl::multi_val(2), cl::ZeroOrMore, cl::value_desc("segment section"), cl::Hidden, @@ -210,6 +214,11 @@ cl::opt<bool> NoLLVMBitcode("no-llvm-bc", cl::desc("Disable LLVM bitcode reader"), cl::cat(NMCat)); +cl::opt<bool> AddInlinedInfo("add-inlinedinfo", + cl::desc("Add symbols from the inlined libraries, " + "TBD(Mach-O) only"), + cl::cat(NMCat)); + cl::extrahelp HelpResponse("\nPass @FILE as argument to read options from FILE.\n"); bool PrintAddress = true; @@ -306,13 +315,17 @@ struct NMSymbol { static bool compareSymbolAddress(const NMSymbol &A, const NMSymbol &B) { bool ADefined; + // Symbol flags have been checked in the caller. + uint32_t AFlags = cantFail(A.Sym.getFlags()); if (A.Sym.getRawDataRefImpl().p) - ADefined = !(A.Sym.getFlags() & SymbolRef::SF_Undefined); + ADefined = !(AFlags & SymbolRef::SF_Undefined); else ADefined = A.TypeChar != 'U'; bool BDefined; + // Symbol flags have been checked in the caller. + uint32_t BFlags = cantFail(B.Sym.getFlags()); if (B.Sym.getRawDataRefImpl().p) - BDefined = !(B.Sym.getFlags() & SymbolRef::SF_Undefined); + BDefined = !(BFlags & SymbolRef::SF_Undefined); else BDefined = B.TypeChar != 'U'; return std::make_tuple(ADefined, A.Address, A.Name, A.Size) < @@ -336,6 +349,8 @@ static char isSymbolList64Bit(SymbolicFile &Obj) { return false; if (isa<WasmObjectFile>(Obj)) return false; + if (TapiFile *Tapi = dyn_cast<TapiFile>(&Obj)) + return Tapi->is64Bit(); if (MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(&Obj)) return MachO->is64Bit(); return cast<ELFObjectFileBase>(Obj).getBytesInAddress() == 8; @@ -366,7 +381,7 @@ static void darwinPrintSymbol(SymbolicFile &Obj, const NMSymbol &S, uint64_t NValue = 0; MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(&Obj); if (Obj.isIR()) { - uint32_t SymFlags = S.Sym.getFlags(); + uint32_t SymFlags = cantFail(S.Sym.getFlags()); if (SymFlags & SymbolRef::SF_Global) NType |= MachO::N_EXT; if (SymFlags & SymbolRef::SF_Hidden) @@ -707,9 +722,32 @@ static bool symbolIsDefined(const NMSymbol &Sym) { return Sym.TypeChar != 'U' && Sym.TypeChar != 'w' && Sym.TypeChar != 'v'; } +static void writeFileName(raw_ostream &S, StringRef ArchiveName, + StringRef ArchitectureName) { + if (!ArchitectureName.empty()) + S << "(for architecture " << ArchitectureName << "):"; + if (OutputFormat == posix && !ArchiveName.empty()) + S << ArchiveName << "[" << CurrentFilename << "]: "; + else { + if (!ArchiveName.empty()) + S << ArchiveName << ":"; + S << CurrentFilename << ": "; + } +} + +static bool isSpecialSym(SymbolicFile &Obj, StringRef Name) { + auto *ELFObj = dyn_cast<ELFObjectFileBase>(&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, - const std::string &ArchiveName, - const std::string &ArchitectureName) { + StringRef ArchiveName, + StringRef ArchitectureName) { if (!NoSort) { using Comparator = bool (*)(const NMSymbol &, const NMSymbol &); Comparator Cmp; @@ -773,24 +811,6 @@ static void sortAndPrintSymbolList(SymbolicFile &Obj, bool printName, } } - auto writeFileName = [&](raw_ostream &S) { - if (!ArchitectureName.empty()) - S << "(for architecture " << ArchitectureName << "):"; - if (OutputFormat == posix && !ArchiveName.empty()) - S << ArchiveName << "[" << CurrentFilename << "]: "; - else { - if (!ArchiveName.empty()) - S << ArchiveName << ":"; - S << CurrentFilename << ": "; - } - }; - - if (SymbolList.empty()) { - if (PrintFileName) - writeFileName(errs()); - errs() << "no symbols\n"; - } - for (const NMSymbol &S : SymbolList) { uint32_t SymFlags; std::string Name = S.Name.str(); @@ -799,19 +819,26 @@ static void sortAndPrintSymbolList(SymbolicFile &Obj, bool printName, if (Optional<std::string> Opt = demangle(S.Name, MachO)) Name = *Opt; } - if (S.Sym.getRawDataRefImpl().p) - SymFlags = S.Sym.getFlags(); - else + if (S.Sym.getRawDataRefImpl().p) { + Expected<uint32_t> SymFlagsOrErr = S.Sym.getFlags(); + if (!SymFlagsOrErr) { + // TODO: Test this error. + error(SymFlagsOrErr.takeError(), Obj.getFileName()); + return; + } + SymFlags = *SymFlagsOrErr; + } else SymFlags = S.SymFlags; bool Undefined = SymFlags & SymbolRef::SF_Undefined; bool Global = SymFlags & SymbolRef::SF_Global; bool Weak = SymFlags & SymbolRef::SF_Weak; if ((!Undefined && UndefinedOnly) || (Undefined && DefinedOnly) || - (!Global && ExternalOnly) || (Weak && NoWeakSymbols)) + (!Global && ExternalOnly) || (Weak && NoWeakSymbols) || + (!SpecialSyms && isSpecialSym(Obj, Name))) continue; if (PrintFileName) - writeFileName(outs()); + writeFileName(outs(), ArchiveName, ArchitectureName); if ((JustSymbolName || (UndefinedOnly && MachO && OutputFormat != darwin)) && OutputFormat != posix) { @@ -1041,15 +1068,19 @@ static char getSymbolNMTypeChar(MachOObjectFile &Obj, basic_symbol_iterator I) { return '?'; } +static char getSymbolNMTypeChar(TapiFile &Obj, basic_symbol_iterator I) { + return 's'; +} + static char getSymbolNMTypeChar(WasmObjectFile &Obj, basic_symbol_iterator I) { - uint32_t Flags = I->getFlags(); + uint32_t Flags = cantFail(I->getFlags()); if (Flags & SymbolRef::SF_Executable) return 't'; return 'd'; } static char getSymbolNMTypeChar(IRObjectFile &Obj, basic_symbol_iterator I) { - uint32_t Flags = I->getFlags(); + uint32_t Flags = cantFail(I->getFlags()); // FIXME: should we print 'b'? At the IR level we cannot be sure if this // will be in bss or not, but we could approximate. if (Flags & SymbolRef::SF_Executable) @@ -1081,7 +1112,8 @@ static StringRef getNMTypeName(SymbolicFile &Obj, basic_symbol_iterator I) { // section and name, to be used in format=sysv output. static char getNMSectionTagAndName(SymbolicFile &Obj, basic_symbol_iterator I, StringRef &SecName) { - uint32_t Symflags = I->getFlags(); + // Symbol Flags have been checked in the caller. + uint32_t Symflags = cantFail(I->getFlags()); if (ELFObjectFileBase *ELFObj = dyn_cast<ELFObjectFileBase>(&Obj)) { if (Symflags & object::SymbolRef::SF_Absolute) SecName = "*ABS*"; @@ -1133,6 +1165,8 @@ static char getNMSectionTagAndName(SymbolicFile &Obj, basic_symbol_iterator I, Ret = getSymbolNMTypeChar(*MachO, I); else if (WasmObjectFile *Wasm = dyn_cast<WasmObjectFile>(&Obj)) Ret = getSymbolNMTypeChar(*Wasm, I); + else if (TapiFile *Tapi = dyn_cast<TapiFile>(&Obj)) + Ret = getSymbolNMTypeChar(*Tapi, I); else if (ELFObjectFileBase *ELF = dyn_cast<ELFObjectFileBase>(&Obj)) { if (ELFSymbolRef(*I).getELFType() == ELF::STT_GNU_IFUNC) return 'i'; @@ -1184,10 +1218,9 @@ static unsigned getNsectInMachO(MachOObjectFile &Obj, BasicSymbolRef Sym) { return (STE.n_type & MachO::N_TYPE) == MachO::N_SECT ? STE.n_sect : 0; } -static void -dumpSymbolNamesFromObject(SymbolicFile &Obj, bool printName, - const std::string &ArchiveName = std::string(), - const std::string &ArchitectureName = std::string()) { +static void dumpSymbolNamesFromObject(SymbolicFile &Obj, bool printName, + StringRef ArchiveName = {}, + StringRef ArchitectureName = {}) { auto Symbols = Obj.symbols(); if (DynamicSyms) { const auto *E = dyn_cast<ELFObjectFileBase>(&Obj); @@ -1209,12 +1242,16 @@ dumpSymbolNamesFromObject(SymbolicFile &Obj, bool printName, if (Nsect == 0) return; } - if (!MachO || !DyldInfoOnly) { + if (!(MachO && DyldInfoOnly)) { for (BasicSymbolRef Sym : Symbols) { - uint32_t SymFlags = Sym.getFlags(); - if (!DebugSyms && (SymFlags & SymbolRef::SF_FormatSpecific)) + Expected<uint32_t> SymFlagsOrErr = Sym.getFlags(); + if (!SymFlagsOrErr) { + error(SymFlagsOrErr.takeError(), Obj.getFileName()); + return; + } + if (!DebugSyms && (*SymFlagsOrErr & SymbolRef::SF_FormatSpecific)) continue; - if (WithoutAliases && (SymFlags & SymbolRef::SF_Indirect)) + if (WithoutAliases && (*SymFlagsOrErr & SymbolRef::SF_Indirect)) continue; // If a "-s segname sectname" option was specified and this is a Mach-O // file and this section appears in this file, Nsect will be non-zero then @@ -1739,6 +1776,12 @@ dumpSymbolNamesFromObject(SymbolicFile &Obj, bool printName, } CurrentFilename = Obj.getFileName(); + + if (Symbols.empty() && SymbolList.empty()) { + writeFileName(errs(), ArchiveName, ArchitectureName); + errs() << "no symbols\n"; + } + sortAndPrintSymbolList(Obj, printName, ArchiveName, ArchitectureName); } @@ -1903,7 +1946,7 @@ static void dumpSymbolNamesFromFile(std::string &Filename) { if (SymbolicFile *O = dyn_cast<SymbolicFile>(&*ChildOrErr.get())) { if (PrintFileName) { - ArchiveName = A->getFileName(); + ArchiveName = std::string(A->getFileName()); if (ArchFlags.size() > 1) ArchitectureName = I->getArchFlagName(); } else { @@ -1972,7 +2015,7 @@ static void dumpSymbolNamesFromFile(std::string &Filename) { if (SymbolicFile *O = dyn_cast<SymbolicFile>(&*ChildOrErr.get())) { if (PrintFileName) - ArchiveName = A->getFileName(); + ArchiveName = std::string(A->getFileName()); else outs() << "\n" << A->getFileName() << "(" << O->getFileName() << ")" @@ -2037,7 +2080,7 @@ static void dumpSymbolNamesFromFile(std::string &Filename) { } if (SymbolicFile *F = dyn_cast<SymbolicFile>(&*ChildOrErr.get())) { if (PrintFileName) { - ArchiveName = A->getFileName(); + ArchiveName = std::string(A->getFileName()); if (isa<MachOObjectFile>(F) && moreThanOneArch) ArchitectureName = O.getArchFlagName(); } else { @@ -2066,6 +2109,31 @@ static void dumpSymbolNamesFromFile(std::string &Filename) { } return; } + + if (TapiUniversal *TU = dyn_cast<TapiUniversal>(&Bin)) { + for (const TapiUniversal::ObjectForArch &I : TU->objects()) { + StringRef ArchName = I.getArchFlagName(); + const bool ShowArch = + ArchFlags.empty() || + any_of(ArchFlags, [&](StringRef Name) { return Name == ArchName; }); + if (!ShowArch) + continue; + if (!AddInlinedInfo && !I.isTopLevelLib()) + continue; + if (auto ObjOrErr = I.getAsObjectFile()) { + outs() << "\n" + << I.getInstallName() << " (for architecture " << ArchName << ")" + << ":\n"; + dumpSymbolNamesFromObject(*ObjOrErr.get(), false, {}, ArchName); + } else if (Error E = + isNotObjectErrorInvalidFileType(ObjOrErr.takeError())) { + error(std::move(E), Filename, ArchName); + } + } + + return; + } + if (SymbolicFile *O = dyn_cast<SymbolicFile>(&Bin)) { if (!MachOPrintSizeWarning && PrintSize && isa<MachOObjectFile>(O)) { WithColor::warning(errs(), ToolName) |