Bug Summary

File:build/llvm-toolchain-snapshot-15~++20220420111733+e13d2efed663/llvm/tools/llvm-nm/llvm-nm.cpp
Warning:line 352, column 9
Called C++ object pointer is null

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name llvm-nm.cpp -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -analyzer-config-compatibility-mode=true -mrelocation-model pic -pic-level 2 -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -ffunction-sections -fdata-sections -fcoverage-compilation-dir=/build/llvm-toolchain-snapshot-15~++20220420111733+e13d2efed663/build-llvm -resource-dir /usr/lib/llvm-15/lib/clang/15.0.0 -D _DEBUG -D _GNU_SOURCE -D __STDC_CONSTANT_MACROS -D __STDC_FORMAT_MACROS -D __STDC_LIMIT_MACROS -I tools/llvm-nm -I /build/llvm-toolchain-snapshot-15~++20220420111733+e13d2efed663/llvm/tools/llvm-nm -I include -I /build/llvm-toolchain-snapshot-15~++20220420111733+e13d2efed663/llvm/include -D _FORTIFY_SOURCE=2 -D NDEBUG -U NDEBUG -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/x86_64-linux-gnu/c++/10 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/backward -internal-isystem /usr/lib/llvm-15/lib/clang/15.0.0/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/10/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -fmacro-prefix-map=/build/llvm-toolchain-snapshot-15~++20220420111733+e13d2efed663/build-llvm=build-llvm -fmacro-prefix-map=/build/llvm-toolchain-snapshot-15~++20220420111733+e13d2efed663/= -fcoverage-prefix-map=/build/llvm-toolchain-snapshot-15~++20220420111733+e13d2efed663/build-llvm=build-llvm -fcoverage-prefix-map=/build/llvm-toolchain-snapshot-15~++20220420111733+e13d2efed663/= -O3 -Wno-unused-command-line-argument -Wno-unused-parameter -Wwrite-strings -Wno-missing-field-initializers -Wno-long-long -Wno-maybe-uninitialized -Wno-class-memaccess -Wno-redundant-move -Wno-pessimizing-move -Wno-noexcept-type -Wno-comment -std=c++14 -fdeprecated-macro -fdebug-compilation-dir=/build/llvm-toolchain-snapshot-15~++20220420111733+e13d2efed663/build-llvm -fdebug-prefix-map=/build/llvm-toolchain-snapshot-15~++20220420111733+e13d2efed663/build-llvm=build-llvm -fdebug-prefix-map=/build/llvm-toolchain-snapshot-15~++20220420111733+e13d2efed663/= -ferror-limit 19 -fvisibility-inlines-hidden -stack-protector 2 -fgnuc-version=4.2.1 -fcolor-diagnostics -vectorize-loops -vectorize-slp -analyzer-output=html -analyzer-config stable-report-filename=true -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /tmp/scan-build-2022-04-20-140412-16051-1 -x c++ /build/llvm-toolchain-snapshot-15~++20220420111733+e13d2efed663/llvm/tools/llvm-nm/llvm-nm.cpp
1//===-- llvm-nm.cpp - Symbol table dumping utility for llvm ---------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This program is a utility that works like traditional Unix "nm", that is, it
10// prints out the names of symbols in a bitcode or object file, along with some
11// information about each symbol.
12//
13// This "nm" supports many of the features of GNU "nm", including its different
14// output formats.
15//
16//===----------------------------------------------------------------------===//
17
18#include "llvm/ADT/StringSwitch.h"
19#include "llvm/BinaryFormat/COFF.h"
20#include "llvm/BinaryFormat/XCOFF.h"
21#include "llvm/Demangle/Demangle.h"
22#include "llvm/IR/Function.h"
23#include "llvm/IR/LLVMContext.h"
24#include "llvm/Object/Archive.h"
25#include "llvm/Object/COFF.h"
26#include "llvm/Object/COFFImportFile.h"
27#include "llvm/Object/ELFObjectFile.h"
28#include "llvm/Object/IRObjectFile.h"
29#include "llvm/Object/MachO.h"
30#include "llvm/Object/MachOUniversal.h"
31#include "llvm/Object/ObjectFile.h"
32#include "llvm/Object/TapiFile.h"
33#include "llvm/Object/TapiUniversal.h"
34#include "llvm/Object/Wasm.h"
35#include "llvm/Object/XCOFFObjectFile.h"
36#include "llvm/Option/Arg.h"
37#include "llvm/Option/ArgList.h"
38#include "llvm/Option/Option.h"
39#include "llvm/Support/CommandLine.h"
40#include "llvm/Support/FileSystem.h"
41#include "llvm/Support/Format.h"
42#include "llvm/Support/InitLLVM.h"
43#include "llvm/Support/MemoryBuffer.h"
44#include "llvm/Support/Program.h"
45#include "llvm/Support/Signals.h"
46#include "llvm/Support/TargetSelect.h"
47#include "llvm/Support/WithColor.h"
48#include "llvm/Support/raw_ostream.h"
49#include <vector>
50
51using namespace llvm;
52using namespace object;
53
54namespace {
55using namespace llvm::opt; // for HelpHidden in Opts.inc
56enum ID {
57 OPT_INVALID = 0, // This is not an option ID.
58#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \
59 HELPTEXT, METAVAR, VALUES) \
60 OPT_##ID,
61#include "Opts.inc"
62#undef OPTION
63};
64
65#define PREFIX(NAME, VALUE) const char *const NAME[] = VALUE;
66#include "Opts.inc"
67#undef PREFIX
68
69const opt::OptTable::Info InfoTable[] = {
70#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \
71 HELPTEXT, METAVAR, VALUES) \
72 { \
73 PREFIX, NAME, HELPTEXT, \
74 METAVAR, OPT_##ID, opt::Option::KIND##Class, \
75 PARAM, FLAGS, OPT_##GROUP, \
76 OPT_##ALIAS, ALIASARGS, VALUES},
77#include "Opts.inc"
78#undef OPTION
79};
80
81class NmOptTable : public opt::OptTable {
82public:
83 NmOptTable() : OptTable(InfoTable) { setGroupedShortOptions(true); }
84};
85
86enum OutputFormatTy { bsd, sysv, posix, darwin, just_symbols };
87enum class BitModeTy { Bit32, Bit64, Bit32_64, Any };
88} // namespace
89
90static bool ArchiveMap;
91static BitModeTy BitMode;
92static bool DebugSyms;
93static bool DefinedOnly;
94static bool Demangle;
95static bool DynamicSyms;
96static bool ExportSymbols;
97static bool ExternalOnly;
98static OutputFormatTy OutputFormat;
99static bool NoLLVMBitcode;
100static bool NoSort;
101static bool NoWeakSymbols;
102static bool NumericSort;
103static bool PrintFileName;
104static bool PrintSize;
105static bool Quiet;
106static bool ReverseSort;
107static bool SpecialSyms;
108static bool SizeSort;
109static bool UndefinedOnly;
110static bool WithoutAliases;
111
112// XCOFF-specific options.
113static bool NoRsrc;
114
115namespace {
116enum Radix { d, o, x };
117} // namespace
118static Radix AddressRadix;
119
120// Mach-O specific options.
121static bool ArchAll = false;
122static std::vector<StringRef> ArchFlags;
123static bool AddDyldInfo;
124static bool AddInlinedInfo;
125static bool DyldInfoOnly;
126static bool FormatMachOasHex;
127static bool NoDyldInfo;
128static std::vector<StringRef> SegSect;
129static bool MachOPrintSizeWarning = false;
130
131// Miscellaneous states.
132static bool PrintAddress = true;
133static bool MultipleFiles = false;
134static bool HadError = false;
135
136static StringRef ToolName;
137
138static void warn(Error Err, Twine FileName, Twine Context = Twine(),
139 Twine Archive = Twine()) {
140 assert(Err)(static_cast <bool> (Err) ? void (0) : __assert_fail ("Err"
, "llvm/tools/llvm-nm/llvm-nm.cpp", 140, __extension__ __PRETTY_FUNCTION__
))
;
141
142 // Flush the standard output so that the warning isn't interleaved with other
143 // output if stdout and stderr are writing to the same place.
144 outs().flush();
145
146 handleAllErrors(std::move(Err), [&](const ErrorInfoBase &EI) {
147 WithColor::warning(errs(), ToolName)
148 << (Archive.str().empty() ? FileName : Archive + "(" + FileName + ")")
149 << ": " << (Context.str().empty() ? "" : Context + ": ") << EI.message()
150 << "\n";
151 });
152}
153
154static void error(Twine Message, Twine Path = Twine()) {
155 HadError = true;
156 WithColor::error(errs(), ToolName) << Path << ": " << Message << "\n";
157}
158
159static bool error(std::error_code EC, Twine Path = Twine()) {
160 if (EC) {
161 error(EC.message(), Path);
162 return true;
163 }
164 return false;
165}
166
167// This version of error() prints the archive name and member name, for example:
168// "libx.a(foo.o)" after the ToolName before the error message. It sets
169// HadError but returns allowing the code to move on to other archive members.
170static void error(llvm::Error E, StringRef FileName, const Archive::Child &C,
171 StringRef ArchitectureName = StringRef()) {
172 HadError = true;
173 WithColor::error(errs(), ToolName) << FileName;
174
175 Expected<StringRef> NameOrErr = C.getName();
176 // TODO: if we have a error getting the name then it would be nice to print
177 // the index of which archive member this is and or its offset in the
178 // archive instead of "???" as the name.
179 if (!NameOrErr) {
180 consumeError(NameOrErr.takeError());
181 errs() << "(" << "???" << ")";
182 } else
183 errs() << "(" << NameOrErr.get() << ")";
184
185 if (!ArchitectureName.empty())
186 errs() << " (for architecture " << ArchitectureName << ")";
187
188 std::string Buf;
189 raw_string_ostream OS(Buf);
190 logAllUnhandledErrors(std::move(E), OS);
191 OS.flush();
192 errs() << ": " << Buf << "\n";
193}
194
195// This version of error() prints the file name and which architecture slice it
196// is from, for example: "foo.o (for architecture i386)" after the ToolName
197// before the error message. It sets HadError but returns allowing the code to
198// move on to other architecture slices.
199static void error(llvm::Error E, StringRef FileName,
200 StringRef ArchitectureName = StringRef()) {
201 HadError = true;
202 WithColor::error(errs(), ToolName) << FileName;
203
204 if (!ArchitectureName.empty())
205 errs() << " (for architecture " << ArchitectureName << ")";
206
207 std::string Buf;
208 raw_string_ostream OS(Buf);
209 logAllUnhandledErrors(std::move(E), OS);
210 OS.flush();
211 errs() << ": " << Buf << "\n";
212}
213
214namespace {
215struct NMSymbol {
216 uint64_t Address;
217 uint64_t Size;
218 char TypeChar;
219 std::string Name;
220 StringRef SectionName;
221 StringRef TypeName;
222 BasicSymbolRef Sym;
223 StringRef Visibility;
224
225 // The Sym field above points to the native symbol in the object file,
226 // for Mach-O when we are creating symbols from the dyld info the above
227 // pointer is null as there is no native symbol. In these cases the fields
228 // below are filled in to represent what would have been a Mach-O nlist
229 // native symbol.
230 uint32_t SymFlags;
231 SectionRef Section;
232 uint8_t NType;
233 uint8_t NSect;
234 uint16_t NDesc;
235 std::string IndirectName;
236
237 bool isDefined() const {
238 if (Sym.getRawDataRefImpl().p) {
239 uint32_t Flags = cantFail(Sym.getFlags());
240 return !(Flags & SymbolRef::SF_Undefined);
241 }
242 return TypeChar != 'U';
243 }
244
245 bool initializeFlags(const SymbolicFile &Obj) {
246 Expected<uint32_t> SymFlagsOrErr = Sym.getFlags();
247 if (!SymFlagsOrErr) {
248 // TODO: Test this error.
249 error(SymFlagsOrErr.takeError(), Obj.getFileName());
250 return false;
251 }
252 SymFlags = *SymFlagsOrErr;
253 return true;
254 }
255
256 bool shouldPrint() const {
257 bool Undefined = SymFlags & SymbolRef::SF_Undefined;
258 bool Global = SymFlags & SymbolRef::SF_Global;
259 bool Weak = SymFlags & SymbolRef::SF_Weak;
260 bool FormatSpecific = SymFlags & SymbolRef::SF_FormatSpecific;
261 if ((!Undefined && UndefinedOnly) || (Undefined && DefinedOnly) ||
262 (!Global && ExternalOnly) || (Weak && NoWeakSymbols) ||
263 (FormatSpecific && !(SpecialSyms || DebugSyms)))
264 return false;
265 return true;
266 }
267};
268
269bool operator<(const NMSymbol &A, const NMSymbol &B) {
270 if (NumericSort)
271 return std::make_tuple(A.isDefined(), A.Address, A.Name, A.Size) <
272 std::make_tuple(B.isDefined(), B.Address, B.Name, B.Size);
273 if (SizeSort)
274 return std::make_tuple(A.Size, A.Name, A.Address) <
275 std::make_tuple(B.Size, B.Name, B.Address);
276 if (ExportSymbols)
277 return std::make_tuple(A.Name, A.Visibility) <
278 std::make_tuple(B.Name, B.Visibility);
279 return std::make_tuple(A.Name, A.Size, A.Address) <
280 std::make_tuple(B.Name, B.Size, B.Address);
281}
282
283bool operator>(const NMSymbol &A, const NMSymbol &B) { return B < A; }
284bool operator==(const NMSymbol &A, const NMSymbol &B) {
285 return !(A < B) && !(B < A);
286}
287} // anonymous namespace
288
289static char isSymbolList64Bit(SymbolicFile &Obj) {
290 if (auto *IRObj = dyn_cast<IRObjectFile>(&Obj))
291 return Triple(IRObj->getTargetTriple()).isArch64Bit();
292 if (isa<COFFObjectFile>(Obj) || isa<COFFImportFile>(Obj))
293 return false;
294 if (XCOFFObjectFile *XCOFFObj = dyn_cast<XCOFFObjectFile>(&Obj))
295 return XCOFFObj->is64Bit();
296 if (isa<WasmObjectFile>(Obj))
297 return false;
298 if (TapiFile *Tapi = dyn_cast<TapiFile>(&Obj))
299 return Tapi->is64Bit();
300 if (MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(&Obj))
301 return MachO->is64Bit();
302 return cast<ELFObjectFileBase>(Obj).getBytesInAddress() == 8;
303}
304
305static StringRef CurrentFilename;
306
307static char getSymbolNMTypeChar(IRObjectFile &Obj, basic_symbol_iterator I);
308
309// darwinPrintSymbol() is used to print a symbol from a Mach-O file when the
310// the OutputFormat is darwin or we are printing Mach-O symbols in hex. For
311// the darwin format it produces the same output as darwin's nm(1) -m output
312// and when printing Mach-O symbols in hex it produces the same output as
313// darwin's nm(1) -x format.
314static void darwinPrintSymbol(SymbolicFile &Obj, const NMSymbol &S,
315 char *SymbolAddrStr, const char *printBlanks,
316 const char *printDashes,
317 const char *printFormat) {
318 MachO::mach_header H;
319 MachO::mach_header_64 H_64;
320 uint32_t Filetype = MachO::MH_OBJECT;
321 uint32_t Flags = 0;
322 uint8_t NType = 0;
323 uint8_t NSect = 0;
324 uint16_t NDesc = 0;
325 uint32_t NStrx = 0;
326 uint64_t NValue = 0;
327 MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(&Obj);
1
Assuming the object is not a 'MachOObjectFile'
2
'MachO' initialized to a null pointer value
328 if (Obj.isIR()) {
3
Taking false branch
329 uint32_t SymFlags = cantFail(S.Sym.getFlags());
330 if (SymFlags & SymbolRef::SF_Global)
331 NType |= MachO::N_EXT;
332 if (SymFlags & SymbolRef::SF_Hidden)
333 NType |= MachO::N_PEXT;
334 if (SymFlags & SymbolRef::SF_Undefined)
335 NType |= MachO::N_EXT | MachO::N_UNDF;
336 else {
337 // Here we have a symbol definition. So to fake out a section name we
338 // use 1, 2 and 3 for section numbers. See below where they are used to
339 // print out fake section names.
340 NType |= MachO::N_SECT;
341 if (SymFlags & SymbolRef::SF_Const)
342 NSect = 3;
343 else if (SymFlags & SymbolRef::SF_Executable)
344 NSect = 1;
345 else
346 NSect = 2;
347 }
348 if (SymFlags & SymbolRef::SF_Weak)
349 NDesc |= MachO::N_WEAK_DEF;
350 } else {
351 DataRefImpl SymDRI = S.Sym.getRawDataRefImpl();
352 if (MachO->is64Bit()) {
4
Called C++ object pointer is null
353 H_64 = MachO->MachOObjectFile::getHeader64();
354 Filetype = H_64.filetype;
355 Flags = H_64.flags;
356 if (SymDRI.p){
357 MachO::nlist_64 STE_64 = MachO->getSymbol64TableEntry(SymDRI);
358 NType = STE_64.n_type;
359 NSect = STE_64.n_sect;
360 NDesc = STE_64.n_desc;
361 NStrx = STE_64.n_strx;
362 NValue = STE_64.n_value;
363 } else {
364 NType = S.NType;
365 NSect = S.NSect;
366 NDesc = S.NDesc;
367 NStrx = 0;
368 NValue = S.Address;
369 }
370 } else {
371 H = MachO->MachOObjectFile::getHeader();
372 Filetype = H.filetype;
373 Flags = H.flags;
374 if (SymDRI.p){
375 MachO::nlist STE = MachO->getSymbolTableEntry(SymDRI);
376 NType = STE.n_type;
377 NSect = STE.n_sect;
378 NDesc = STE.n_desc;
379 NStrx = STE.n_strx;
380 NValue = STE.n_value;
381 } else {
382 NType = S.NType;
383 NSect = S.NSect;
384 NDesc = S.NDesc;
385 NStrx = 0;
386 NValue = S.Address;
387 }
388 }
389 }
390
391 // If we are printing Mach-O symbols in hex do that and return.
392 if (FormatMachOasHex) {
393 outs() << format(printFormat, NValue) << ' '
394 << format("%02x %02x %04x %08x", NType, NSect, NDesc, NStrx) << ' '
395 << S.Name;
396 if ((NType & MachO::N_TYPE) == MachO::N_INDR) {
397 outs() << " (indirect for ";
398 outs() << format(printFormat, NValue) << ' ';
399 StringRef IndirectName;
400 if (S.Sym.getRawDataRefImpl().p) {
401 if (MachO->getIndirectName(S.Sym.getRawDataRefImpl(), IndirectName))
402 outs() << "?)";
403 else
404 outs() << IndirectName << ")";
405 } else
406 outs() << S.IndirectName << ")";
407 }
408 outs() << "\n";
409 return;
410 }
411
412 if (PrintAddress) {
413 if ((NType & MachO::N_TYPE) == MachO::N_INDR)
414 strcpy(SymbolAddrStr, printBlanks);
415 if (Obj.isIR() && (NType & MachO::N_TYPE) == MachO::N_TYPE)
416 strcpy(SymbolAddrStr, printDashes);
417 outs() << SymbolAddrStr << ' ';
418 }
419
420 switch (NType & MachO::N_TYPE) {
421 case MachO::N_UNDF:
422 if (NValue != 0) {
423 outs() << "(common) ";
424 if (MachO::GET_COMM_ALIGN(NDesc) != 0)
425 outs() << "(alignment 2^" << (int)MachO::GET_COMM_ALIGN(NDesc) << ") ";
426 } else {
427 if ((NType & MachO::N_TYPE) == MachO::N_PBUD)
428 outs() << "(prebound ";
429 else
430 outs() << "(";
431 if ((NDesc & MachO::REFERENCE_TYPE) ==
432 MachO::REFERENCE_FLAG_UNDEFINED_LAZY)
433 outs() << "undefined [lazy bound]) ";
434 else if ((NDesc & MachO::REFERENCE_TYPE) ==
435 MachO::REFERENCE_FLAG_PRIVATE_UNDEFINED_LAZY)
436 outs() << "undefined [private lazy bound]) ";
437 else if ((NDesc & MachO::REFERENCE_TYPE) ==
438 MachO::REFERENCE_FLAG_PRIVATE_UNDEFINED_NON_LAZY)
439 outs() << "undefined [private]) ";
440 else
441 outs() << "undefined) ";
442 }
443 break;
444 case MachO::N_ABS:
445 outs() << "(absolute) ";
446 break;
447 case MachO::N_INDR:
448 outs() << "(indirect) ";
449 break;
450 case MachO::N_SECT: {
451 if (Obj.isIR()) {
452 // For llvm bitcode files print out a fake section name using the values
453 // use 1, 2 and 3 for section numbers as set above.
454 if (NSect == 1)
455 outs() << "(LTO,CODE) ";
456 else if (NSect == 2)
457 outs() << "(LTO,DATA) ";
458 else if (NSect == 3)
459 outs() << "(LTO,RODATA) ";
460 else
461 outs() << "(?,?) ";
462 break;
463 }
464 section_iterator Sec = SectionRef();
465 if (S.Sym.getRawDataRefImpl().p) {
466 Expected<section_iterator> SecOrErr =
467 MachO->getSymbolSection(S.Sym.getRawDataRefImpl());
468 if (!SecOrErr) {
469 consumeError(SecOrErr.takeError());
470 outs() << "(?,?) ";
471 break;
472 }
473 Sec = *SecOrErr;
474 if (Sec == MachO->section_end()) {
475 outs() << "(?,?) ";
476 break;
477 }
478 } else {
479 Sec = S.Section;
480 }
481 DataRefImpl Ref = Sec->getRawDataRefImpl();
482 StringRef SectionName;
483 if (Expected<StringRef> NameOrErr = MachO->getSectionName(Ref))
484 SectionName = *NameOrErr;
485 StringRef SegmentName = MachO->getSectionFinalSegmentName(Ref);
486 outs() << "(" << SegmentName << "," << SectionName << ") ";
487 break;
488 }
489 default:
490 outs() << "(?) ";
491 break;
492 }
493
494 if (NType & MachO::N_EXT) {
495 if (NDesc & MachO::REFERENCED_DYNAMICALLY)
496 outs() << "[referenced dynamically] ";
497 if (NType & MachO::N_PEXT) {
498 if ((NDesc & MachO::N_WEAK_DEF) == MachO::N_WEAK_DEF)
499 outs() << "weak private external ";
500 else
501 outs() << "private external ";
502 } else {
503 if ((NDesc & MachO::N_WEAK_REF) == MachO::N_WEAK_REF ||
504 (NDesc & MachO::N_WEAK_DEF) == MachO::N_WEAK_DEF) {
505 if ((NDesc & (MachO::N_WEAK_REF | MachO::N_WEAK_DEF)) ==
506 (MachO::N_WEAK_REF | MachO::N_WEAK_DEF))
507 outs() << "weak external automatically hidden ";
508 else
509 outs() << "weak external ";
510 } else
511 outs() << "external ";
512 }
513 } else {
514 if (NType & MachO::N_PEXT)
515 outs() << "non-external (was a private external) ";
516 else
517 outs() << "non-external ";
518 }
519
520 if (Filetype == MachO::MH_OBJECT) {
521 if (NDesc & MachO::N_NO_DEAD_STRIP)
522 outs() << "[no dead strip] ";
523 if ((NType & MachO::N_TYPE) != MachO::N_UNDF &&
524 NDesc & MachO::N_SYMBOL_RESOLVER)
525 outs() << "[symbol resolver] ";
526 if ((NType & MachO::N_TYPE) != MachO::N_UNDF && NDesc & MachO::N_ALT_ENTRY)
527 outs() << "[alt entry] ";
528 if ((NType & MachO::N_TYPE) != MachO::N_UNDF && NDesc & MachO::N_COLD_FUNC)
529 outs() << "[cold func] ";
530 }
531
532 if ((NDesc & MachO::N_ARM_THUMB_DEF) == MachO::N_ARM_THUMB_DEF)
533 outs() << "[Thumb] ";
534
535 if ((NType & MachO::N_TYPE) == MachO::N_INDR) {
536 outs() << S.Name << " (for ";
537 StringRef IndirectName;
538 if (MachO) {
539 if (S.Sym.getRawDataRefImpl().p) {
540 if (MachO->getIndirectName(S.Sym.getRawDataRefImpl(), IndirectName))
541 outs() << "?)";
542 else
543 outs() << IndirectName << ")";
544 } else
545 outs() << S.IndirectName << ")";
546 } else
547 outs() << "?)";
548 } else
549 outs() << S.Name;
550
551 if ((Flags & MachO::MH_TWOLEVEL) == MachO::MH_TWOLEVEL &&
552 (((NType & MachO::N_TYPE) == MachO::N_UNDF && NValue == 0) ||
553 (NType & MachO::N_TYPE) == MachO::N_PBUD)) {
554 uint32_t LibraryOrdinal = MachO::GET_LIBRARY_ORDINAL(NDesc);
555 if (LibraryOrdinal != 0) {
556 if (LibraryOrdinal == MachO::EXECUTABLE_ORDINAL)
557 outs() << " (from executable)";
558 else if (LibraryOrdinal == MachO::DYNAMIC_LOOKUP_ORDINAL)
559 outs() << " (dynamically looked up)";
560 else {
561 StringRef LibraryName;
562 if (!MachO ||
563 MachO->getLibraryShortNameByIndex(LibraryOrdinal - 1, LibraryName))
564 outs() << " (from bad library ordinal " << LibraryOrdinal << ")";
565 else
566 outs() << " (from " << LibraryName << ")";
567 }
568 }
569 }
570
571 outs() << "\n";
572}
573
574// Table that maps Darwin's Mach-O stab constants to strings to allow printing.
575struct DarwinStabName {
576 uint8_t NType;
577 const char *Name;
578};
579const struct DarwinStabName DarwinStabNames[] = {
580 {MachO::N_GSYM, "GSYM"},
581 {MachO::N_FNAME, "FNAME"},
582 {MachO::N_FUN, "FUN"},
583 {MachO::N_STSYM, "STSYM"},
584 {MachO::N_LCSYM, "LCSYM"},
585 {MachO::N_BNSYM, "BNSYM"},
586 {MachO::N_PC, "PC"},
587 {MachO::N_AST, "AST"},
588 {MachO::N_OPT, "OPT"},
589 {MachO::N_RSYM, "RSYM"},
590 {MachO::N_SLINE, "SLINE"},
591 {MachO::N_ENSYM, "ENSYM"},
592 {MachO::N_SSYM, "SSYM"},
593 {MachO::N_SO, "SO"},
594 {MachO::N_OSO, "OSO"},
595 {MachO::N_LSYM, "LSYM"},
596 {MachO::N_BINCL, "BINCL"},
597 {MachO::N_SOL, "SOL"},
598 {MachO::N_PARAMS, "PARAM"},
599 {MachO::N_VERSION, "VERS"},
600 {MachO::N_OLEVEL, "OLEV"},
601 {MachO::N_PSYM, "PSYM"},
602 {MachO::N_EINCL, "EINCL"},
603 {MachO::N_ENTRY, "ENTRY"},
604 {MachO::N_LBRAC, "LBRAC"},
605 {MachO::N_EXCL, "EXCL"},
606 {MachO::N_RBRAC, "RBRAC"},
607 {MachO::N_BCOMM, "BCOMM"},
608 {MachO::N_ECOMM, "ECOMM"},
609 {MachO::N_ECOML, "ECOML"},
610 {MachO::N_LENG, "LENG"},
611};
612
613static const char *getDarwinStabString(uint8_t NType) {
614 for (auto I : makeArrayRef(DarwinStabNames))
615 if (I.NType == NType)
616 return I.Name;
617 return nullptr;
618}
619
620// darwinPrintStab() prints the n_sect, n_desc along with a symbolic name of
621// a stab n_type value in a Mach-O file.
622static void darwinPrintStab(MachOObjectFile *MachO, const NMSymbol &S) {
623 MachO::nlist_64 STE_64;
624 MachO::nlist STE;
625 uint8_t NType;
626 uint8_t NSect;
627 uint16_t NDesc;
628 DataRefImpl SymDRI = S.Sym.getRawDataRefImpl();
629 if (MachO->is64Bit()) {
630 STE_64 = MachO->getSymbol64TableEntry(SymDRI);
631 NType = STE_64.n_type;
632 NSect = STE_64.n_sect;
633 NDesc = STE_64.n_desc;
634 } else {
635 STE = MachO->getSymbolTableEntry(SymDRI);
636 NType = STE.n_type;
637 NSect = STE.n_sect;
638 NDesc = STE.n_desc;
639 }
640
641 outs() << format(" %02x %04x ", NSect, NDesc);
642 if (const char *stabString = getDarwinStabString(NType))
643 outs() << format("%5.5s", stabString);
644 else
645 outs() << format(" %02x", NType);
646}
647
648static Optional<std::string> demangle(StringRef Name) {
649 std::string Demangled;
650 if (nonMicrosoftDemangle(Name.str().c_str(), Demangled))
651 return Demangled;
652 return None;
653}
654
655static Optional<std::string> demangleXCOFF(StringRef Name) {
656 if (Name.empty() || Name[0] != '.')
657 return demangle(Name);
658
659 Name = Name.drop_front();
660 Optional<std::string> DemangledName = demangle(Name);
661 if (DemangledName)
662 return "." + *DemangledName;
663 return None;
664}
665
666static Optional<std::string> demangleMachO(StringRef Name) {
667 if (!Name.empty() && Name[0] == '_')
668 Name = Name.drop_front();
669 return demangle(Name);
670}
671
672static bool symbolIsDefined(const NMSymbol &Sym) {
673 return Sym.TypeChar != 'U' && Sym.TypeChar != 'w' && Sym.TypeChar != 'v';
674}
675
676static void writeFileName(raw_ostream &S, StringRef ArchiveName,
677 StringRef ArchitectureName) {
678 if (!ArchitectureName.empty())
679 S << "(for architecture " << ArchitectureName << "):";
680 if (OutputFormat == posix && !ArchiveName.empty())
681 S << ArchiveName << "[" << CurrentFilename << "]: ";
682 else {
683 if (!ArchiveName.empty())
684 S << ArchiveName << ":";
685 S << CurrentFilename << ": ";
686 }
687}
688
689static void sortSymbolList(std::vector<NMSymbol> &SymbolList) {
690 if (NoSort)
691 return;
692
693 if (ReverseSort)
694 llvm::sort(SymbolList, std::greater<>());
695 else
696 llvm::sort(SymbolList);
697}
698
699static void printExportSymbolList(const std::vector<NMSymbol> &SymbolList) {
700 for (const NMSymbol &Sym : SymbolList) {
701 outs() << Sym.Name;
702 if (!Sym.Visibility.empty())
703 outs() << ' ' << Sym.Visibility;
704 outs() << '\n';
705 }
706}
707
708static void printSymbolList(SymbolicFile &Obj,
709 std::vector<NMSymbol> &SymbolList, bool printName,
710 StringRef ArchiveName, StringRef ArchitectureName) {
711 if (!PrintFileName) {
712 if ((OutputFormat == bsd || OutputFormat == posix ||
713 OutputFormat == just_symbols) &&
714 MultipleFiles && printName) {
715 outs() << '\n' << CurrentFilename << ":\n";
716 } else if (OutputFormat == sysv) {
717 outs() << "\n\nSymbols from " << CurrentFilename << ":\n\n";
718 if (isSymbolList64Bit(Obj))
719 outs() << "Name Value Class Type"
720 << " Size Line Section\n";
721 else
722 outs() << "Name Value Class Type"
723 << " Size Line Section\n";
724 }
725 }
726
727 const char *printBlanks, *printDashes, *printFormat;
728 if (isSymbolList64Bit(Obj)) {
729 printBlanks = " ";
730 printDashes = "----------------";
731 switch (AddressRadix) {
732 case Radix::o:
733 printFormat = OutputFormat == posix ? "%" PRIo64"l" "o" : "%016" PRIo64"l" "o";
734 break;
735 case Radix::x:
736 printFormat = OutputFormat == posix ? "%" PRIx64"l" "x" : "%016" PRIx64"l" "x";
737 break;
738 default:
739 printFormat = OutputFormat == posix ? "%" PRId64"l" "d" : "%016" PRId64"l" "d";
740 }
741 } else {
742 printBlanks = " ";
743 printDashes = "--------";
744 switch (AddressRadix) {
745 case Radix::o:
746 printFormat = OutputFormat == posix ? "%" PRIo64"l" "o" : "%08" PRIo64"l" "o";
747 break;
748 case Radix::x:
749 printFormat = OutputFormat == posix ? "%" PRIx64"l" "x" : "%08" PRIx64"l" "x";
750 break;
751 default:
752 printFormat = OutputFormat == posix ? "%" PRId64"l" "d" : "%08" PRId64"l" "d";
753 }
754 }
755
756 for (const NMSymbol &S : SymbolList) {
757 if (!S.shouldPrint())
758 continue;
759
760 std::string Name = S.Name;
761 MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(&Obj);
762 if (Demangle) {
763 function_ref<Optional<std::string>(StringRef)> Fn = ::demangle;
764 if (Obj.isXCOFF())
765 Fn = demangleXCOFF;
766 if (Obj.isMachO())
767 Fn = demangleMachO;
768 if (Optional<std::string> Opt = Fn(S.Name))
769 Name = *Opt;
770 }
771
772 if (PrintFileName)
773 writeFileName(outs(), ArchiveName, ArchitectureName);
774 if ((OutputFormat == just_symbols ||
775 (UndefinedOnly && MachO && OutputFormat != darwin)) &&
776 OutputFormat != posix) {
777 outs() << Name << "\n";
778 continue;
779 }
780
781 char SymbolAddrStr[23], SymbolSizeStr[23];
782
783 // If the format is SysV or the symbol isn't defined, then print spaces.
784 if (OutputFormat == sysv || !symbolIsDefined(S)) {
785 if (OutputFormat == posix) {
786 format(printFormat, S.Address)
787 .print(SymbolAddrStr, sizeof(SymbolAddrStr));
788 format(printFormat, S.Size).print(SymbolSizeStr, sizeof(SymbolSizeStr));
789 } else {
790 strcpy(SymbolAddrStr, printBlanks);
791 strcpy(SymbolSizeStr, printBlanks);
792 }
793 }
794
795 if (symbolIsDefined(S)) {
796 // Otherwise, print the symbol address and size.
797 if (Obj.isIR())
798 strcpy(SymbolAddrStr, printDashes);
799 else if (MachO && S.TypeChar == 'I')
800 strcpy(SymbolAddrStr, printBlanks);
801 else
802 format(printFormat, S.Address)
803 .print(SymbolAddrStr, sizeof(SymbolAddrStr));
804 format(printFormat, S.Size).print(SymbolSizeStr, sizeof(SymbolSizeStr));
805 }
806
807 // If OutputFormat is darwin or we are printing Mach-O symbols in hex and
808 // we have a MachOObjectFile, call darwinPrintSymbol to print as darwin's
809 // nm(1) -m output or hex, else if OutputFormat is darwin or we are
810 // printing Mach-O symbols in hex and not a Mach-O object fall back to
811 // OutputFormat bsd (see below).
812 if ((OutputFormat == darwin || FormatMachOasHex) && (MachO || Obj.isIR())) {
813 darwinPrintSymbol(Obj, S, SymbolAddrStr, printBlanks, printDashes,
814 printFormat);
815 } else if (OutputFormat == posix) {
816 outs() << Name << " " << S.TypeChar << " " << SymbolAddrStr << " "
817 << (MachO ? "0" : SymbolSizeStr) << "\n";
818 } else if (OutputFormat == bsd || (OutputFormat == darwin && !MachO)) {
819 if (PrintAddress)
820 outs() << SymbolAddrStr << ' ';
821 if (PrintSize)
822 outs() << SymbolSizeStr << ' ';
823 outs() << S.TypeChar;
824 if (S.TypeChar == '-' && MachO)
825 darwinPrintStab(MachO, S);
826 outs() << " " << Name;
827 if (S.TypeChar == 'I' && MachO) {
828 outs() << " (indirect for ";
829 if (S.Sym.getRawDataRefImpl().p) {
830 StringRef IndirectName;
831 if (MachO->getIndirectName(S.Sym.getRawDataRefImpl(), IndirectName))
832 outs() << "?)";
833 else
834 outs() << IndirectName << ")";
835 } else
836 outs() << S.IndirectName << ")";
837 }
838 outs() << "\n";
839 } else if (OutputFormat == sysv) {
840 outs() << left_justify(Name, 20) << "|" << SymbolAddrStr << "| "
841 << S.TypeChar << " |" << right_justify(S.TypeName, 18) << "|"
842 << SymbolSizeStr << "| |" << S.SectionName << "\n";
843 }
844 }
845
846 SymbolList.clear();
847}
848
849static char getSymbolNMTypeChar(ELFObjectFileBase &Obj,
850 basic_symbol_iterator I) {
851 // OK, this is ELF
852 elf_symbol_iterator SymI(I);
853
854 Expected<elf_section_iterator> SecIOrErr = SymI->getSection();
855 if (!SecIOrErr) {
856 consumeError(SecIOrErr.takeError());
857 return '?';
858 }
859
860 uint8_t Binding = SymI->getBinding();
861 if (Binding == ELF::STB_GNU_UNIQUE)
862 return 'u';
863
864 assert(Binding != ELF::STB_WEAK && "STB_WEAK not tested in calling function")(static_cast <bool> (Binding != ELF::STB_WEAK &&
"STB_WEAK not tested in calling function") ? void (0) : __assert_fail
("Binding != ELF::STB_WEAK && \"STB_WEAK not tested in calling function\""
, "llvm/tools/llvm-nm/llvm-nm.cpp", 864, __extension__ __PRETTY_FUNCTION__
))
;
865 if (Binding != ELF::STB_GLOBAL && Binding != ELF::STB_LOCAL)
866 return '?';
867
868 elf_section_iterator SecI = *SecIOrErr;
869 if (SecI != Obj.section_end()) {
870 uint32_t Type = SecI->getType();
871 uint64_t Flags = SecI->getFlags();
872 if (Flags & ELF::SHF_EXECINSTR)
873 return 't';
874 if (Type == ELF::SHT_NOBITS)
875 return 'b';
876 if (Flags & ELF::SHF_ALLOC)
877 return Flags & ELF::SHF_WRITE ? 'd' : 'r';
878
879 auto NameOrErr = SecI->getName();
880 if (!NameOrErr) {
881 consumeError(NameOrErr.takeError());
882 return '?';
883 }
884 if ((*NameOrErr).startswith(".debug"))
885 return 'N';
886 if (!(Flags & ELF::SHF_WRITE))
887 return 'n';
888 }
889
890 return '?';
891}
892
893static char getSymbolNMTypeChar(COFFObjectFile &Obj, symbol_iterator I) {
894 COFFSymbolRef Symb = Obj.getCOFFSymbol(*I);
895 // OK, this is COFF.
896 symbol_iterator SymI(I);
897
898 Expected<StringRef> Name = SymI->getName();
899 if (!Name) {
900 consumeError(Name.takeError());
901 return '?';
902 }
903
904 char Ret = StringSwitch<char>(*Name)
905 .StartsWith(".debug", 'N')
906 .StartsWith(".sxdata", 'N')
907 .Default('?');
908
909 if (Ret != '?')
910 return Ret;
911
912 uint32_t Characteristics = 0;
913 if (!COFF::isReservedSectionNumber(Symb.getSectionNumber())) {
914 Expected<section_iterator> SecIOrErr = SymI->getSection();
915 if (!SecIOrErr) {
916 consumeError(SecIOrErr.takeError());
917 return '?';
918 }
919 section_iterator SecI = *SecIOrErr;
920 const coff_section *Section = Obj.getCOFFSection(*SecI);
921 Characteristics = Section->Characteristics;
922 if (Expected<StringRef> NameOrErr = Obj.getSectionName(Section))
923 if (NameOrErr->startswith(".idata"))
924 return 'i';
925 }
926
927 switch (Symb.getSectionNumber()) {
928 case COFF::IMAGE_SYM_DEBUG:
929 return 'n';
930 default:
931 // Check section type.
932 if (Characteristics & COFF::IMAGE_SCN_CNT_CODE)
933 return 't';
934 if (Characteristics & COFF::IMAGE_SCN_CNT_INITIALIZED_DATA)
935 return Characteristics & COFF::IMAGE_SCN_MEM_WRITE ? 'd' : 'r';
936 if (Characteristics & COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA)
937 return 'b';
938 if (Characteristics & COFF::IMAGE_SCN_LNK_INFO)
939 return 'i';
940 // Check for section symbol.
941 if (Symb.isSectionDefinition())
942 return 's';
943 }
944
945 return '?';
946}
947
948static char getSymbolNMTypeChar(XCOFFObjectFile &Obj, symbol_iterator I) {
949 Expected<uint32_t> TypeOrErr = I->getType();
950 if (!TypeOrErr) {
951 warn(TypeOrErr.takeError(), Obj.getFileName(),
952 "for symbol with index " +
953 Twine(Obj.getSymbolIndex(I->getRawDataRefImpl().p)));
954 return '?';
955 }
956
957 uint32_t SymType = *TypeOrErr;
958
959 if (SymType == SymbolRef::ST_File)
960 return 'f';
961
962 // If the I->getSection() call would return an error, the earlier I->getType()
963 // call will already have returned the same error first.
964 section_iterator SecIter = cantFail(I->getSection());
965
966 if (SecIter == Obj.section_end())
967 return '?';
968
969 if (Obj.isDebugSection(SecIter->getRawDataRefImpl()))
970 return 'N';
971
972 if (SecIter->isText())
973 return 't';
974
975 if (SecIter->isData())
976 return 'd';
977
978 if (SecIter->isBSS())
979 return 'b';
980
981 return '?';
982}
983
984static char getSymbolNMTypeChar(COFFImportFile &Obj) {
985 switch (Obj.getCOFFImportHeader()->getType()) {
986 case COFF::IMPORT_CODE:
987 return 't';
988 case COFF::IMPORT_DATA:
989 return 'd';
990 case COFF::IMPORT_CONST:
991 return 'r';
992 }
993 return '?';
994}
995
996static char getSymbolNMTypeChar(MachOObjectFile &Obj, basic_symbol_iterator I) {
997 DataRefImpl Symb = I->getRawDataRefImpl();
998 uint8_t NType = Obj.is64Bit() ? Obj.getSymbol64TableEntry(Symb).n_type
999 : Obj.getSymbolTableEntry(Symb).n_type;
1000
1001 if (NType & MachO::N_STAB)
1002 return '-';
1003
1004 switch (NType & MachO::N_TYPE) {
1005 case MachO::N_ABS:
1006 return 's';
1007 case MachO::N_INDR:
1008 return 'i';
1009 case MachO::N_SECT: {
1010 Expected<section_iterator> SecOrErr = Obj.getSymbolSection(Symb);
1011 if (!SecOrErr) {
1012 consumeError(SecOrErr.takeError());
1013 return 's';
1014 }
1015 section_iterator Sec = *SecOrErr;
1016 if (Sec == Obj.section_end())
1017 return 's';
1018 DataRefImpl Ref = Sec->getRawDataRefImpl();
1019 StringRef SectionName;
1020 if (Expected<StringRef> NameOrErr = Obj.getSectionName(Ref))
1021 SectionName = *NameOrErr;
1022 StringRef SegmentName = Obj.getSectionFinalSegmentName(Ref);
1023 if (Obj.is64Bit() && Obj.getHeader64().filetype == MachO::MH_KEXT_BUNDLE &&
1024 SegmentName == "__TEXT_EXEC" && SectionName == "__text")
1025 return 't';
1026 if (SegmentName == "__TEXT" && SectionName == "__text")
1027 return 't';
1028 if (SegmentName == "__DATA" && SectionName == "__data")
1029 return 'd';
1030 if (SegmentName == "__DATA" && SectionName == "__bss")
1031 return 'b';
1032 return 's';
1033 }
1034 }
1035
1036 return '?';
1037}
1038
1039static char getSymbolNMTypeChar(TapiFile &Obj, basic_symbol_iterator I) {
1040 return 's';
1041}
1042
1043static char getSymbolNMTypeChar(WasmObjectFile &Obj, basic_symbol_iterator I) {
1044 uint32_t Flags = cantFail(I->getFlags());
1045 if (Flags & SymbolRef::SF_Executable)
1046 return 't';
1047 return 'd';
1048}
1049
1050static char getSymbolNMTypeChar(IRObjectFile &Obj, basic_symbol_iterator I) {
1051 uint32_t Flags = cantFail(I->getFlags());
1052 // FIXME: should we print 'b'? At the IR level we cannot be sure if this
1053 // will be in bss or not, but we could approximate.
1054 if (Flags & SymbolRef::SF_Executable)
1055 return 't';
1056 else if (Triple(Obj.getTargetTriple()).isOSDarwin() &&
1057 (Flags & SymbolRef::SF_Const))
1058 return 's';
1059 else
1060 return 'd';
1061}
1062
1063static bool isObject(SymbolicFile &Obj, basic_symbol_iterator I) {
1064 return isa<ELFObjectFileBase>(&Obj) &&
1065 elf_symbol_iterator(I)->getELFType() == ELF::STT_OBJECT;
1066}
1067
1068// For ELF object files, Set TypeName to the symbol typename, to be printed
1069// in the 'Type' column of the SYSV format output.
1070static StringRef getNMTypeName(SymbolicFile &Obj, basic_symbol_iterator I) {
1071 if (isa<ELFObjectFileBase>(&Obj)) {
1072 elf_symbol_iterator SymI(I);
1073 return SymI->getELFTypeName();
1074 }
1075 return "";
1076}
1077
1078// Return Posix nm class type tag (single letter), but also set SecName and
1079// section and name, to be used in format=sysv output.
1080static char getNMSectionTagAndName(SymbolicFile &Obj, basic_symbol_iterator I,
1081 StringRef &SecName) {
1082 // Symbol Flags have been checked in the caller.
1083 uint32_t Symflags = cantFail(I->getFlags());
1084 if (ELFObjectFileBase *ELFObj = dyn_cast<ELFObjectFileBase>(&Obj)) {
1085 if (Symflags & object::SymbolRef::SF_Absolute)
1086 SecName = "*ABS*";
1087 else if (Symflags & object::SymbolRef::SF_Common)
1088 SecName = "*COM*";
1089 else if (Symflags & object::SymbolRef::SF_Undefined)
1090 SecName = "*UND*";
1091 else {
1092 elf_symbol_iterator SymI(I);
1093 Expected<elf_section_iterator> SecIOrErr = SymI->getSection();
1094 if (!SecIOrErr) {
1095 consumeError(SecIOrErr.takeError());
1096 return '?';
1097 }
1098
1099 if (*SecIOrErr == ELFObj->section_end())
1100 return '?';
1101
1102 Expected<StringRef> NameOrErr = (*SecIOrErr)->getName();
1103 if (!NameOrErr) {
1104 consumeError(NameOrErr.takeError());
1105 return '?';
1106 }
1107 SecName = *NameOrErr;
1108 }
1109 }
1110
1111 if (Symflags & object::SymbolRef::SF_Undefined) {
1112 if (isa<MachOObjectFile>(Obj) || !(Symflags & object::SymbolRef::SF_Weak))
1113 return 'U';
1114 return isObject(Obj, I) ? 'v' : 'w';
1115 }
1116 if (isa<ELFObjectFileBase>(&Obj))
1117 if (ELFSymbolRef(*I).getELFType() == ELF::STT_GNU_IFUNC)
1118 return 'i';
1119 if (!isa<MachOObjectFile>(Obj) && (Symflags & object::SymbolRef::SF_Weak))
1120 return isObject(Obj, I) ? 'V' : 'W';
1121
1122 if (Symflags & object::SymbolRef::SF_Common)
1123 return 'C';
1124
1125 char Ret = '?';
1126 if (Symflags & object::SymbolRef::SF_Absolute)
1127 Ret = 'a';
1128 else if (IRObjectFile *IR = dyn_cast<IRObjectFile>(&Obj))
1129 Ret = getSymbolNMTypeChar(*IR, I);
1130 else if (COFFObjectFile *COFF = dyn_cast<COFFObjectFile>(&Obj))
1131 Ret = getSymbolNMTypeChar(*COFF, I);
1132 else if (XCOFFObjectFile *XCOFF = dyn_cast<XCOFFObjectFile>(&Obj))
1133 Ret = getSymbolNMTypeChar(*XCOFF, I);
1134 else if (COFFImportFile *COFFImport = dyn_cast<COFFImportFile>(&Obj))
1135 Ret = getSymbolNMTypeChar(*COFFImport);
1136 else if (MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(&Obj))
1137 Ret = getSymbolNMTypeChar(*MachO, I);
1138 else if (WasmObjectFile *Wasm = dyn_cast<WasmObjectFile>(&Obj))
1139 Ret = getSymbolNMTypeChar(*Wasm, I);
1140 else if (TapiFile *Tapi = dyn_cast<TapiFile>(&Obj))
1141 Ret = getSymbolNMTypeChar(*Tapi, I);
1142 else if (ELFObjectFileBase *ELF = dyn_cast<ELFObjectFileBase>(&Obj)) {
1143 Ret = getSymbolNMTypeChar(*ELF, I);
1144 if (ELFSymbolRef(*I).getBinding() == ELF::STB_GNU_UNIQUE)
1145 return Ret;
1146 } else
1147 llvm_unreachable("unknown binary format")::llvm::llvm_unreachable_internal("unknown binary format", "llvm/tools/llvm-nm/llvm-nm.cpp"
, 1147)
;
1148
1149 if (!(Symflags & object::SymbolRef::SF_Global))
1150 return Ret;
1151
1152 return toupper(Ret);
1153}
1154
1155// getNsectForSegSect() is used to implement the Mach-O "-s segname sectname"
1156// option to dump only those symbols from that section in a Mach-O file.
1157// It is called once for each Mach-O file from getSymbolNamesFromObject()
1158// to get the section number for that named section from the command line
1159// arguments. It returns the section number for that section in the Mach-O
1160// file or zero it is not present.
1161static unsigned getNsectForSegSect(MachOObjectFile *Obj) {
1162 unsigned Nsect = 1;
1163 for (auto &S : Obj->sections()) {
1164 DataRefImpl Ref = S.getRawDataRefImpl();
1165 StringRef SectionName;
1166 if (Expected<StringRef> NameOrErr = Obj->getSectionName(Ref))
1167 SectionName = *NameOrErr;
1168 StringRef SegmentName = Obj->getSectionFinalSegmentName(Ref);
1169 if (SegmentName == SegSect[0] && SectionName == SegSect[1])
1170 return Nsect;
1171 Nsect++;
1172 }
1173 return 0;
1174}
1175
1176// getNsectInMachO() is used to implement the Mach-O "-s segname sectname"
1177// option to dump only those symbols from that section in a Mach-O file.
1178// It is called once for each symbol in a Mach-O file from
1179// getSymbolNamesFromObject() and returns the section number for that symbol
1180// if it is in a section, else it returns 0.
1181static unsigned getNsectInMachO(MachOObjectFile &Obj, BasicSymbolRef Sym) {
1182 DataRefImpl Symb = Sym.getRawDataRefImpl();
1183 if (Obj.is64Bit()) {
1184 MachO::nlist_64 STE = Obj.getSymbol64TableEntry(Symb);
1185 return (STE.n_type & MachO::N_TYPE) == MachO::N_SECT ? STE.n_sect : 0;
1186 }
1187 MachO::nlist STE = Obj.getSymbolTableEntry(Symb);
1188 return (STE.n_type & MachO::N_TYPE) == MachO::N_SECT ? STE.n_sect : 0;
1189}
1190
1191static void dumpSymbolsFromDLInfoMachO(MachOObjectFile &MachO,
1192 std::vector<NMSymbol> &SymbolList) {
1193 size_t I = SymbolList.size();
1194 std::string ExportsNameBuffer;
1195 raw_string_ostream EOS(ExportsNameBuffer);
1196 std::string BindsNameBuffer;
1197 raw_string_ostream BOS(BindsNameBuffer);
1198 std::string LazysNameBuffer;
1199 raw_string_ostream LOS(LazysNameBuffer);
1200 std::string WeaksNameBuffer;
1201 raw_string_ostream WOS(WeaksNameBuffer);
1202 std::string FunctionStartsNameBuffer;
1203 raw_string_ostream FOS(FunctionStartsNameBuffer);
1204
1205 MachO::mach_header H;
1206 MachO::mach_header_64 H_64;
1207 uint32_t HFlags = 0;
1208 if (MachO.is64Bit()) {
1209 H_64 = MachO.MachOObjectFile::getHeader64();
1210 HFlags = H_64.flags;
1211 } else {
1212 H = MachO.MachOObjectFile::getHeader();
1213 HFlags = H.flags;
1214 }
1215 uint64_t BaseSegmentAddress = 0;
1216 for (const auto &Command : MachO.load_commands()) {
1217 if (Command.C.cmd == MachO::LC_SEGMENT) {
1218 MachO::segment_command Seg = MachO.getSegmentLoadCommand(Command);
1219 if (Seg.fileoff == 0 && Seg.filesize != 0) {
1220 BaseSegmentAddress = Seg.vmaddr;
1221 break;
1222 }
1223 } else if (Command.C.cmd == MachO::LC_SEGMENT_64) {
1224 MachO::segment_command_64 Seg = MachO.getSegment64LoadCommand(Command);
1225 if (Seg.fileoff == 0 && Seg.filesize != 0) {
1226 BaseSegmentAddress = Seg.vmaddr;
1227 break;
1228 }
1229 }
1230 }
1231 if (DyldInfoOnly || AddDyldInfo ||
1232 HFlags & MachO::MH_NLIST_OUTOFSYNC_WITH_DYLDINFO) {
1233 unsigned ExportsAdded = 0;
1234 Error Err = Error::success();
1235 for (const llvm::object::ExportEntry &Entry : MachO.exports(Err)) {
1236 bool found = false;
1237 bool ReExport = false;
1238 if (!DyldInfoOnly) {
1239 for (const NMSymbol &S : SymbolList)
1240 if (S.Address == Entry.address() + BaseSegmentAddress &&
1241 S.Name == Entry.name()) {
1242 found = true;
1243 break;
1244 }
1245 }
1246 if (!found) {
1247 NMSymbol S = {};
1248 S.Address = Entry.address() + BaseSegmentAddress;
1249 S.Size = 0;
1250 S.TypeChar = '\0';
1251 S.Name = Entry.name().str();
1252 // There is no symbol in the nlist symbol table for this so we set
1253 // Sym effectivly to null and the rest of code in here must test for
1254 // it and not do things like Sym.getFlags() for it.
1255 S.Sym = BasicSymbolRef();
1256 S.SymFlags = SymbolRef::SF_Global;
1257 S.Section = SectionRef();
1258 S.NType = 0;
1259 S.NSect = 0;
1260 S.NDesc = 0;
1261
1262 uint64_t EFlags = Entry.flags();
1263 bool Abs = ((EFlags & MachO::EXPORT_SYMBOL_FLAGS_KIND_MASK) ==
1264 MachO::EXPORT_SYMBOL_FLAGS_KIND_ABSOLUTE);
1265 bool Resolver = (EFlags & MachO::EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER);
1266 ReExport = (EFlags & MachO::EXPORT_SYMBOL_FLAGS_REEXPORT);
1267 bool WeakDef = (EFlags & MachO::EXPORT_SYMBOL_FLAGS_WEAK_DEFINITION);
1268 if (WeakDef)
1269 S.NDesc |= MachO::N_WEAK_DEF;
1270 if (Abs) {
1271 S.NType = MachO::N_EXT | MachO::N_ABS;
1272 S.TypeChar = 'A';
1273 } else if (ReExport) {
1274 S.NType = MachO::N_EXT | MachO::N_INDR;
1275 S.TypeChar = 'I';
1276 } else {
1277 S.NType = MachO::N_EXT | MachO::N_SECT;
1278 if (Resolver) {
1279 S.Address = Entry.other() + BaseSegmentAddress;
1280 if ((S.Address & 1) != 0 && !MachO.is64Bit() &&
1281 H.cputype == MachO::CPU_TYPE_ARM) {
1282 S.Address &= ~1LL;
1283 S.NDesc |= MachO::N_ARM_THUMB_DEF;
1284 }
1285 } else {
1286 S.Address = Entry.address() + BaseSegmentAddress;
1287 }
1288 StringRef SegmentName = StringRef();
1289 StringRef SectionName = StringRef();
1290 for (const SectionRef &Section : MachO.sections()) {
1291 S.NSect++;
1292
1293 if (Expected<StringRef> NameOrErr = Section.getName())
1294 SectionName = *NameOrErr;
1295 else
1296 consumeError(NameOrErr.takeError());
1297
1298 SegmentName =
1299 MachO.getSectionFinalSegmentName(Section.getRawDataRefImpl());
1300 if (S.Address >= Section.getAddress() &&
1301 S.Address < Section.getAddress() + Section.getSize()) {
1302 S.Section = Section;
1303 break;
1304 } else if (Entry.name() == "__mh_execute_header" &&
1305 SegmentName == "__TEXT" && SectionName == "__text") {
1306 S.Section = Section;
1307 S.NDesc |= MachO::REFERENCED_DYNAMICALLY;
1308 break;
1309 }
1310 }
1311 if (SegmentName == "__TEXT" && SectionName == "__text")
1312 S.TypeChar = 'T';
1313 else if (SegmentName == "__DATA" && SectionName == "__data")
1314 S.TypeChar = 'D';
1315 else if (SegmentName == "__DATA" && SectionName == "__bss")
1316 S.TypeChar = 'B';
1317 else
1318 S.TypeChar = 'S';
1319 }
1320 SymbolList.push_back(S);
1321
1322 EOS << Entry.name();
1323 EOS << '\0';
1324 ExportsAdded++;
1325
1326 // For ReExports there are a two more things to do, first add the
1327 // indirect name and second create the undefined symbol using the
1328 // referened dynamic library.
1329 if (ReExport) {
1330
1331 // Add the indirect name.
1332 if (Entry.otherName().empty())
1333 EOS << Entry.name();
1334 else
1335 EOS << Entry.otherName();
1336 EOS << '\0';
1337
1338 // Now create the undefined symbol using the referened dynamic
1339 // library.
1340 NMSymbol U = {};
1341 U.Address = 0;
1342 U.Size = 0;
1343 U.TypeChar = 'U';
1344 if (Entry.otherName().empty())
1345 U.Name = Entry.name().str();
1346 else
1347 U.Name = Entry.otherName().str();
1348 // Again there is no symbol in the nlist symbol table for this so
1349 // we set Sym effectivly to null and the rest of code in here must
1350 // test for it and not do things like Sym.getFlags() for it.
1351 U.Sym = BasicSymbolRef();
1352 U.SymFlags = SymbolRef::SF_Global | SymbolRef::SF_Undefined;
1353 U.Section = SectionRef();
1354 U.NType = MachO::N_EXT | MachO::N_UNDF;
1355 U.NSect = 0;
1356 U.NDesc = 0;
1357 // The library ordinal for this undefined symbol is in the export
1358 // trie Entry.other().
1359 MachO::SET_LIBRARY_ORDINAL(U.NDesc, Entry.other());
1360 SymbolList.push_back(U);
1361
1362 // Finally add the undefined symbol's name.
1363 if (Entry.otherName().empty())
1364 EOS << Entry.name();
1365 else
1366 EOS << Entry.otherName();
1367 EOS << '\0';
1368 ExportsAdded++;
1369 }
1370 }
1371 }
1372 if (Err)
1373 error(std::move(Err), MachO.getFileName());
1374 // Set the symbol names and indirect names for the added symbols.
1375 if (ExportsAdded) {
1376 EOS.flush();
1377 const char *Q = ExportsNameBuffer.c_str();
1378 for (unsigned K = 0; K < ExportsAdded; K++) {
1379 SymbolList[I].Name = Q;
1380 Q += strlen(Q) + 1;
1381 if (SymbolList[I].TypeChar == 'I') {
1382 SymbolList[I].IndirectName = Q;
1383 Q += strlen(Q) + 1;
1384 }
1385 I++;
1386 }
1387 }
1388
1389 // Add the undefined symbols from the bind entries.
1390 unsigned BindsAdded = 0;
1391 Error BErr = Error::success();
1392 StringRef LastSymbolName = StringRef();
1393 for (const llvm::object::MachOBindEntry &Entry : MachO.bindTable(BErr)) {
1394 bool found = false;
1395 if (LastSymbolName == Entry.symbolName())
1396 found = true;
1397 else if (!DyldInfoOnly) {
1398 for (unsigned J = 0; J < SymbolList.size() && !found; ++J) {
1399 if (SymbolList[J].Name == Entry.symbolName())
1400 found = true;
1401 }
1402 }
1403 if (!found) {
1404 LastSymbolName = Entry.symbolName();
1405 NMSymbol B = {};
1406 B.Address = 0;
1407 B.Size = 0;
1408 B.TypeChar = 'U';
1409 // There is no symbol in the nlist symbol table for this so we set
1410 // Sym effectivly to null and the rest of code in here must test for
1411 // it and not do things like Sym.getFlags() for it.
1412 B.Sym = BasicSymbolRef();
1413 B.SymFlags = SymbolRef::SF_Global | SymbolRef::SF_Undefined;
1414 B.NType = MachO::N_EXT | MachO::N_UNDF;
1415 B.NSect = 0;
1416 B.NDesc = 0;
1417 MachO::SET_LIBRARY_ORDINAL(B.NDesc, Entry.ordinal());
1418 B.Name = Entry.symbolName().str();
1419 SymbolList.push_back(B);
1420 BOS << Entry.symbolName();
1421 BOS << '\0';
1422 BindsAdded++;
1423 }
1424 }
1425 if (BErr)
1426 error(std::move(BErr), MachO.getFileName());
1427 // Set the symbol names and indirect names for the added symbols.
1428 if (BindsAdded) {
1429 BOS.flush();
1430 const char *Q = BindsNameBuffer.c_str();
1431 for (unsigned K = 0; K < BindsAdded; K++) {
1432 SymbolList[I].Name = Q;
1433 Q += strlen(Q) + 1;
1434 if (SymbolList[I].TypeChar == 'I') {
1435 SymbolList[I].IndirectName = Q;
1436 Q += strlen(Q) + 1;
1437 }
1438 I++;
1439 }
1440 }
1441
1442 // Add the undefined symbols from the lazy bind entries.
1443 unsigned LazysAdded = 0;
1444 Error LErr = Error::success();
1445 LastSymbolName = StringRef();
1446 for (const llvm::object::MachOBindEntry &Entry :
1447 MachO.lazyBindTable(LErr)) {
1448 bool found = false;
1449 if (LastSymbolName == Entry.symbolName())
1450 found = true;
1451 else {
1452 // Here we must check to see it this symbol is already in the
1453 // SymbolList as it might have already have been added above via a
1454 // non-lazy (bind) entry.
1455 for (unsigned J = 0; J < SymbolList.size() && !found; ++J) {
1456 if (SymbolList[J].Name == Entry.symbolName())
1457 found = true;
1458 }
1459 }
1460 if (!found) {
1461 LastSymbolName = Entry.symbolName();
1462 NMSymbol L = {};
1463 L.Name = Entry.symbolName().str();
1464 L.Address = 0;
1465 L.Size = 0;
1466 L.TypeChar = 'U';
1467 // There is no symbol in the nlist symbol table for this so we set
1468 // Sym effectivly to null and the rest of code in here must test for
1469 // it and not do things like Sym.getFlags() for it.
1470 L.Sym = BasicSymbolRef();
1471 L.SymFlags = SymbolRef::SF_Global | SymbolRef::SF_Undefined;
1472 L.NType = MachO::N_EXT | MachO::N_UNDF;
1473 L.NSect = 0;
1474 // The REFERENCE_FLAG_UNDEFINED_LAZY is no longer used but here it
1475 // makes sence since we are creating this from a lazy bind entry.
1476 L.NDesc = MachO::REFERENCE_FLAG_UNDEFINED_LAZY;
1477 MachO::SET_LIBRARY_ORDINAL(L.NDesc, Entry.ordinal());
1478 SymbolList.push_back(L);
1479 LOS << Entry.symbolName();
1480 LOS << '\0';
1481 LazysAdded++;
1482 }
1483 }
1484 if (LErr)
1485 error(std::move(LErr), MachO.getFileName());
1486 // Set the symbol names and indirect names for the added symbols.
1487 if (LazysAdded) {
1488 LOS.flush();
1489 const char *Q = LazysNameBuffer.c_str();
1490 for (unsigned K = 0; K < LazysAdded; K++) {
1491 SymbolList[I].Name = Q;
1492 Q += strlen(Q) + 1;
1493 if (SymbolList[I].TypeChar == 'I') {
1494 SymbolList[I].IndirectName = Q;
1495 Q += strlen(Q) + 1;
1496 }
1497 I++;
1498 }
1499 }
1500
1501 // Add the undefineds symbol from the weak bind entries which are not
1502 // strong symbols.
1503 unsigned WeaksAdded = 0;
1504 Error WErr = Error::success();
1505 LastSymbolName = StringRef();
1506 for (const llvm::object::MachOBindEntry &Entry :
1507 MachO.weakBindTable(WErr)) {
1508 bool found = false;
1509 unsigned J = 0;
1510 if (LastSymbolName == Entry.symbolName() ||
1511 Entry.flags() & MachO::BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION) {
1512 found = true;
1513 } else {
1514 for (J = 0; J < SymbolList.size() && !found; ++J) {
1515 if (SymbolList[J].Name == Entry.symbolName()) {
1516 found = true;
1517 break;
1518 }
1519 }
1520 }
1521 if (!found) {
1522 LastSymbolName = Entry.symbolName();
1523 NMSymbol W = {};
1524 W.Name = Entry.symbolName().str();
1525 W.Address = 0;
1526 W.Size = 0;
1527 W.TypeChar = 'U';
1528 // There is no symbol in the nlist symbol table for this so we set
1529 // Sym effectivly to null and the rest of code in here must test for
1530 // it and not do things like Sym.getFlags() for it.
1531 W.Sym = BasicSymbolRef();
1532 W.SymFlags = SymbolRef::SF_Global | SymbolRef::SF_Undefined;
1533 W.NType = MachO::N_EXT | MachO::N_UNDF;
1534 W.NSect = 0;
1535 // Odd that we are using N_WEAK_DEF on an undefined symbol but that is
1536 // what is created in this case by the linker when there are real
1537 // symbols in the nlist structs.
1538 W.NDesc = MachO::N_WEAK_DEF;
1539 SymbolList.push_back(W);
1540 WOS << Entry.symbolName();
1541 WOS << '\0';
1542 WeaksAdded++;
1543 } else {
1544 // This is the case the symbol was previously been found and it could
1545 // have been added from a bind or lazy bind symbol. If so and not
1546 // a definition also mark it as weak.
1547 if (SymbolList[J].TypeChar == 'U')
1548 // See comment above about N_WEAK_DEF.
1549 SymbolList[J].NDesc |= MachO::N_WEAK_DEF;
1550 }
1551 }
1552 if (WErr)
1553 error(std::move(WErr), MachO.getFileName());
1554 // Set the symbol names and indirect names for the added symbols.
1555 if (WeaksAdded) {
1556 WOS.flush();
1557 const char *Q = WeaksNameBuffer.c_str();
1558 for (unsigned K = 0; K < WeaksAdded; K++) {
1559 SymbolList[I].Name = Q;
1560 Q += strlen(Q) + 1;
1561 if (SymbolList[I].TypeChar == 'I') {
1562 SymbolList[I].IndirectName = Q;
1563 Q += strlen(Q) + 1;
1564 }
1565 I++;
1566 }
1567 }
1568
1569 // Trying adding symbol from the function starts table and LC_MAIN entry
1570 // point.
1571 SmallVector<uint64_t, 8> FoundFns;
1572 uint64_t lc_main_offset = UINT64_MAX(18446744073709551615UL);
1573 for (const auto &Command : MachO.load_commands()) {
1574 if (Command.C.cmd == MachO::LC_FUNCTION_STARTS) {
1575 // We found a function starts segment, parse the addresses for
1576 // consumption.
1577 MachO::linkedit_data_command LLC =
1578 MachO.getLinkeditDataLoadCommand(Command);
1579
1580 MachO.ReadULEB128s(LLC.dataoff, FoundFns);
1581 } else if (Command.C.cmd == MachO::LC_MAIN) {
1582 MachO::entry_point_command LCmain = MachO.getEntryPointCommand(Command);
1583 lc_main_offset = LCmain.entryoff;
1584 }
1585 }
1586 // See if these addresses are already in the symbol table.
1587 unsigned FunctionStartsAdded = 0;
1588 for (uint64_t f = 0; f < FoundFns.size(); f++) {
1589 bool found = false;
1590 for (unsigned J = 0; J < SymbolList.size() && !found; ++J) {
1591 if (SymbolList[J].Address == FoundFns[f] + BaseSegmentAddress)
1592 found = true;
1593 }
1594 // See this address is not already in the symbol table fake up an
1595 // nlist for it.
1596 if (!found) {
1597 NMSymbol F = {};
1598 F.Name = "<redacted function X>";
1599 F.Address = FoundFns[f] + BaseSegmentAddress;
1600 F.Size = 0;
1601 // There is no symbol in the nlist symbol table for this so we set
1602 // Sym effectivly to null and the rest of code in here must test for
1603 // it and not do things like Sym.getFlags() for it.
1604 F.Sym = BasicSymbolRef();
1605 F.SymFlags = 0;
1606 F.NType = MachO::N_SECT;
1607 F.NSect = 0;
1608 StringRef SegmentName = StringRef();
1609 StringRef SectionName = StringRef();
1610 for (const SectionRef &Section : MachO.sections()) {
1611 if (Expected<StringRef> NameOrErr = Section.getName())
1612 SectionName = *NameOrErr;
1613 else
1614 consumeError(NameOrErr.takeError());
1615
1616 SegmentName =
1617 MachO.getSectionFinalSegmentName(Section.getRawDataRefImpl());
1618 F.NSect++;
1619 if (F.Address >= Section.getAddress() &&
1620 F.Address < Section.getAddress() + Section.getSize()) {
1621 F.Section = Section;
1622 break;
1623 }
1624 }
1625 if (SegmentName == "__TEXT" && SectionName == "__text")
1626 F.TypeChar = 't';
1627 else if (SegmentName == "__DATA" && SectionName == "__data")
1628 F.TypeChar = 'd';
1629 else if (SegmentName == "__DATA" && SectionName == "__bss")
1630 F.TypeChar = 'b';
1631 else
1632 F.TypeChar = 's';
1633 F.NDesc = 0;
1634 SymbolList.push_back(F);
1635 if (FoundFns[f] == lc_main_offset)
1636 FOS << "<redacted LC_MAIN>";
1637 else
1638 FOS << "<redacted function " << f << ">";
1639 FOS << '\0';
1640 FunctionStartsAdded++;
1641 }
1642 }
1643 if (FunctionStartsAdded) {
1644 FOS.flush();
1645 const char *Q = FunctionStartsNameBuffer.c_str();
1646 for (unsigned K = 0; K < FunctionStartsAdded; K++) {
1647 SymbolList[I].Name = Q;
1648 Q += strlen(Q) + 1;
1649 if (SymbolList[I].TypeChar == 'I') {
1650 SymbolList[I].IndirectName = Q;
1651 Q += strlen(Q) + 1;
1652 }
1653 I++;
1654 }
1655 }
1656 }
1657}
1658
1659static bool shouldDump(SymbolicFile &Obj) {
1660 // The -X option is currently only implemented for XCOFF, ELF, and IR object
1661 // files. The option isn't fundamentally impossible with other formats, just
1662 // isn't implemented.
1663 if (!isa<XCOFFObjectFile>(Obj) && !isa<ELFObjectFileBase>(Obj) &&
1664 !isa<IRObjectFile>(Obj))
1665 return true;
1666
1667 return isSymbolList64Bit(Obj) ? BitMode != BitModeTy::Bit32
1668 : BitMode != BitModeTy::Bit64;
1669}
1670
1671static void getXCOFFExports(XCOFFObjectFile *XCOFFObj,
1672 std::vector<NMSymbol> &SymbolList,
1673 StringRef ArchiveName) {
1674 // Skip Shared object file.
1675 if (XCOFFObj->getFlags() & XCOFF::F_SHROBJ)
1676 return;
1677
1678 for (SymbolRef Sym : XCOFFObj->symbols()) {
1679 // There is no visibility in old 32 bit XCOFF object file interpret.
1680 bool HasVisibilityAttr =
1681 XCOFFObj->is64Bit() || (XCOFFObj->auxiliaryHeader32() &&
1682 (XCOFFObj->auxiliaryHeader32()->getVersion() ==
1683 XCOFF::NEW_XCOFF_INTERPRET));
1684
1685 if (HasVisibilityAttr) {
1686 XCOFFSymbolRef XCOFFSym = XCOFFObj->toSymbolRef(Sym.getRawDataRefImpl());
1687 uint16_t SymType = XCOFFSym.getSymbolType();
1688 if ((SymType & XCOFF::VISIBILITY_MASK) == XCOFF::SYM_V_INTERNAL)
1689 continue;
1690 if ((SymType & XCOFF::VISIBILITY_MASK) == XCOFF::SYM_V_HIDDEN)
1691 continue;
1692 }
1693
1694 Expected<section_iterator> SymSecOrErr = Sym.getSection();
1695 if (!SymSecOrErr) {
1696 warn(SymSecOrErr.takeError(), XCOFFObj->getFileName(),
1697 "for symbol with index " +
1698 Twine(XCOFFObj->getSymbolIndex(Sym.getRawDataRefImpl().p)),
1699 ArchiveName);
1700 continue;
1701 }
1702 section_iterator SecIter = *SymSecOrErr;
1703 // If the symbol is not in a text or data section, it is not exported.
1704 if (SecIter == XCOFFObj->section_end())
1705 continue;
1706 if (!(SecIter->isText() || SecIter->isData() || SecIter->isBSS()))
1707 continue;
1708
1709 StringRef SymName = cantFail(Sym.getName());
1710 if (SymName.empty())
1711 continue;
1712 if (SymName.startswith("__sinit") || SymName.startswith("__sterm") ||
1713 SymName.front() == '.' || SymName.front() == '(')
1714 continue;
1715
1716 // Check the SymName regex matching with "^__[0-9]+__".
1717 if (SymName.size() > 4 && SymName.startswith("__") &&
1718 SymName.endswith("__")) {
1719 if (std::all_of(SymName.begin() + 2, SymName.end() - 2, isDigit))
1720 continue;
1721 }
1722
1723 if (SymName == "__rsrc" && NoRsrc)
1724 continue;
1725
1726 if (SymName.startswith("__tf1"))
1727 SymName = SymName.substr(6);
1728 else if (SymName.startswith("__tf9"))
1729 SymName = SymName.substr(14);
1730
1731 NMSymbol S = {};
1732 S.Name = SymName.str();
1733 S.Sym = Sym;
1734
1735 if (HasVisibilityAttr) {
1736 XCOFFSymbolRef XCOFFSym = XCOFFObj->toSymbolRef(Sym.getRawDataRefImpl());
1737 uint16_t SymType = XCOFFSym.getSymbolType();
1738 if ((SymType & XCOFF::VISIBILITY_MASK) == XCOFF::SYM_V_PROTECTED)
1739 S.Visibility = "protected";
1740 else if ((SymType & XCOFF::VISIBILITY_MASK) == XCOFF::SYM_V_EXPORTED)
1741 S.Visibility = "export";
1742 }
1743 if (S.initializeFlags(*XCOFFObj))
1744 SymbolList.push_back(S);
1745 }
1746}
1747
1748static Expected<SymbolicFile::basic_symbol_iterator_range>
1749getDynamicSyms(SymbolicFile &Obj) {
1750 const auto *E = dyn_cast<ELFObjectFileBase>(&Obj);
1751 if (!E)
1752 return createError("File format has no dynamic symbol table");
1753 return E->getDynamicSymbolIterators();
1754}
1755
1756// Returns false if there is error found or true otherwise.
1757static bool getSymbolNamesFromObject(SymbolicFile &Obj,
1758 std::vector<NMSymbol> &SymbolList) {
1759 auto Symbols = Obj.symbols();
1760 std::vector<VersionEntry> SymbolVersions;
1761
1762 if (DynamicSyms) {
1763 Expected<SymbolicFile::basic_symbol_iterator_range> SymbolsOrErr =
1764 getDynamicSyms(Obj);
1765 if (!SymbolsOrErr) {
1766 error(SymbolsOrErr.takeError(), Obj.getFileName());
1767 return false;
1768 }
1769 Symbols = *SymbolsOrErr;
1770 if (const auto *E = dyn_cast<ELFObjectFileBase>(&Obj)) {
1771 if (Expected<std::vector<VersionEntry>> VersionsOrErr =
1772 E->readDynsymVersions())
1773 SymbolVersions = std::move(*VersionsOrErr);
1774 else
1775 WithColor::warning(errs(), ToolName)
1776 << "unable to read symbol versions: "
1777 << toString(VersionsOrErr.takeError()) << "\n";
1778 }
1779 }
1780 // If a "-s segname sectname" option was specified and this is a Mach-O
1781 // file get the section number for that section in this object file.
1782 unsigned int Nsect = 0;
1783 MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(&Obj);
1784 if (!SegSect.empty() && MachO) {
1785 Nsect = getNsectForSegSect(MachO);
1786 // If this section is not in the object file no symbols are printed.
1787 if (Nsect == 0)
1788 return false;
1789 }
1790
1791 if (!(MachO && DyldInfoOnly)) {
1792 size_t I = -1;
1793 for (BasicSymbolRef Sym : Symbols) {
1794 ++I;
1795 Expected<uint32_t> SymFlagsOrErr = Sym.getFlags();
1796 if (!SymFlagsOrErr) {
1797 error(SymFlagsOrErr.takeError(), Obj.getFileName());
1798 return false;
1799 }
1800
1801 // Don't drop format specifc symbols for ARM and AArch64 ELF targets, they
1802 // are used to repesent mapping symbols and needed to honor the
1803 // --special-syms option.
1804 auto *ELFObj = dyn_cast<ELFObjectFileBase>(&Obj);
1805 if ((!ELFObj || (ELFObj->getEMachine() != ELF::EM_ARM &&
1806 ELFObj->getEMachine() != ELF::EM_AARCH64)) &&
1807 !DebugSyms && (*SymFlagsOrErr & SymbolRef::SF_FormatSpecific))
1808 continue;
1809 if (WithoutAliases && (*SymFlagsOrErr & SymbolRef::SF_Indirect))
1810 continue;
1811 // If a "-s segname sectname" option was specified and this is a Mach-O
1812 // file and this section appears in this file, Nsect will be non-zero then
1813 // see if this symbol is a symbol from that section and if not skip it.
1814 if (Nsect && Nsect != getNsectInMachO(*MachO, Sym))
1815 continue;
1816 NMSymbol S = {};
1817 S.Size = 0;
1818 S.Address = 0;
1819 if (isa<ELFObjectFileBase>(&Obj))
1820 S.Size = ELFSymbolRef(Sym).getSize();
1821
1822 if (const XCOFFObjectFile *XCOFFObj =
1823 dyn_cast<const XCOFFObjectFile>(&Obj))
1824 S.Size = XCOFFObj->getSymbolSize(Sym.getRawDataRefImpl());
1825
1826 if (PrintAddress && isa<ObjectFile>(Obj)) {
1827 SymbolRef SymRef(Sym);
1828 Expected<uint64_t> AddressOrErr = SymRef.getAddress();
1829 if (!AddressOrErr) {
1830 consumeError(AddressOrErr.takeError());
1831 break;
1832 }
1833 S.Address = *AddressOrErr;
1834 }
1835 S.TypeName = getNMTypeName(Obj, Sym);
1836 S.TypeChar = getNMSectionTagAndName(Obj, Sym, S.SectionName);
1837
1838 raw_string_ostream OS(S.Name);
1839 if (Error E = Sym.printName(OS)) {
1840 if (MachO) {
1841 OS << "bad string index";
1842 consumeError(std::move(E));
1843 } else
1844 error(std::move(E), Obj.getFileName());
1845 }
1846 if (!SymbolVersions.empty() && !SymbolVersions[I].Name.empty())
1847 S.Name +=
1848 (SymbolVersions[I].IsVerDef ? "@@" : "@") + SymbolVersions[I].Name;
1849
1850 S.Sym = Sym;
1851 if (S.initializeFlags(Obj))
1852 SymbolList.push_back(S);
1853 }
1854 }
1855
1856 // If this is a Mach-O file where the nlist symbol table is out of sync
1857 // with the dyld export trie then look through exports and fake up symbols
1858 // for the ones that are missing (also done with the -add-dyldinfo flag).
1859 // This is needed if strip(1) -T is run on a binary containing swift
1860 // language symbols for example. The option -only-dyldinfo will fake up
1861 // all symbols from the dyld export trie as well as the bind info.
1862 if (MachO && !NoDyldInfo)
1863 dumpSymbolsFromDLInfoMachO(*MachO, SymbolList);
1864
1865 return true;
1866}
1867
1868static void printObjectLabel(bool PrintArchiveName, StringRef ArchiveName,
1869 StringRef ArchitectureName,
1870 StringRef ObjectFileName) {
1871 outs() << "\n";
1872 if (ArchiveName.empty() || !PrintArchiveName)
1873 outs() << ObjectFileName;
1874 else
1875 outs() << ArchiveName << "(" << ObjectFileName << ")";
1876 if (!ArchitectureName.empty())
1877 outs() << " (for architecture " << ArchitectureName << ")";
1878 outs() << ":\n";
1879}
1880
1881static Expected<bool> hasSymbols(SymbolicFile &Obj) {
1882 if (DynamicSyms) {
1883 Expected<SymbolicFile::basic_symbol_iterator_range> DynamicSymsOrErr =
1884 getDynamicSyms(Obj);
1885 if (!DynamicSymsOrErr)
1886 return DynamicSymsOrErr.takeError();
1887 return !DynamicSymsOrErr->empty();
1888 }
1889 return !Obj.symbols().empty();
1890}
1891
1892static void dumpSymbolNamesFromObject(
1893 SymbolicFile &Obj, std::vector<NMSymbol> &SymbolList,
1894 bool PrintSymbolObject, bool PrintObjectLabel, StringRef ArchiveName = {},
1895 StringRef ArchitectureName = {}, StringRef ObjectName = {},
1896 bool PrintArchiveName = true) {
1897 if (!shouldDump(Obj))
1898 return;
1899
1900 if (ExportSymbols && Obj.isXCOFF()) {
1901 XCOFFObjectFile *XCOFFObj = cast<XCOFFObjectFile>(&Obj);
1902 getXCOFFExports(XCOFFObj, SymbolList, ArchiveName);
1903 return;
1904 }
1905
1906 if (PrintObjectLabel && !ExportSymbols)
1907 printObjectLabel(PrintArchiveName, ArchiveName, ArchitectureName,
1908 ObjectName.empty() ? Obj.getFileName() : ObjectName);
1909 if (!getSymbolNamesFromObject(Obj, SymbolList) || ExportSymbols)
1910 return;
1911 CurrentFilename = Obj.getFileName();
1912
1913 // If there is an error in hasSymbols(), the error should be encountered in
1914 // function getSymbolNamesFromObject first.
1915 if (!cantFail(hasSymbols(Obj)) && SymbolList.empty() && !Quiet) {
1916 writeFileName(errs(), ArchiveName, ArchitectureName);
1917 errs() << "no symbols\n";
1918 }
1919
1920 sortSymbolList(SymbolList);
1921 printSymbolList(Obj, SymbolList, PrintSymbolObject, ArchiveName,
1922 ArchitectureName);
1923}
1924
1925// checkMachOAndArchFlags() checks to see if the SymbolicFile is a Mach-O file
1926// and if it is and there is a list of architecture flags is specified then
1927// check to make sure this Mach-O file is one of those architectures or all
1928// architectures was specificed. If not then an error is generated and this
1929// routine returns false. Else it returns true.
1930static bool checkMachOAndArchFlags(SymbolicFile *O, StringRef Filename) {
1931 auto *MachO = dyn_cast<MachOObjectFile>(O);
1932
1933 if (!MachO || ArchAll || ArchFlags.empty())
1934 return true;
1935
1936 MachO::mach_header H;
1937 MachO::mach_header_64 H_64;
1938 Triple T;
1939 const char *McpuDefault, *ArchFlag;
1940 if (MachO->is64Bit()) {
1941 H_64 = MachO->MachOObjectFile::getHeader64();
1942 T = MachOObjectFile::getArchTriple(H_64.cputype, H_64.cpusubtype,
1943 &McpuDefault, &ArchFlag);
1944 } else {
1945 H = MachO->MachOObjectFile::getHeader();
1946 T = MachOObjectFile::getArchTriple(H.cputype, H.cpusubtype,
1947 &McpuDefault, &ArchFlag);
1948 }
1949 const std::string ArchFlagName(ArchFlag);
1950 if (!llvm::is_contained(ArchFlags, ArchFlagName)) {
1951 error("No architecture specified", Filename);
1952 return false;
1953 }
1954 return true;
1955}
1956
1957static void dumpArchiveMap(Archive *A, StringRef Filename) {
1958 Archive::symbol_iterator I = A->symbol_begin();
1959 Archive::symbol_iterator E = A->symbol_end();
1960 if (I != E) {
1961 outs() << "Archive map\n";
1962 for (; I != E; ++I) {
1963 Expected<Archive::Child> C = I->getMember();
1964 if (!C) {
1965 error(C.takeError(), Filename);
1966 break;
1967 }
1968 Expected<StringRef> FileNameOrErr = C->getName();
1969 if (!FileNameOrErr) {
1970 error(FileNameOrErr.takeError(), Filename);
1971 break;
1972 }
1973 StringRef SymName = I->getName();
1974 outs() << SymName << " in " << FileNameOrErr.get() << "\n";
1975 }
1976 outs() << "\n";
1977 }
1978}
1979
1980static void dumpArchive(Archive *A, std::vector<NMSymbol> &SymbolList,
1981 StringRef Filename, LLVMContext *ContextPtr) {
1982 if (ArchiveMap)
1983 dumpArchiveMap(A, Filename);
1984
1985 Error Err = Error::success();
1986 for (auto &C : A->children(Err)) {
1987 Expected<std::unique_ptr<Binary>> ChildOrErr = C.getAsBinary(ContextPtr);
1988 if (!ChildOrErr) {
1989 if (auto E = isNotObjectErrorInvalidFileType(ChildOrErr.takeError()))
1990 error(std::move(E), Filename, C);
1991 continue;
1992 }
1993 if (SymbolicFile *O = dyn_cast<SymbolicFile>(&*ChildOrErr.get())) {
1994 if (!MachOPrintSizeWarning && PrintSize && isa<MachOObjectFile>(O)) {
1995 WithColor::warning(errs(), ToolName)
1996 << "sizes with -print-size for Mach-O files are always zero.\n";
1997 MachOPrintSizeWarning = true;
1998 }
1999 if (!checkMachOAndArchFlags(O, Filename))
2000 return;
2001 dumpSymbolNamesFromObject(*O, SymbolList, /*PrintSymbolObject=*/false,
2002 !PrintFileName, Filename,
2003 /*ArchitectureName=*/{}, O->getFileName(),
2004 /*PrintArchiveName=*/false);
2005 }
2006 }
2007 if (Err)
2008 error(std::move(Err), A->getFileName());
2009}
2010
2011static void dumpMachOUniversalBinaryMatchArchFlags(
2012 MachOUniversalBinary *UB, std::vector<NMSymbol> &SymbolList,
2013 StringRef Filename, LLVMContext *ContextPtr) {
2014 // Look for a slice in the universal binary that matches each ArchFlag.
2015 bool ArchFound;
2016 for (unsigned i = 0; i < ArchFlags.size(); ++i) {
2017 ArchFound = false;
2018 for (MachOUniversalBinary::object_iterator I = UB->begin_objects(),
2019 E = UB->end_objects();
2020 I != E; ++I) {
2021 if (ArchFlags[i] == I->getArchFlagName()) {
2022 ArchFound = true;
2023 Expected<std::unique_ptr<ObjectFile>> ObjOrErr = I->getAsObjectFile();
2024 std::string ArchiveName;
2025 std::string ArchitectureName;
2026 ArchiveName.clear();
2027 ArchitectureName.clear();
2028 if (ObjOrErr) {
2029 ObjectFile &Obj = *ObjOrErr.get();
2030 if (ArchFlags.size() > 1)
2031 ArchitectureName = I->getArchFlagName();
2032 dumpSymbolNamesFromObject(Obj, SymbolList,
2033 /*PrintSymbolObject=*/false,
2034 (ArchFlags.size() > 1) && !PrintFileName,
2035 ArchiveName, ArchitectureName);
2036 } else if (auto E =
2037 isNotObjectErrorInvalidFileType(ObjOrErr.takeError())) {
2038 error(std::move(E), Filename,
2039 ArchFlags.size() > 1 ? StringRef(I->getArchFlagName())
2040 : StringRef());
2041 continue;
2042 } else if (Expected<std::unique_ptr<Archive>> AOrErr =
2043 I->getAsArchive()) {
2044 std::unique_ptr<Archive> &A = *AOrErr;
2045 Error Err = Error::success();
2046 for (auto &C : A->children(Err)) {
2047 Expected<std::unique_ptr<Binary>> ChildOrErr =
2048 C.getAsBinary(ContextPtr);
2049 if (!ChildOrErr) {
2050 if (auto E =
2051 isNotObjectErrorInvalidFileType(ChildOrErr.takeError())) {
2052 error(std::move(E), Filename, C,
2053 ArchFlags.size() > 1 ? StringRef(I->getArchFlagName())
2054 : StringRef());
2055 }
2056 continue;
2057 }
2058 if (SymbolicFile *O = dyn_cast<SymbolicFile>(&*ChildOrErr.get())) {
2059 ArchiveName = std::string(A->getFileName());
2060 if (ArchFlags.size() > 1)
2061 ArchitectureName = I->getArchFlagName();
2062 dumpSymbolNamesFromObject(
2063 *O, SymbolList, /*PrintSymbolObject=*/false, !PrintFileName,
2064 ArchiveName, ArchitectureName);
2065 }
2066 }
2067 if (Err)
2068 error(std::move(Err), A->getFileName());
2069 } else {
2070 consumeError(AOrErr.takeError());
2071 error(Filename + " for architecture " +
2072 StringRef(I->getArchFlagName()) +
2073 " is not a Mach-O file or an archive file",
2074 "Mach-O universal file");
2075 }
2076 }
2077 }
2078 if (!ArchFound) {
2079 error(ArchFlags[i],
2080 "file: " + Filename + " does not contain architecture");
2081 return;
2082 }
2083 }
2084}
2085
2086// Returns true If the binary contains a slice that matches the host
2087// architecture, or false otherwise.
2088static bool dumpMachOUniversalBinaryMatchHost(MachOUniversalBinary *UB,
2089 std::vector<NMSymbol> &SymbolList,
2090 StringRef Filename,
2091 LLVMContext *ContextPtr) {
2092 Triple HostTriple = MachOObjectFile::getHostArch();
2093 StringRef HostArchName = HostTriple.getArchName();
2094 for (MachOUniversalBinary::object_iterator I = UB->begin_objects(),
2095 E = UB->end_objects();
2096 I != E; ++I) {
2097 if (HostArchName == I->getArchFlagName()) {
2098 Expected<std::unique_ptr<ObjectFile>> ObjOrErr = I->getAsObjectFile();
2099 std::string ArchiveName;
2100 if (ObjOrErr) {
2101 ObjectFile &Obj = *ObjOrErr.get();
2102 dumpSymbolNamesFromObject(Obj, SymbolList, /*PrintSymbolObject=*/false,
2103 /*PrintObjectLabel=*/false);
2104 } else if (auto E = isNotObjectErrorInvalidFileType(ObjOrErr.takeError()))
2105 error(std::move(E), Filename);
2106 else if (Expected<std::unique_ptr<Archive>> AOrErr = I->getAsArchive()) {
2107 std::unique_ptr<Archive> &A = *AOrErr;
2108 Error Err = Error::success();
2109 for (auto &C : A->children(Err)) {
2110 Expected<std::unique_ptr<Binary>> ChildOrErr =
2111 C.getAsBinary(ContextPtr);
2112 if (!ChildOrErr) {
2113 if (auto E =
2114 isNotObjectErrorInvalidFileType(ChildOrErr.takeError()))
2115 error(std::move(E), Filename, C);
2116 continue;
2117 }
2118 if (SymbolicFile *O = dyn_cast<SymbolicFile>(&*ChildOrErr.get())) {
2119 ArchiveName = std::string(A->getFileName());
2120 dumpSymbolNamesFromObject(*O, SymbolList,
2121 /*PrintSymbolObject=*/false,
2122 !PrintFileName, ArchiveName);
2123 }
2124 }
2125 if (Err)
2126 error(std::move(Err), A->getFileName());
2127 } else {
2128 consumeError(AOrErr.takeError());
2129 error(Filename + " for architecture " +
2130 StringRef(I->getArchFlagName()) +
2131 " is not a Mach-O file or an archive file",
2132 "Mach-O universal file");
2133 }
2134 return true;
2135 }
2136 }
2137 return false;
2138}
2139
2140static void dumpMachOUniversalBinaryArchAll(MachOUniversalBinary *UB,
2141 std::vector<NMSymbol> &SymbolList,
2142 StringRef Filename,
2143 LLVMContext *ContextPtr) {
2144 bool moreThanOneArch = UB->getNumberOfObjects() > 1;
2145 for (const MachOUniversalBinary::ObjectForArch &O : UB->objects()) {
2146 Expected<std::unique_ptr<ObjectFile>> ObjOrErr = O.getAsObjectFile();
2147 std::string ArchiveName;
2148 std::string ArchitectureName;
2149 ArchiveName.clear();
2150 ArchitectureName.clear();
2151 if (ObjOrErr) {
2152 ObjectFile &Obj = *ObjOrErr.get();
2153 if (isa<MachOObjectFile>(Obj) && moreThanOneArch)
2154 ArchitectureName = O.getArchFlagName();
2155 dumpSymbolNamesFromObject(Obj, SymbolList, /*PrintSymbolObject=*/false,
2156 !PrintFileName, ArchiveName, ArchitectureName);
2157 } else if (auto E = isNotObjectErrorInvalidFileType(ObjOrErr.takeError())) {
2158 error(std::move(E), Filename,
2159 moreThanOneArch ? StringRef(O.getArchFlagName()) : StringRef());
2160 continue;
2161 } else if (Expected<std::unique_ptr<Archive>> AOrErr = O.getAsArchive()) {
2162 std::unique_ptr<Archive> &A = *AOrErr;
2163 Error Err = Error::success();
2164 for (auto &C : A->children(Err)) {
2165 Expected<std::unique_ptr<Binary>> ChildOrErr =
2166 C.getAsBinary(ContextPtr);
2167 if (!ChildOrErr) {
2168 if (auto E = isNotObjectErrorInvalidFileType(ChildOrErr.takeError()))
2169 error(std::move(E), Filename, C,
2170 moreThanOneArch ? StringRef(ArchitectureName) : StringRef());
2171 continue;
2172 }
2173 if (SymbolicFile *F = dyn_cast<SymbolicFile>(&*ChildOrErr.get())) {
2174 ArchiveName = std::string(A->getFileName());
2175 if (isa<MachOObjectFile>(F) && moreThanOneArch)
2176 ArchitectureName = O.getArchFlagName();
2177 dumpSymbolNamesFromObject(*F, SymbolList, /*PrintSymbolObject=*/false,
2178 !PrintFileName, ArchiveName,
2179 ArchitectureName);
2180 }
2181 }
2182 if (Err)
2183 error(std::move(Err), A->getFileName());
2184 } else {
2185 consumeError(AOrErr.takeError());
2186 error(Filename + " for architecture " + StringRef(O.getArchFlagName()) +
2187 " is not a Mach-O file or an archive file",
2188 "Mach-O universal file");
2189 }
2190 }
2191}
2192
2193static void dumpMachOUniversalBinary(MachOUniversalBinary *UB,
2194 std::vector<NMSymbol> &SymbolList,
2195 StringRef Filename,
2196 LLVMContext *ContextPtr) {
2197 // If we have a list of architecture flags specified dump only those.
2198 if (!ArchAll && !ArchFlags.empty()) {
2199 dumpMachOUniversalBinaryMatchArchFlags(UB, SymbolList, Filename,
2200 ContextPtr);
2201 return;
2202 }
2203
2204 // No architecture flags were specified so if this contains a slice that
2205 // matches the host architecture dump only that.
2206 if (!ArchAll &&
2207 dumpMachOUniversalBinaryMatchHost(UB, SymbolList, Filename, ContextPtr))
2208 return;
2209
2210 // Either all architectures have been specified or none have been specified
2211 // and this does not contain the host architecture so dump all the slices.
2212 dumpMachOUniversalBinaryArchAll(UB, SymbolList, Filename, ContextPtr);
2213}
2214
2215static void dumpTapiUniversal(TapiUniversal *TU,
2216 std::vector<NMSymbol> &SymbolList,
2217 StringRef Filename) {
2218 for (const TapiUniversal::ObjectForArch &I : TU->objects()) {
2219 StringRef ArchName = I.getArchFlagName();
2220 const bool ShowArch =
2221 ArchFlags.empty() || llvm::is_contained(ArchFlags, ArchName);
2222 if (!ShowArch)
2223 continue;
2224 if (!AddInlinedInfo && !I.isTopLevelLib())
2225 continue;
2226 if (auto ObjOrErr = I.getAsObjectFile())
2227 dumpSymbolNamesFromObject(
2228 *ObjOrErr.get(), SymbolList, /*PrintSymbolObject=*/false,
2229 /*PrintObjectLabel=*/true,
2230 /*ArchiveName=*/{}, ArchName, I.getInstallName());
2231 else if (Error E = isNotObjectErrorInvalidFileType(ObjOrErr.takeError())) {
2232 error(std::move(E), Filename, ArchName);
2233 }
2234 }
2235}
2236
2237static void dumpSymbolicFile(SymbolicFile *O, std::vector<NMSymbol> &SymbolList,
2238 StringRef Filename) {
2239 if (!MachOPrintSizeWarning && PrintSize && isa<MachOObjectFile>(O)) {
2240 WithColor::warning(errs(), ToolName)
2241 << "sizes with --print-size for Mach-O files are always zero.\n";
2242 MachOPrintSizeWarning = true;
2243 }
2244 if (!checkMachOAndArchFlags(O, Filename))
2245 return;
2246 dumpSymbolNamesFromObject(*O, SymbolList, /*PrintSymbolObject=*/true,
2247 /*PrintObjectLabel=*/false);
2248}
2249
2250static std::vector<NMSymbol> dumpSymbolNamesFromFile(StringRef Filename) {
2251 std::vector<NMSymbol> SymbolList;
2252 ErrorOr<std::unique_ptr<MemoryBuffer>> BufferOrErr =
2253 MemoryBuffer::getFileOrSTDIN(Filename);
2254 if (error(BufferOrErr.getError(), Filename))
2255 return SymbolList;
2256
2257 LLVMContext Context;
2258 LLVMContext *ContextPtr = NoLLVMBitcode ? nullptr : &Context;
2259 Expected<std::unique_ptr<Binary>> BinaryOrErr =
2260 createBinary(BufferOrErr.get()->getMemBufferRef(), ContextPtr);
2261 if (!BinaryOrErr) {
2262 error(BinaryOrErr.takeError(), Filename);
2263 return SymbolList;
2264 }
2265 Binary &Bin = *BinaryOrErr.get();
2266 if (Archive *A = dyn_cast<Archive>(&Bin))
2267 dumpArchive(A, SymbolList, Filename, ContextPtr);
2268 else if (MachOUniversalBinary *UB = dyn_cast<MachOUniversalBinary>(&Bin))
2269 dumpMachOUniversalBinary(UB, SymbolList, Filename, ContextPtr);
2270 else if (TapiUniversal *TU = dyn_cast<TapiUniversal>(&Bin))
2271 dumpTapiUniversal(TU, SymbolList, Filename);
2272 else if (SymbolicFile *O = dyn_cast<SymbolicFile>(&Bin))
2273 dumpSymbolicFile(O, SymbolList, Filename);
2274 return SymbolList;
2275}
2276
2277static void
2278exportSymbolNamesFromFiles(const std::vector<std::string> &InputFilenames) {
2279 std::vector<NMSymbol> SymbolList;
2280 for (const auto &FileName : InputFilenames) {
2281 std::vector<NMSymbol> FileSymList = dumpSymbolNamesFromFile(FileName);
2282 SymbolList.insert(SymbolList.end(), FileSymList.begin(), FileSymList.end());
2283 }
2284
2285 // Delete symbols which should not be printed from SymolList.
2286 SymbolList.erase(
2287 llvm::remove_if(SymbolList,
2288 [](const NMSymbol &s) { return !s.shouldPrint(); }),
2289 SymbolList.end());
2290 sortSymbolList(SymbolList);
2291 SymbolList.erase(std::unique(SymbolList.begin(), SymbolList.end()),
2292 SymbolList.end());
2293 printExportSymbolList(SymbolList);
2294}
2295
2296int main(int argc, char **argv) {
2297 InitLLVM X(argc, argv);
2298 BumpPtrAllocator A;
2299 StringSaver Saver(A);
2300 NmOptTable Tbl;
2301 ToolName = argv[0];
2302 opt::InputArgList Args =
2303 Tbl.parseArgs(argc, argv, OPT_UNKNOWN, Saver, [&](StringRef Msg) {
2304 error(Msg);
2305 exit(1);
2306 });
2307 if (Args.hasArg(OPT_help)) {
2308 Tbl.printHelp(
2309 outs(),
2310 (Twine(ToolName) + " [options] <input object files>").str().c_str(),
2311 "LLVM symbol table dumper");
2312 // TODO Replace this with OptTable API once it adds extrahelp support.
2313 outs() << "\nPass @FILE as argument to read options from FILE.\n";
2314 return 0;
2315 }
2316 if (Args.hasArg(OPT_version)) {
2317 // This needs to contain the word "GNU", libtool looks for that string.
2318 outs() << "llvm-nm, compatible with GNU nm" << '\n';
2319 cl::PrintVersionMessage();
2320 return 0;
2321 }
2322
2323 DebugSyms = Args.hasArg(OPT_debug_syms);
2324 DefinedOnly = Args.hasArg(OPT_defined_only);
2325 Demangle = Args.hasFlag(OPT_demangle, OPT_no_demangle, false);
2326 DynamicSyms = Args.hasArg(OPT_dynamic);
2327 ExternalOnly = Args.hasArg(OPT_extern_only);
2328 StringRef V = Args.getLastArgValue(OPT_format_EQ, "bsd");
2329 if (V == "bsd")
2330 OutputFormat = bsd;
2331 else if (V == "posix")
2332 OutputFormat = posix;
2333 else if (V == "sysv")
2334 OutputFormat = sysv;
2335 else if (V == "darwin")
2336 OutputFormat = darwin;
2337 else if (V == "just-symbols")
2338 OutputFormat = just_symbols;
2339 else
2340 error("--format value should be one of: bsd, posix, sysv, darwin, "
2341 "just-symbols");
2342 NoLLVMBitcode = Args.hasArg(OPT_no_llvm_bc);
2343 NoSort = Args.hasArg(OPT_no_sort);
2344 NoWeakSymbols = Args.hasArg(OPT_no_weak);
2345 NumericSort = Args.hasArg(OPT_numeric_sort);
2346 ArchiveMap = Args.hasArg(OPT_print_armap);
2347 PrintFileName = Args.hasArg(OPT_print_file_name);
2348 PrintSize = Args.hasArg(OPT_print_size);
2349 ReverseSort = Args.hasArg(OPT_reverse_sort);
2350 ExportSymbols = Args.hasArg(OPT_export_symbols);
2351 if (ExportSymbols) {
2352 ExternalOnly = true;
2353 DefinedOnly = true;
2354 }
2355
2356 Quiet = Args.hasArg(OPT_quiet);
2357 V = Args.getLastArgValue(OPT_radix_EQ, "x");
2358 if (V == "o")
2359 AddressRadix = Radix::o;
2360 else if (V == "d")
2361 AddressRadix = Radix::d;
2362 else if (V == "x")
2363 AddressRadix = Radix::x;
2364 else
2365 error("--radix value should be one of: 'o' (octal), 'd' (decimal), 'x' "
2366 "(hexadecimal)");
2367 SizeSort = Args.hasArg(OPT_size_sort);
2368 SpecialSyms = Args.hasArg(OPT_special_syms);
2369 UndefinedOnly = Args.hasArg(OPT_undefined_only);
2370 WithoutAliases = Args.hasArg(OPT_without_aliases);
2371
2372 StringRef Mode = Args.getLastArgValue(OPT_X, "any");
2373 if (Mode == "32")
2374 BitMode = BitModeTy::Bit32;
2375 else if (Mode == "64")
2376 BitMode = BitModeTy::Bit64;
2377 else if (Mode == "32_64")
2378 BitMode = BitModeTy::Bit32_64;
2379 else if (Mode == "any")
2380 BitMode = BitModeTy::Any;
2381 else
2382 error("-X value should be one of: 32, 64, 32_64, (default) any");
2383
2384 // Mach-O specific options.
2385 FormatMachOasHex = Args.hasArg(OPT_x);
2386 AddDyldInfo = Args.hasArg(OPT_add_dyldinfo);
2387 AddInlinedInfo = Args.hasArg(OPT_add_inlinedinfo);
2388 DyldInfoOnly = Args.hasArg(OPT_dyldinfo_only);
2389 NoDyldInfo = Args.hasArg(OPT_no_dyldinfo);
2390
2391 // XCOFF specific options.
2392 NoRsrc = Args.hasArg(OPT_no_rsrc);
2393
2394 // llvm-nm only reads binary files.
2395 if (error(sys::ChangeStdinToBinary()))
2396 return 1;
2397
2398 // These calls are needed so that we can read bitcode correctly.
2399 llvm::InitializeAllTargetInfos();
2400 llvm::InitializeAllTargetMCs();
2401 llvm::InitializeAllAsmParsers();
2402
2403 // The relative order of these is important. If you pass --size-sort it should
2404 // only print out the size. However, if you pass -S --size-sort, it should
2405 // print out both the size and address.
2406 if (SizeSort && !PrintSize)
2407 PrintAddress = false;
2408 if (OutputFormat == sysv || SizeSort)
2409 PrintSize = true;
2410
2411 for (const auto *A : Args.filtered(OPT_arch_EQ)) {
2412 SmallVector<StringRef, 2> Values;
2413 llvm::SplitString(A->getValue(), Values, ",");
2414 for (StringRef V : Values) {
2415 if (V == "all")
2416 ArchAll = true;
2417 else if (MachOObjectFile::isValidArch(V))
2418 ArchFlags.push_back(V);
2419 else
2420 error("Unknown architecture named '" + V + "'",
2421 "for the --arch option");
2422 }
2423 }
2424
2425 // Mach-O takes -s to accept two arguments. We emulate this by iterating over
2426 // both OPT_s and OPT_INPUT.
2427 std::vector<std::string> InputFilenames;
2428 int SegSectArgs = 0;
2429 for (opt::Arg *A : Args.filtered(OPT_s, OPT_INPUT)) {
2430 if (SegSectArgs > 0) {
2431 --SegSectArgs;
2432 SegSect.push_back(A->getValue());
2433 } else if (A->getOption().matches(OPT_s)) {
2434 SegSectArgs = 2;
2435 } else {
2436 InputFilenames.push_back(A->getValue());
2437 }
2438 }
2439 if (!SegSect.empty() && SegSect.size() != 2)
2440 error("bad number of arguments (must be two arguments)",
2441 "for the -s option");
2442
2443 if (InputFilenames.empty())
2444 InputFilenames.push_back("a.out");
2445 if (InputFilenames.size() > 1)
2446 MultipleFiles = true;
2447
2448 if (NoDyldInfo && (AddDyldInfo || DyldInfoOnly))
2449 error("--no-dyldinfo can't be used with --add-dyldinfo or --dyldinfo-only");
2450
2451 if (ExportSymbols)
2452 exportSymbolNamesFromFiles(InputFilenames);
2453 else
2454 llvm::for_each(InputFilenames, dumpSymbolNamesFromFile);
2455
2456 if (HadError)
2457 return 1;
2458}