summaryrefslogtreecommitdiff
path: root/llvm/tools/llvm-nm/llvm-nm.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/tools/llvm-nm/llvm-nm.cpp')
-rw-r--r--llvm/tools/llvm-nm/llvm-nm.cpp156
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)