Run DCE after a LoopFlatten test to reduce spurious output [nfc]
[llvm-project.git] / llvm / tools / llvm-nm / llvm-nm.cpp
blobfede89e9c1167df925cfd17b77138a786f2648cd
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.
13 // This "nm" supports many of the features of GNU "nm", including its different
14 // output formats.
16 //===----------------------------------------------------------------------===//
18 #include "llvm/ADT/StringSwitch.h"
19 #include "llvm/BinaryFormat/COFF.h"
20 #include "llvm/BinaryFormat/MachO.h"
21 #include "llvm/BinaryFormat/XCOFF.h"
22 #include "llvm/DebugInfo/Symbolize/Symbolize.h"
23 #include "llvm/Demangle/Demangle.h"
24 #include "llvm/IR/Function.h"
25 #include "llvm/IR/LLVMContext.h"
26 #include "llvm/Object/Archive.h"
27 #include "llvm/Object/COFF.h"
28 #include "llvm/Object/COFFImportFile.h"
29 #include "llvm/Object/ELFObjectFile.h"
30 #include "llvm/Object/IRObjectFile.h"
31 #include "llvm/Object/MachO.h"
32 #include "llvm/Object/MachOUniversal.h"
33 #include "llvm/Object/ObjectFile.h"
34 #include "llvm/Object/SymbolicFile.h"
35 #include "llvm/Object/TapiFile.h"
36 #include "llvm/Object/TapiUniversal.h"
37 #include "llvm/Object/Wasm.h"
38 #include "llvm/Object/XCOFFObjectFile.h"
39 #include "llvm/Option/Arg.h"
40 #include "llvm/Option/ArgList.h"
41 #include "llvm/Option/Option.h"
42 #include "llvm/Support/CommandLine.h"
43 #include "llvm/Support/FileSystem.h"
44 #include "llvm/Support/Format.h"
45 #include "llvm/Support/InitLLVM.h"
46 #include "llvm/Support/LLVMDriver.h"
47 #include "llvm/Support/MemoryBuffer.h"
48 #include "llvm/Support/Program.h"
49 #include "llvm/Support/Signals.h"
50 #include "llvm/Support/TargetSelect.h"
51 #include "llvm/Support/WithColor.h"
52 #include "llvm/Support/raw_ostream.h"
53 #include "llvm/TargetParser/Host.h"
54 #include "llvm/TargetParser/Triple.h"
55 #include <vector>
57 using namespace llvm;
58 using namespace object;
60 namespace {
61 using namespace llvm::opt; // for HelpHidden in Opts.inc
62 enum ID {
63 OPT_INVALID = 0, // This is not an option ID.
64 #define OPTION(...) LLVM_MAKE_OPT_ID(__VA_ARGS__),
65 #include "Opts.inc"
66 #undef OPTION
69 #define PREFIX(NAME, VALUE) \
70 static constexpr StringLiteral NAME##_init[] = VALUE; \
71 static constexpr ArrayRef<StringLiteral> NAME(NAME##_init, \
72 std::size(NAME##_init) - 1);
73 #include "Opts.inc"
74 #undef PREFIX
76 static constexpr opt::OptTable::Info InfoTable[] = {
77 #define OPTION(...) LLVM_CONSTRUCT_OPT_INFO(__VA_ARGS__),
78 #include "Opts.inc"
79 #undef OPTION
82 class NmOptTable : public opt::GenericOptTable {
83 public:
84 NmOptTable() : opt::GenericOptTable(InfoTable) {
85 setGroupedShortOptions(true);
89 enum OutputFormatTy { bsd, sysv, posix, darwin, just_symbols };
90 enum class BitModeTy { Bit32, Bit64, Bit32_64, Any };
91 } // namespace
93 static bool ArchiveMap;
94 static BitModeTy BitMode;
95 static bool DebugSyms;
96 static bool DefinedOnly;
97 static bool Demangle;
98 static bool DynamicSyms;
99 static bool ExportSymbols;
100 static bool ExternalOnly;
101 static bool LineNumbers;
102 static OutputFormatTy OutputFormat;
103 static bool NoLLVMBitcode;
104 static bool NoSort;
105 static bool NoWeakSymbols;
106 static bool NumericSort;
107 static bool PrintFileName;
108 static bool PrintSize;
109 static bool Quiet;
110 static bool ReverseSort;
111 static bool SpecialSyms;
112 static bool SizeSort;
113 static bool UndefinedOnly;
114 static bool WithoutAliases;
116 // XCOFF-specific options.
117 static bool NoRsrc;
119 namespace {
120 enum Radix { d, o, x };
121 } // namespace
122 static Radix AddressRadix;
124 // Mach-O specific options.
125 static bool ArchAll = false;
126 static std::vector<StringRef> ArchFlags;
127 static bool AddDyldInfo;
128 static bool AddInlinedInfo;
129 static bool DyldInfoOnly;
130 static bool FormatMachOasHex;
131 static bool NoDyldInfo;
132 static std::vector<StringRef> SegSect;
133 static bool MachOPrintSizeWarning = false;
135 // Miscellaneous states.
136 static bool PrintAddress = true;
137 static bool MultipleFiles = false;
138 static bool HadError = false;
140 static StringRef ToolName;
142 static void warn(Error Err, Twine FileName, Twine Context = Twine(),
143 Twine Archive = Twine()) {
144 assert(Err);
146 // Flush the standard output so that the warning isn't interleaved with other
147 // output if stdout and stderr are writing to the same place.
148 outs().flush();
150 handleAllErrors(std::move(Err), [&](const ErrorInfoBase &EI) {
151 WithColor::warning(errs(), ToolName)
152 << (Archive.str().empty() ? FileName : Archive + "(" + FileName + ")")
153 << ": " << (Context.str().empty() ? "" : Context + ": ") << EI.message()
154 << "\n";
158 static void error(Twine Message, Twine Path = Twine()) {
159 HadError = true;
160 WithColor::error(errs(), ToolName) << Path << ": " << Message << "\n";
163 static bool error(std::error_code EC, Twine Path = Twine()) {
164 if (EC) {
165 error(EC.message(), Path);
166 return true;
168 return false;
171 // This version of error() prints the archive name and member name, for example:
172 // "libx.a(foo.o)" after the ToolName before the error message. It sets
173 // HadError but returns allowing the code to move on to other archive members.
174 static void error(llvm::Error E, StringRef FileName, const Archive::Child &C,
175 StringRef ArchitectureName = StringRef()) {
176 HadError = true;
177 WithColor::error(errs(), ToolName) << FileName;
179 Expected<StringRef> NameOrErr = C.getName();
180 // TODO: if we have a error getting the name then it would be nice to print
181 // the index of which archive member this is and or its offset in the
182 // archive instead of "???" as the name.
183 if (!NameOrErr) {
184 consumeError(NameOrErr.takeError());
185 errs() << "(" << "???" << ")";
186 } else
187 errs() << "(" << NameOrErr.get() << ")";
189 if (!ArchitectureName.empty())
190 errs() << " (for architecture " << ArchitectureName << ")";
192 std::string Buf;
193 raw_string_ostream OS(Buf);
194 logAllUnhandledErrors(std::move(E), OS);
195 OS.flush();
196 errs() << ": " << Buf << "\n";
199 // This version of error() prints the file name and which architecture slice it
200 // is from, for example: "foo.o (for architecture i386)" after the ToolName
201 // before the error message. It sets HadError but returns allowing the code to
202 // move on to other architecture slices.
203 static void error(llvm::Error E, StringRef FileName,
204 StringRef ArchitectureName = StringRef()) {
205 HadError = true;
206 WithColor::error(errs(), ToolName) << FileName;
208 if (!ArchitectureName.empty())
209 errs() << " (for architecture " << ArchitectureName << ")";
211 std::string Buf;
212 raw_string_ostream OS(Buf);
213 logAllUnhandledErrors(std::move(E), OS);
214 OS.flush();
215 errs() << ": " << Buf << "\n";
218 namespace {
219 struct NMSymbol {
220 uint64_t Address;
221 uint64_t Size;
222 char TypeChar;
223 std::string Name;
224 StringRef SectionName;
225 StringRef TypeName;
226 BasicSymbolRef Sym;
227 StringRef Visibility;
229 // The Sym field above points to the native symbol in the object file,
230 // for Mach-O when we are creating symbols from the dyld info the above
231 // pointer is null as there is no native symbol. In these cases the fields
232 // below are filled in to represent what would have been a Mach-O nlist
233 // native symbol.
234 uint32_t SymFlags;
235 SectionRef Section;
236 uint8_t NType;
237 uint8_t NSect;
238 uint16_t NDesc;
239 std::string IndirectName;
241 bool isDefined() const {
242 if (Sym.getRawDataRefImpl().p)
243 return !(SymFlags & SymbolRef::SF_Undefined);
244 return TypeChar != 'U';
247 bool initializeFlags(const SymbolicFile &Obj) {
248 Expected<uint32_t> SymFlagsOrErr = Sym.getFlags();
249 if (!SymFlagsOrErr) {
250 // TODO: Test this error.
251 error(SymFlagsOrErr.takeError(), Obj.getFileName());
252 return false;
254 SymFlags = *SymFlagsOrErr;
255 return true;
258 bool shouldPrint() const {
259 bool Undefined = SymFlags & SymbolRef::SF_Undefined;
260 bool Global = SymFlags & SymbolRef::SF_Global;
261 bool Weak = SymFlags & SymbolRef::SF_Weak;
262 bool FormatSpecific = SymFlags & SymbolRef::SF_FormatSpecific;
263 if ((!Undefined && UndefinedOnly) || (Undefined && DefinedOnly) ||
264 (!Global && ExternalOnly) || (Weak && NoWeakSymbols) ||
265 (FormatSpecific && !(SpecialSyms || DebugSyms)))
266 return false;
267 return true;
271 bool operator<(const NMSymbol &A, const NMSymbol &B) {
272 if (NumericSort)
273 return std::make_tuple(A.isDefined(), A.Address, A.Name, A.Size) <
274 std::make_tuple(B.isDefined(), B.Address, B.Name, B.Size);
275 if (SizeSort)
276 return std::make_tuple(A.Size, A.Name, A.Address) <
277 std::make_tuple(B.Size, B.Name, B.Address);
278 if (ExportSymbols)
279 return std::make_tuple(A.Name, A.Visibility) <
280 std::make_tuple(B.Name, B.Visibility);
281 return std::make_tuple(A.Name, A.Size, A.Address) <
282 std::make_tuple(B.Name, B.Size, B.Address);
285 bool operator>(const NMSymbol &A, const NMSymbol &B) { return B < A; }
286 bool operator==(const NMSymbol &A, const NMSymbol &B) {
287 return !(A < B) && !(B < A);
289 } // anonymous namespace
291 static StringRef CurrentFilename;
293 static char getSymbolNMTypeChar(IRObjectFile &Obj, basic_symbol_iterator I);
295 // darwinPrintSymbol() is used to print a symbol from a Mach-O file when the
296 // the OutputFormat is darwin or we are printing Mach-O symbols in hex. For
297 // the darwin format it produces the same output as darwin's nm(1) -m output
298 // and when printing Mach-O symbols in hex it produces the same output as
299 // darwin's nm(1) -x format.
300 static void darwinPrintSymbol(SymbolicFile &Obj, const NMSymbol &S,
301 char *SymbolAddrStr, const char *printBlanks,
302 const char *printDashes,
303 const char *printFormat) {
304 MachO::mach_header H;
305 MachO::mach_header_64 H_64;
306 uint32_t Filetype = MachO::MH_OBJECT;
307 uint32_t Flags = 0;
308 uint8_t NType = 0;
309 uint8_t NSect = 0;
310 uint16_t NDesc = 0;
311 uint32_t NStrx = 0;
312 uint64_t NValue = 0;
313 MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(&Obj);
314 if (Obj.isIR()) {
315 uint32_t SymFlags = cantFail(S.Sym.getFlags());
316 if (SymFlags & SymbolRef::SF_Global)
317 NType |= MachO::N_EXT;
318 if (SymFlags & SymbolRef::SF_Hidden)
319 NType |= MachO::N_PEXT;
320 if (SymFlags & SymbolRef::SF_Undefined)
321 NType |= MachO::N_EXT | MachO::N_UNDF;
322 else {
323 // Here we have a symbol definition. So to fake out a section name we
324 // use 1, 2 and 3 for section numbers. See below where they are used to
325 // print out fake section names.
326 NType |= MachO::N_SECT;
327 if (SymFlags & SymbolRef::SF_Const)
328 NSect = 3;
329 else if (SymFlags & SymbolRef::SF_Executable)
330 NSect = 1;
331 else
332 NSect = 2;
334 if (SymFlags & SymbolRef::SF_Weak)
335 NDesc |= MachO::N_WEAK_DEF;
336 } else {
337 DataRefImpl SymDRI = S.Sym.getRawDataRefImpl();
338 if (MachO->is64Bit()) {
339 H_64 = MachO->MachOObjectFile::getHeader64();
340 Filetype = H_64.filetype;
341 Flags = H_64.flags;
342 if (SymDRI.p){
343 MachO::nlist_64 STE_64 = MachO->getSymbol64TableEntry(SymDRI);
344 NType = STE_64.n_type;
345 NSect = STE_64.n_sect;
346 NDesc = STE_64.n_desc;
347 NStrx = STE_64.n_strx;
348 NValue = STE_64.n_value;
349 } else {
350 NType = S.NType;
351 NSect = S.NSect;
352 NDesc = S.NDesc;
353 NStrx = 0;
354 NValue = S.Address;
356 } else {
357 H = MachO->MachOObjectFile::getHeader();
358 Filetype = H.filetype;
359 Flags = H.flags;
360 if (SymDRI.p){
361 MachO::nlist STE = MachO->getSymbolTableEntry(SymDRI);
362 NType = STE.n_type;
363 NSect = STE.n_sect;
364 NDesc = STE.n_desc;
365 NStrx = STE.n_strx;
366 NValue = STE.n_value;
367 } else {
368 NType = S.NType;
369 NSect = S.NSect;
370 NDesc = S.NDesc;
371 NStrx = 0;
372 NValue = S.Address;
377 // If we are printing Mach-O symbols in hex do that and return.
378 if (FormatMachOasHex) {
379 outs() << format(printFormat, NValue) << ' '
380 << format("%02x %02x %04x %08x", NType, NSect, NDesc, NStrx) << ' '
381 << S.Name;
382 if ((NType & MachO::N_TYPE) == MachO::N_INDR) {
383 outs() << " (indirect for ";
384 outs() << format(printFormat, NValue) << ' ';
385 StringRef IndirectName;
386 if (S.Sym.getRawDataRefImpl().p) {
387 if (MachO->getIndirectName(S.Sym.getRawDataRefImpl(), IndirectName))
388 outs() << "?)";
389 else
390 outs() << IndirectName << ")";
391 } else
392 outs() << S.IndirectName << ")";
394 outs() << "\n";
395 return;
398 if (PrintAddress) {
399 if ((NType & MachO::N_TYPE) == MachO::N_INDR)
400 strcpy(SymbolAddrStr, printBlanks);
401 if (Obj.isIR() && (NType & MachO::N_TYPE) == MachO::N_TYPE)
402 strcpy(SymbolAddrStr, printDashes);
403 outs() << SymbolAddrStr << ' ';
406 switch (NType & MachO::N_TYPE) {
407 case MachO::N_UNDF:
408 if (NValue != 0) {
409 outs() << "(common) ";
410 if (MachO::GET_COMM_ALIGN(NDesc) != 0)
411 outs() << "(alignment 2^" << (int)MachO::GET_COMM_ALIGN(NDesc) << ") ";
412 } else {
413 if ((NType & MachO::N_TYPE) == MachO::N_PBUD)
414 outs() << "(prebound ";
415 else
416 outs() << "(";
417 if ((NDesc & MachO::REFERENCE_TYPE) ==
418 MachO::REFERENCE_FLAG_UNDEFINED_LAZY)
419 outs() << "undefined [lazy bound]) ";
420 else if ((NDesc & MachO::REFERENCE_TYPE) ==
421 MachO::REFERENCE_FLAG_PRIVATE_UNDEFINED_LAZY)
422 outs() << "undefined [private lazy bound]) ";
423 else if ((NDesc & MachO::REFERENCE_TYPE) ==
424 MachO::REFERENCE_FLAG_PRIVATE_UNDEFINED_NON_LAZY)
425 outs() << "undefined [private]) ";
426 else
427 outs() << "undefined) ";
429 break;
430 case MachO::N_ABS:
431 outs() << "(absolute) ";
432 break;
433 case MachO::N_INDR:
434 outs() << "(indirect) ";
435 break;
436 case MachO::N_SECT: {
437 if (Obj.isIR()) {
438 // For llvm bitcode files print out a fake section name using the values
439 // use 1, 2 and 3 for section numbers as set above.
440 if (NSect == 1)
441 outs() << "(LTO,CODE) ";
442 else if (NSect == 2)
443 outs() << "(LTO,DATA) ";
444 else if (NSect == 3)
445 outs() << "(LTO,RODATA) ";
446 else
447 outs() << "(?,?) ";
448 break;
450 section_iterator Sec = SectionRef();
451 if (S.Sym.getRawDataRefImpl().p) {
452 Expected<section_iterator> SecOrErr =
453 MachO->getSymbolSection(S.Sym.getRawDataRefImpl());
454 if (!SecOrErr) {
455 consumeError(SecOrErr.takeError());
456 outs() << "(?,?) ";
457 break;
459 Sec = *SecOrErr;
460 if (Sec == MachO->section_end()) {
461 outs() << "(?,?) ";
462 break;
464 } else {
465 Sec = S.Section;
467 DataRefImpl Ref = Sec->getRawDataRefImpl();
468 StringRef SectionName;
469 if (Expected<StringRef> NameOrErr = MachO->getSectionName(Ref))
470 SectionName = *NameOrErr;
471 StringRef SegmentName = MachO->getSectionFinalSegmentName(Ref);
472 outs() << "(" << SegmentName << "," << SectionName << ") ";
473 break;
475 default:
476 outs() << "(?) ";
477 break;
480 if (NType & MachO::N_EXT) {
481 if (NDesc & MachO::REFERENCED_DYNAMICALLY)
482 outs() << "[referenced dynamically] ";
483 if (NType & MachO::N_PEXT) {
484 if ((NDesc & MachO::N_WEAK_DEF) == MachO::N_WEAK_DEF)
485 outs() << "weak private external ";
486 else
487 outs() << "private external ";
488 } else {
489 if ((NDesc & MachO::N_WEAK_REF) == MachO::N_WEAK_REF ||
490 (NDesc & MachO::N_WEAK_DEF) == MachO::N_WEAK_DEF) {
491 if ((NDesc & (MachO::N_WEAK_REF | MachO::N_WEAK_DEF)) ==
492 (MachO::N_WEAK_REF | MachO::N_WEAK_DEF))
493 outs() << "weak external automatically hidden ";
494 else
495 outs() << "weak external ";
496 } else
497 outs() << "external ";
499 } else {
500 if (NType & MachO::N_PEXT)
501 outs() << "non-external (was a private external) ";
502 else
503 outs() << "non-external ";
506 if (Filetype == MachO::MH_OBJECT) {
507 if (NDesc & MachO::N_NO_DEAD_STRIP)
508 outs() << "[no dead strip] ";
509 if ((NType & MachO::N_TYPE) != MachO::N_UNDF &&
510 NDesc & MachO::N_SYMBOL_RESOLVER)
511 outs() << "[symbol resolver] ";
512 if ((NType & MachO::N_TYPE) != MachO::N_UNDF && NDesc & MachO::N_ALT_ENTRY)
513 outs() << "[alt entry] ";
514 if ((NType & MachO::N_TYPE) != MachO::N_UNDF && NDesc & MachO::N_COLD_FUNC)
515 outs() << "[cold func] ";
518 if ((NDesc & MachO::N_ARM_THUMB_DEF) == MachO::N_ARM_THUMB_DEF)
519 outs() << "[Thumb] ";
521 if ((NType & MachO::N_TYPE) == MachO::N_INDR) {
522 outs() << S.Name << " (for ";
523 StringRef IndirectName;
524 if (MachO) {
525 if (S.Sym.getRawDataRefImpl().p) {
526 if (MachO->getIndirectName(S.Sym.getRawDataRefImpl(), IndirectName))
527 outs() << "?)";
528 else
529 outs() << IndirectName << ")";
530 } else
531 outs() << S.IndirectName << ")";
532 } else
533 outs() << "?)";
534 } else
535 outs() << S.Name;
537 if ((Flags & MachO::MH_TWOLEVEL) == MachO::MH_TWOLEVEL &&
538 (((NType & MachO::N_TYPE) == MachO::N_UNDF && NValue == 0) ||
539 (NType & MachO::N_TYPE) == MachO::N_PBUD)) {
540 uint32_t LibraryOrdinal = MachO::GET_LIBRARY_ORDINAL(NDesc);
541 if (LibraryOrdinal != 0) {
542 if (LibraryOrdinal == MachO::EXECUTABLE_ORDINAL)
543 outs() << " (from executable)";
544 else if (LibraryOrdinal == MachO::DYNAMIC_LOOKUP_ORDINAL)
545 outs() << " (dynamically looked up)";
546 else {
547 StringRef LibraryName;
548 if (!MachO ||
549 MachO->getLibraryShortNameByIndex(LibraryOrdinal - 1, LibraryName))
550 outs() << " (from bad library ordinal " << LibraryOrdinal << ")";
551 else
552 outs() << " (from " << LibraryName << ")";
558 // Table that maps Darwin's Mach-O stab constants to strings to allow printing.
559 struct DarwinStabName {
560 uint8_t NType;
561 const char *Name;
563 const struct DarwinStabName DarwinStabNames[] = {
564 {MachO::N_GSYM, "GSYM"}, {MachO::N_FNAME, "FNAME"},
565 {MachO::N_FUN, "FUN"}, {MachO::N_STSYM, "STSYM"},
566 {MachO::N_LCSYM, "LCSYM"}, {MachO::N_BNSYM, "BNSYM"},
567 {MachO::N_PC, "PC"}, {MachO::N_AST, "AST"},
568 {MachO::N_OPT, "OPT"}, {MachO::N_RSYM, "RSYM"},
569 {MachO::N_SLINE, "SLINE"}, {MachO::N_ENSYM, "ENSYM"},
570 {MachO::N_SSYM, "SSYM"}, {MachO::N_SO, "SO"},
571 {MachO::N_OSO, "OSO"}, {MachO::N_LIB, "LIB"},
572 {MachO::N_LSYM, "LSYM"}, {MachO::N_BINCL, "BINCL"},
573 {MachO::N_SOL, "SOL"}, {MachO::N_PARAMS, "PARAM"},
574 {MachO::N_VERSION, "VERS"}, {MachO::N_OLEVEL, "OLEV"},
575 {MachO::N_PSYM, "PSYM"}, {MachO::N_EINCL, "EINCL"},
576 {MachO::N_ENTRY, "ENTRY"}, {MachO::N_LBRAC, "LBRAC"},
577 {MachO::N_EXCL, "EXCL"}, {MachO::N_RBRAC, "RBRAC"},
578 {MachO::N_BCOMM, "BCOMM"}, {MachO::N_ECOMM, "ECOMM"},
579 {MachO::N_ECOML, "ECOML"}, {MachO::N_LENG, "LENG"},
582 static const char *getDarwinStabString(uint8_t NType) {
583 for (auto I : ArrayRef(DarwinStabNames))
584 if (I.NType == NType)
585 return I.Name;
586 return nullptr;
589 // darwinPrintStab() prints the n_sect, n_desc along with a symbolic name of
590 // a stab n_type value in a Mach-O file.
591 static void darwinPrintStab(MachOObjectFile *MachO, const NMSymbol &S) {
592 MachO::nlist_64 STE_64;
593 MachO::nlist STE;
594 uint8_t NType;
595 uint8_t NSect;
596 uint16_t NDesc;
597 DataRefImpl SymDRI = S.Sym.getRawDataRefImpl();
598 if (MachO->is64Bit()) {
599 STE_64 = MachO->getSymbol64TableEntry(SymDRI);
600 NType = STE_64.n_type;
601 NSect = STE_64.n_sect;
602 NDesc = STE_64.n_desc;
603 } else {
604 STE = MachO->getSymbolTableEntry(SymDRI);
605 NType = STE.n_type;
606 NSect = STE.n_sect;
607 NDesc = STE.n_desc;
610 outs() << format(" %02x %04x ", NSect, NDesc);
611 if (const char *stabString = getDarwinStabString(NType))
612 outs() << format("%5.5s", stabString);
613 else
614 outs() << format(" %02x", NType);
617 static bool symbolIsDefined(const NMSymbol &Sym) {
618 return Sym.TypeChar != 'U' && Sym.TypeChar != 'w' && Sym.TypeChar != 'v';
621 static void writeFileName(raw_ostream &S, StringRef ArchiveName,
622 StringRef ArchitectureName) {
623 if (!ArchitectureName.empty())
624 S << "(for architecture " << ArchitectureName << "):";
625 if (OutputFormat == posix && !ArchiveName.empty())
626 S << ArchiveName << "[" << CurrentFilename << "]: ";
627 else {
628 if (!ArchiveName.empty())
629 S << ArchiveName << ":";
630 S << CurrentFilename << ": ";
634 static void sortSymbolList(std::vector<NMSymbol> &SymbolList) {
635 if (NoSort)
636 return;
638 if (ReverseSort)
639 llvm::sort(SymbolList, std::greater<>());
640 else
641 llvm::sort(SymbolList);
644 static void printExportSymbolList(const std::vector<NMSymbol> &SymbolList) {
645 for (const NMSymbol &Sym : SymbolList) {
646 outs() << Sym.Name;
647 if (!Sym.Visibility.empty())
648 outs() << ' ' << Sym.Visibility;
649 outs() << '\n';
653 static void printLineNumbers(symbolize::LLVMSymbolizer &Symbolizer,
654 const NMSymbol &S) {
655 const auto *Obj = dyn_cast<ObjectFile>(S.Sym.getObject());
656 if (!Obj)
657 return;
658 const SymbolRef Sym(S.Sym);
659 uint64_t SectionIndex = object::SectionedAddress::UndefSection;
660 section_iterator Sec = cantFail(Sym.getSection());
661 if (Sec != Obj->section_end())
662 SectionIndex = Sec->getIndex();
663 object::SectionedAddress Address = {cantFail(Sym.getAddress()), SectionIndex};
665 std::string FileName;
666 uint32_t Line;
667 switch (S.TypeChar) {
668 // For undefined symbols, find the first relocation for that symbol with a
669 // line number.
670 case 'U': {
671 for (const SectionRef RelocsSec : Obj->sections()) {
672 if (RelocsSec.relocations().empty())
673 continue;
674 SectionRef TextSec = *cantFail(RelocsSec.getRelocatedSection());
675 if (!TextSec.isText())
676 continue;
677 for (const RelocationRef R : RelocsSec.relocations()) {
678 if (R.getSymbol() != Sym)
679 continue;
680 Expected<DILineInfo> ResOrErr = Symbolizer.symbolizeCode(
681 *Obj, {TextSec.getAddress() + R.getOffset(), SectionIndex});
682 if (!ResOrErr) {
683 error(ResOrErr.takeError(), Obj->getFileName());
684 return;
686 if (ResOrErr->FileName == DILineInfo::BadString)
687 return;
688 FileName = std::move(ResOrErr->FileName);
689 Line = ResOrErr->Line;
690 break;
692 if (!FileName.empty())
693 break;
695 if (FileName.empty())
696 return;
697 break;
699 case 't':
700 case 'T': {
701 Expected<DILineInfo> ResOrErr = Symbolizer.symbolizeCode(*Obj, Address);
702 if (!ResOrErr) {
703 error(ResOrErr.takeError(), Obj->getFileName());
704 return;
706 if (ResOrErr->FileName == DILineInfo::BadString)
707 return;
708 FileName = std::move(ResOrErr->FileName);
709 Line = ResOrErr->Line;
710 break;
712 default: {
713 Expected<DIGlobal> ResOrErr = Symbolizer.symbolizeData(*Obj, Address);
714 if (!ResOrErr) {
715 error(ResOrErr.takeError(), Obj->getFileName());
716 return;
718 if (ResOrErr->DeclFile.empty())
719 return;
720 FileName = std::move(ResOrErr->DeclFile);
721 Line = ResOrErr->DeclLine;
722 break;
725 outs() << '\t' << FileName << ':' << Line;
728 static void printSymbolList(SymbolicFile &Obj,
729 std::vector<NMSymbol> &SymbolList, bool printName,
730 StringRef ArchiveName, StringRef ArchitectureName) {
731 std::optional<symbolize::LLVMSymbolizer> Symbolizer;
732 if (LineNumbers)
733 Symbolizer.emplace();
735 if (!PrintFileName) {
736 if ((OutputFormat == bsd || OutputFormat == posix ||
737 OutputFormat == just_symbols) &&
738 MultipleFiles && printName) {
739 outs() << '\n' << CurrentFilename << ":\n";
740 } else if (OutputFormat == sysv) {
741 outs() << "\n\nSymbols from " << CurrentFilename << ":\n\n";
742 if (Obj.is64Bit())
743 outs() << "Name Value Class Type"
744 << " Size Line Section\n";
745 else
746 outs() << "Name Value Class Type"
747 << " Size Line Section\n";
751 const char *printBlanks, *printDashes, *printFormat;
752 if (Obj.is64Bit()) {
753 printBlanks = " ";
754 printDashes = "----------------";
755 switch (AddressRadix) {
756 case Radix::o:
757 printFormat = OutputFormat == posix ? "%" PRIo64 : "%016" PRIo64;
758 break;
759 case Radix::x:
760 printFormat = OutputFormat == posix ? "%" PRIx64 : "%016" PRIx64;
761 break;
762 default:
763 printFormat = OutputFormat == posix ? "%" PRId64 : "%016" PRId64;
765 } else {
766 printBlanks = " ";
767 printDashes = "--------";
768 switch (AddressRadix) {
769 case Radix::o:
770 printFormat = OutputFormat == posix ? "%" PRIo64 : "%08" PRIo64;
771 break;
772 case Radix::x:
773 printFormat = OutputFormat == posix ? "%" PRIx64 : "%08" PRIx64;
774 break;
775 default:
776 printFormat = OutputFormat == posix ? "%" PRId64 : "%08" PRId64;
780 for (const NMSymbol &S : SymbolList) {
781 if (!S.shouldPrint())
782 continue;
784 std::string Name = S.Name;
785 MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(&Obj);
786 if (Demangle)
787 Name = demangle(Name);
789 if (PrintFileName)
790 writeFileName(outs(), ArchiveName, ArchitectureName);
791 if ((OutputFormat == just_symbols ||
792 (UndefinedOnly && MachO && OutputFormat != darwin)) &&
793 OutputFormat != posix) {
794 outs() << Name << "\n";
795 continue;
798 char SymbolAddrStr[23], SymbolSizeStr[23];
800 // If the format is SysV or the symbol isn't defined, then print spaces.
801 if (OutputFormat == sysv || !symbolIsDefined(S)) {
802 if (OutputFormat == posix) {
803 format(printFormat, S.Address)
804 .print(SymbolAddrStr, sizeof(SymbolAddrStr));
805 format(printFormat, S.Size).print(SymbolSizeStr, sizeof(SymbolSizeStr));
806 } else {
807 strcpy(SymbolAddrStr, printBlanks);
808 strcpy(SymbolSizeStr, printBlanks);
812 if (symbolIsDefined(S)) {
813 // Otherwise, print the symbol address and size.
814 if (Obj.isIR())
815 strcpy(SymbolAddrStr, printDashes);
816 else if (MachO && S.TypeChar == 'I')
817 strcpy(SymbolAddrStr, printBlanks);
818 else
819 format(printFormat, S.Address)
820 .print(SymbolAddrStr, sizeof(SymbolAddrStr));
821 format(printFormat, S.Size).print(SymbolSizeStr, sizeof(SymbolSizeStr));
824 // If OutputFormat is darwin or we are printing Mach-O symbols in hex and
825 // we have a MachOObjectFile, call darwinPrintSymbol to print as darwin's
826 // nm(1) -m output or hex, else if OutputFormat is darwin or we are
827 // printing Mach-O symbols in hex and not a Mach-O object fall back to
828 // OutputFormat bsd (see below).
829 if ((OutputFormat == darwin || FormatMachOasHex) && (MachO || Obj.isIR())) {
830 darwinPrintSymbol(Obj, S, SymbolAddrStr, printBlanks, printDashes,
831 printFormat);
832 } else if (OutputFormat == posix) {
833 outs() << Name << " " << S.TypeChar << " " << SymbolAddrStr << " "
834 << (MachO ? "0" : SymbolSizeStr);
835 } else if (OutputFormat == bsd || (OutputFormat == darwin && !MachO)) {
836 if (PrintAddress)
837 outs() << SymbolAddrStr << ' ';
838 if (PrintSize)
839 outs() << SymbolSizeStr << ' ';
840 outs() << S.TypeChar;
841 if (S.TypeChar == '-' && MachO)
842 darwinPrintStab(MachO, S);
843 outs() << " " << Name;
844 if (S.TypeChar == 'I' && MachO) {
845 outs() << " (indirect for ";
846 if (S.Sym.getRawDataRefImpl().p) {
847 StringRef IndirectName;
848 if (MachO->getIndirectName(S.Sym.getRawDataRefImpl(), IndirectName))
849 outs() << "?)";
850 else
851 outs() << IndirectName << ")";
852 } else
853 outs() << S.IndirectName << ")";
855 } else if (OutputFormat == sysv) {
856 outs() << left_justify(Name, 20) << "|" << SymbolAddrStr << "| "
857 << S.TypeChar << " |" << right_justify(S.TypeName, 18) << "|"
858 << SymbolSizeStr << "| |" << S.SectionName;
860 if (LineNumbers)
861 printLineNumbers(*Symbolizer, S);
862 outs() << '\n';
865 SymbolList.clear();
868 static char getSymbolNMTypeChar(ELFObjectFileBase &Obj,
869 basic_symbol_iterator I) {
870 // OK, this is ELF
871 elf_symbol_iterator SymI(I);
873 Expected<elf_section_iterator> SecIOrErr = SymI->getSection();
874 if (!SecIOrErr) {
875 consumeError(SecIOrErr.takeError());
876 return '?';
879 uint8_t Binding = SymI->getBinding();
880 if (Binding == ELF::STB_GNU_UNIQUE)
881 return 'u';
883 assert(Binding != ELF::STB_WEAK && "STB_WEAK not tested in calling function");
884 if (Binding != ELF::STB_GLOBAL && Binding != ELF::STB_LOCAL)
885 return '?';
887 elf_section_iterator SecI = *SecIOrErr;
888 if (SecI != Obj.section_end()) {
889 uint32_t Type = SecI->getType();
890 uint64_t Flags = SecI->getFlags();
891 if (Flags & ELF::SHF_EXECINSTR)
892 return 't';
893 if (Type == ELF::SHT_NOBITS)
894 return 'b';
895 if (Flags & ELF::SHF_ALLOC)
896 return Flags & ELF::SHF_WRITE ? 'd' : 'r';
898 auto NameOrErr = SecI->getName();
899 if (!NameOrErr) {
900 consumeError(NameOrErr.takeError());
901 return '?';
903 if ((*NameOrErr).startswith(".debug"))
904 return 'N';
905 if (!(Flags & ELF::SHF_WRITE))
906 return 'n';
909 return '?';
912 static char getSymbolNMTypeChar(COFFObjectFile &Obj, symbol_iterator I) {
913 COFFSymbolRef Symb = Obj.getCOFFSymbol(*I);
914 // OK, this is COFF.
915 symbol_iterator SymI(I);
917 Expected<StringRef> Name = SymI->getName();
918 if (!Name) {
919 consumeError(Name.takeError());
920 return '?';
923 char Ret = StringSwitch<char>(*Name)
924 .StartsWith(".debug", 'N')
925 .StartsWith(".sxdata", 'N')
926 .Default('?');
928 if (Ret != '?')
929 return Ret;
931 uint32_t Characteristics = 0;
932 if (!COFF::isReservedSectionNumber(Symb.getSectionNumber())) {
933 Expected<section_iterator> SecIOrErr = SymI->getSection();
934 if (!SecIOrErr) {
935 consumeError(SecIOrErr.takeError());
936 return '?';
938 section_iterator SecI = *SecIOrErr;
939 const coff_section *Section = Obj.getCOFFSection(*SecI);
940 Characteristics = Section->Characteristics;
941 if (Expected<StringRef> NameOrErr = Obj.getSectionName(Section))
942 if (NameOrErr->startswith(".idata"))
943 return 'i';
946 switch (Symb.getSectionNumber()) {
947 case COFF::IMAGE_SYM_DEBUG:
948 return 'n';
949 default:
950 // Check section type.
951 if (Characteristics & COFF::IMAGE_SCN_CNT_CODE)
952 return 't';
953 if (Characteristics & COFF::IMAGE_SCN_CNT_INITIALIZED_DATA)
954 return Characteristics & COFF::IMAGE_SCN_MEM_WRITE ? 'd' : 'r';
955 if (Characteristics & COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA)
956 return 'b';
957 if (Characteristics & COFF::IMAGE_SCN_LNK_INFO)
958 return 'i';
959 // Check for section symbol.
960 if (Symb.isSectionDefinition())
961 return 's';
964 return '?';
967 static char getSymbolNMTypeChar(XCOFFObjectFile &Obj, symbol_iterator I) {
968 Expected<uint32_t> TypeOrErr = I->getType();
969 if (!TypeOrErr) {
970 warn(TypeOrErr.takeError(), Obj.getFileName(),
971 "for symbol with index " +
972 Twine(Obj.getSymbolIndex(I->getRawDataRefImpl().p)));
973 return '?';
976 uint32_t SymType = *TypeOrErr;
978 if (SymType == SymbolRef::ST_File)
979 return 'f';
981 // If the I->getSection() call would return an error, the earlier I->getType()
982 // call will already have returned the same error first.
983 section_iterator SecIter = cantFail(I->getSection());
985 if (SecIter == Obj.section_end())
986 return '?';
988 if (Obj.isDebugSection(SecIter->getRawDataRefImpl()))
989 return 'N';
991 if (SecIter->isText())
992 return 't';
994 if (SecIter->isData())
995 return 'd';
997 if (SecIter->isBSS())
998 return 'b';
1000 return '?';
1003 static char getSymbolNMTypeChar(COFFImportFile &Obj) {
1004 switch (Obj.getCOFFImportHeader()->getType()) {
1005 case COFF::IMPORT_CODE:
1006 return 't';
1007 case COFF::IMPORT_DATA:
1008 return 'd';
1009 case COFF::IMPORT_CONST:
1010 return 'r';
1012 return '?';
1015 static char getSymbolNMTypeChar(MachOObjectFile &Obj, basic_symbol_iterator I) {
1016 DataRefImpl Symb = I->getRawDataRefImpl();
1017 uint8_t NType = Obj.is64Bit() ? Obj.getSymbol64TableEntry(Symb).n_type
1018 : Obj.getSymbolTableEntry(Symb).n_type;
1020 if (NType & MachO::N_STAB)
1021 return '-';
1023 switch (NType & MachO::N_TYPE) {
1024 case MachO::N_ABS:
1025 return 's';
1026 case MachO::N_INDR:
1027 return 'i';
1028 case MachO::N_SECT: {
1029 Expected<section_iterator> SecOrErr = Obj.getSymbolSection(Symb);
1030 if (!SecOrErr) {
1031 consumeError(SecOrErr.takeError());
1032 return 's';
1034 section_iterator Sec = *SecOrErr;
1035 if (Sec == Obj.section_end())
1036 return 's';
1037 DataRefImpl Ref = Sec->getRawDataRefImpl();
1038 StringRef SectionName;
1039 if (Expected<StringRef> NameOrErr = Obj.getSectionName(Ref))
1040 SectionName = *NameOrErr;
1041 StringRef SegmentName = Obj.getSectionFinalSegmentName(Ref);
1042 if (Obj.is64Bit() && Obj.getHeader64().filetype == MachO::MH_KEXT_BUNDLE &&
1043 SegmentName == "__TEXT_EXEC" && SectionName == "__text")
1044 return 't';
1045 if (SegmentName == "__TEXT" && SectionName == "__text")
1046 return 't';
1047 if (SegmentName == "__DATA" && SectionName == "__data")
1048 return 'd';
1049 if (SegmentName == "__DATA" && SectionName == "__bss")
1050 return 'b';
1051 return 's';
1055 return '?';
1058 static char getSymbolNMTypeChar(TapiFile &Obj, basic_symbol_iterator I) {
1059 auto Type = cantFail(Obj.getSymbolType(I->getRawDataRefImpl()));
1060 switch (Type) {
1061 case SymbolRef::ST_Function:
1062 return 't';
1063 case SymbolRef::ST_Data:
1064 if (Obj.hasSegmentInfo())
1065 return 'd';
1066 [[fallthrough]];
1067 default:
1068 return 's';
1072 static char getSymbolNMTypeChar(WasmObjectFile &Obj, basic_symbol_iterator I) {
1073 uint32_t Flags = cantFail(I->getFlags());
1074 if (Flags & SymbolRef::SF_Executable)
1075 return 't';
1076 return 'd';
1079 static char getSymbolNMTypeChar(IRObjectFile &Obj, basic_symbol_iterator I) {
1080 uint32_t Flags = cantFail(I->getFlags());
1081 // FIXME: should we print 'b'? At the IR level we cannot be sure if this
1082 // will be in bss or not, but we could approximate.
1083 if (Flags & SymbolRef::SF_Executable)
1084 return 't';
1085 else if (Triple(Obj.getTargetTriple()).isOSDarwin() &&
1086 (Flags & SymbolRef::SF_Const))
1087 return 's';
1088 else
1089 return 'd';
1092 static bool isObject(SymbolicFile &Obj, basic_symbol_iterator I) {
1093 return isa<ELFObjectFileBase>(&Obj) &&
1094 elf_symbol_iterator(I)->getELFType() == ELF::STT_OBJECT;
1097 // For ELF object files, Set TypeName to the symbol typename, to be printed
1098 // in the 'Type' column of the SYSV format output.
1099 static StringRef getNMTypeName(SymbolicFile &Obj, basic_symbol_iterator I) {
1100 if (isa<ELFObjectFileBase>(&Obj)) {
1101 elf_symbol_iterator SymI(I);
1102 return SymI->getELFTypeName();
1104 return "";
1107 // Return Posix nm class type tag (single letter), but also set SecName and
1108 // section and name, to be used in format=sysv output.
1109 static char getNMSectionTagAndName(SymbolicFile &Obj, basic_symbol_iterator I,
1110 StringRef &SecName) {
1111 // Symbol Flags have been checked in the caller.
1112 uint32_t Symflags = cantFail(I->getFlags());
1113 if (ELFObjectFileBase *ELFObj = dyn_cast<ELFObjectFileBase>(&Obj)) {
1114 if (Symflags & object::SymbolRef::SF_Absolute)
1115 SecName = "*ABS*";
1116 else if (Symflags & object::SymbolRef::SF_Common)
1117 SecName = "*COM*";
1118 else if (Symflags & object::SymbolRef::SF_Undefined)
1119 SecName = "*UND*";
1120 else {
1121 elf_symbol_iterator SymI(I);
1122 Expected<elf_section_iterator> SecIOrErr = SymI->getSection();
1123 if (!SecIOrErr) {
1124 consumeError(SecIOrErr.takeError());
1125 return '?';
1128 if (*SecIOrErr == ELFObj->section_end())
1129 return '?';
1131 Expected<StringRef> NameOrErr = (*SecIOrErr)->getName();
1132 if (!NameOrErr) {
1133 consumeError(NameOrErr.takeError());
1134 return '?';
1136 SecName = *NameOrErr;
1140 if (Symflags & object::SymbolRef::SF_Undefined) {
1141 if (isa<MachOObjectFile>(Obj) || !(Symflags & object::SymbolRef::SF_Weak))
1142 return 'U';
1143 return isObject(Obj, I) ? 'v' : 'w';
1145 if (isa<ELFObjectFileBase>(&Obj))
1146 if (ELFSymbolRef(*I).getELFType() == ELF::STT_GNU_IFUNC)
1147 return 'i';
1148 if (!isa<MachOObjectFile>(Obj) && (Symflags & object::SymbolRef::SF_Weak))
1149 return isObject(Obj, I) ? 'V' : 'W';
1151 if (Symflags & object::SymbolRef::SF_Common)
1152 return 'C';
1154 char Ret = '?';
1155 if (Symflags & object::SymbolRef::SF_Absolute)
1156 Ret = 'a';
1157 else if (IRObjectFile *IR = dyn_cast<IRObjectFile>(&Obj))
1158 Ret = getSymbolNMTypeChar(*IR, I);
1159 else if (COFFObjectFile *COFF = dyn_cast<COFFObjectFile>(&Obj))
1160 Ret = getSymbolNMTypeChar(*COFF, I);
1161 else if (XCOFFObjectFile *XCOFF = dyn_cast<XCOFFObjectFile>(&Obj))
1162 Ret = getSymbolNMTypeChar(*XCOFF, I);
1163 else if (COFFImportFile *COFFImport = dyn_cast<COFFImportFile>(&Obj))
1164 Ret = getSymbolNMTypeChar(*COFFImport);
1165 else if (MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(&Obj))
1166 Ret = getSymbolNMTypeChar(*MachO, I);
1167 else if (WasmObjectFile *Wasm = dyn_cast<WasmObjectFile>(&Obj))
1168 Ret = getSymbolNMTypeChar(*Wasm, I);
1169 else if (TapiFile *Tapi = dyn_cast<TapiFile>(&Obj))
1170 Ret = getSymbolNMTypeChar(*Tapi, I);
1171 else if (ELFObjectFileBase *ELF = dyn_cast<ELFObjectFileBase>(&Obj)) {
1172 Ret = getSymbolNMTypeChar(*ELF, I);
1173 if (ELFSymbolRef(*I).getBinding() == ELF::STB_GNU_UNIQUE)
1174 return Ret;
1175 } else
1176 llvm_unreachable("unknown binary format");
1178 if (!(Symflags & object::SymbolRef::SF_Global))
1179 return Ret;
1181 return toupper(Ret);
1184 // getNsectForSegSect() is used to implement the Mach-O "-s segname sectname"
1185 // option to dump only those symbols from that section in a Mach-O file.
1186 // It is called once for each Mach-O file from getSymbolNamesFromObject()
1187 // to get the section number for that named section from the command line
1188 // arguments. It returns the section number for that section in the Mach-O
1189 // file or zero it is not present.
1190 static unsigned getNsectForSegSect(MachOObjectFile *Obj) {
1191 unsigned Nsect = 1;
1192 for (auto &S : Obj->sections()) {
1193 DataRefImpl Ref = S.getRawDataRefImpl();
1194 StringRef SectionName;
1195 if (Expected<StringRef> NameOrErr = Obj->getSectionName(Ref))
1196 SectionName = *NameOrErr;
1197 StringRef SegmentName = Obj->getSectionFinalSegmentName(Ref);
1198 if (SegmentName == SegSect[0] && SectionName == SegSect[1])
1199 return Nsect;
1200 Nsect++;
1202 return 0;
1205 // getNsectInMachO() is used to implement the Mach-O "-s segname sectname"
1206 // option to dump only those symbols from that section in a Mach-O file.
1207 // It is called once for each symbol in a Mach-O file from
1208 // getSymbolNamesFromObject() and returns the section number for that symbol
1209 // if it is in a section, else it returns 0.
1210 static unsigned getNsectInMachO(MachOObjectFile &Obj, BasicSymbolRef Sym) {
1211 DataRefImpl Symb = Sym.getRawDataRefImpl();
1212 if (Obj.is64Bit()) {
1213 MachO::nlist_64 STE = Obj.getSymbol64TableEntry(Symb);
1214 return (STE.n_type & MachO::N_TYPE) == MachO::N_SECT ? STE.n_sect : 0;
1216 MachO::nlist STE = Obj.getSymbolTableEntry(Symb);
1217 return (STE.n_type & MachO::N_TYPE) == MachO::N_SECT ? STE.n_sect : 0;
1220 static void dumpSymbolsFromDLInfoMachO(MachOObjectFile &MachO,
1221 std::vector<NMSymbol> &SymbolList) {
1222 size_t I = SymbolList.size();
1223 std::string ExportsNameBuffer;
1224 raw_string_ostream EOS(ExportsNameBuffer);
1225 std::string BindsNameBuffer;
1226 raw_string_ostream BOS(BindsNameBuffer);
1227 std::string LazysNameBuffer;
1228 raw_string_ostream LOS(LazysNameBuffer);
1229 std::string WeaksNameBuffer;
1230 raw_string_ostream WOS(WeaksNameBuffer);
1231 std::string FunctionStartsNameBuffer;
1232 raw_string_ostream FOS(FunctionStartsNameBuffer);
1234 MachO::mach_header H;
1235 MachO::mach_header_64 H_64;
1236 uint32_t HFlags = 0;
1237 if (MachO.is64Bit()) {
1238 H_64 = MachO.MachOObjectFile::getHeader64();
1239 HFlags = H_64.flags;
1240 } else {
1241 H = MachO.MachOObjectFile::getHeader();
1242 HFlags = H.flags;
1244 uint64_t BaseSegmentAddress = 0;
1245 for (const auto &Command : MachO.load_commands()) {
1246 if (Command.C.cmd == MachO::LC_SEGMENT) {
1247 MachO::segment_command Seg = MachO.getSegmentLoadCommand(Command);
1248 if (Seg.fileoff == 0 && Seg.filesize != 0) {
1249 BaseSegmentAddress = Seg.vmaddr;
1250 break;
1252 } else if (Command.C.cmd == MachO::LC_SEGMENT_64) {
1253 MachO::segment_command_64 Seg = MachO.getSegment64LoadCommand(Command);
1254 if (Seg.fileoff == 0 && Seg.filesize != 0) {
1255 BaseSegmentAddress = Seg.vmaddr;
1256 break;
1260 if (DyldInfoOnly || AddDyldInfo ||
1261 HFlags & MachO::MH_NLIST_OUTOFSYNC_WITH_DYLDINFO) {
1262 unsigned ExportsAdded = 0;
1263 Error Err = Error::success();
1264 for (const llvm::object::ExportEntry &Entry : MachO.exports(Err)) {
1265 bool found = false;
1266 bool ReExport = false;
1267 if (!DyldInfoOnly) {
1268 for (const NMSymbol &S : SymbolList)
1269 if (S.Address == Entry.address() + BaseSegmentAddress &&
1270 S.Name == Entry.name()) {
1271 found = true;
1272 break;
1275 if (!found) {
1276 NMSymbol S = {};
1277 S.Address = Entry.address() + BaseSegmentAddress;
1278 S.Size = 0;
1279 S.TypeChar = '\0';
1280 S.Name = Entry.name().str();
1281 // There is no symbol in the nlist symbol table for this so we set
1282 // Sym effectivly to null and the rest of code in here must test for
1283 // it and not do things like Sym.getFlags() for it.
1284 S.Sym = BasicSymbolRef();
1285 S.SymFlags = SymbolRef::SF_Global;
1286 S.Section = SectionRef();
1287 S.NType = 0;
1288 S.NSect = 0;
1289 S.NDesc = 0;
1291 uint64_t EFlags = Entry.flags();
1292 bool Abs = ((EFlags & MachO::EXPORT_SYMBOL_FLAGS_KIND_MASK) ==
1293 MachO::EXPORT_SYMBOL_FLAGS_KIND_ABSOLUTE);
1294 bool Resolver = (EFlags & MachO::EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER);
1295 ReExport = (EFlags & MachO::EXPORT_SYMBOL_FLAGS_REEXPORT);
1296 bool WeakDef = (EFlags & MachO::EXPORT_SYMBOL_FLAGS_WEAK_DEFINITION);
1297 if (WeakDef)
1298 S.NDesc |= MachO::N_WEAK_DEF;
1299 if (Abs) {
1300 S.NType = MachO::N_EXT | MachO::N_ABS;
1301 S.TypeChar = 'A';
1302 } else if (ReExport) {
1303 S.NType = MachO::N_EXT | MachO::N_INDR;
1304 S.TypeChar = 'I';
1305 } else {
1306 S.NType = MachO::N_EXT | MachO::N_SECT;
1307 if (Resolver) {
1308 S.Address = Entry.other() + BaseSegmentAddress;
1309 if ((S.Address & 1) != 0 && !MachO.is64Bit() &&
1310 H.cputype == MachO::CPU_TYPE_ARM) {
1311 S.Address &= ~1LL;
1312 S.NDesc |= MachO::N_ARM_THUMB_DEF;
1314 } else {
1315 S.Address = Entry.address() + BaseSegmentAddress;
1317 StringRef SegmentName = StringRef();
1318 StringRef SectionName = StringRef();
1319 for (const SectionRef &Section : MachO.sections()) {
1320 S.NSect++;
1322 if (Expected<StringRef> NameOrErr = Section.getName())
1323 SectionName = *NameOrErr;
1324 else
1325 consumeError(NameOrErr.takeError());
1327 SegmentName =
1328 MachO.getSectionFinalSegmentName(Section.getRawDataRefImpl());
1329 if (S.Address >= Section.getAddress() &&
1330 S.Address < Section.getAddress() + Section.getSize()) {
1331 S.Section = Section;
1332 break;
1333 } else if (Entry.name() == "__mh_execute_header" &&
1334 SegmentName == "__TEXT" && SectionName == "__text") {
1335 S.Section = Section;
1336 S.NDesc |= MachO::REFERENCED_DYNAMICALLY;
1337 break;
1340 if (SegmentName == "__TEXT" && SectionName == "__text")
1341 S.TypeChar = 'T';
1342 else if (SegmentName == "__DATA" && SectionName == "__data")
1343 S.TypeChar = 'D';
1344 else if (SegmentName == "__DATA" && SectionName == "__bss")
1345 S.TypeChar = 'B';
1346 else
1347 S.TypeChar = 'S';
1349 SymbolList.push_back(S);
1351 EOS << Entry.name();
1352 EOS << '\0';
1353 ExportsAdded++;
1355 // For ReExports there are a two more things to do, first add the
1356 // indirect name and second create the undefined symbol using the
1357 // referened dynamic library.
1358 if (ReExport) {
1360 // Add the indirect name.
1361 if (Entry.otherName().empty())
1362 EOS << Entry.name();
1363 else
1364 EOS << Entry.otherName();
1365 EOS << '\0';
1367 // Now create the undefined symbol using the referened dynamic
1368 // library.
1369 NMSymbol U = {};
1370 U.Address = 0;
1371 U.Size = 0;
1372 U.TypeChar = 'U';
1373 if (Entry.otherName().empty())
1374 U.Name = Entry.name().str();
1375 else
1376 U.Name = Entry.otherName().str();
1377 // Again there is no symbol in the nlist symbol table for this so
1378 // we set Sym effectivly to null and the rest of code in here must
1379 // test for it and not do things like Sym.getFlags() for it.
1380 U.Sym = BasicSymbolRef();
1381 U.SymFlags = SymbolRef::SF_Global | SymbolRef::SF_Undefined;
1382 U.Section = SectionRef();
1383 U.NType = MachO::N_EXT | MachO::N_UNDF;
1384 U.NSect = 0;
1385 U.NDesc = 0;
1386 // The library ordinal for this undefined symbol is in the export
1387 // trie Entry.other().
1388 MachO::SET_LIBRARY_ORDINAL(U.NDesc, Entry.other());
1389 SymbolList.push_back(U);
1391 // Finally add the undefined symbol's name.
1392 if (Entry.otherName().empty())
1393 EOS << Entry.name();
1394 else
1395 EOS << Entry.otherName();
1396 EOS << '\0';
1397 ExportsAdded++;
1401 if (Err)
1402 error(std::move(Err), MachO.getFileName());
1403 // Set the symbol names and indirect names for the added symbols.
1404 if (ExportsAdded) {
1405 EOS.flush();
1406 const char *Q = ExportsNameBuffer.c_str();
1407 for (unsigned K = 0; K < ExportsAdded; K++) {
1408 SymbolList[I].Name = Q;
1409 Q += strlen(Q) + 1;
1410 if (SymbolList[I].TypeChar == 'I') {
1411 SymbolList[I].IndirectName = Q;
1412 Q += strlen(Q) + 1;
1414 I++;
1418 // Add the undefined symbols from the bind entries.
1419 unsigned BindsAdded = 0;
1420 Error BErr = Error::success();
1421 StringRef LastSymbolName = StringRef();
1422 for (const llvm::object::MachOBindEntry &Entry : MachO.bindTable(BErr)) {
1423 bool found = false;
1424 if (LastSymbolName == Entry.symbolName())
1425 found = true;
1426 else if (!DyldInfoOnly) {
1427 for (unsigned J = 0; J < SymbolList.size() && !found; ++J) {
1428 if (SymbolList[J].Name == Entry.symbolName())
1429 found = true;
1432 if (!found) {
1433 LastSymbolName = Entry.symbolName();
1434 NMSymbol B = {};
1435 B.Address = 0;
1436 B.Size = 0;
1437 B.TypeChar = 'U';
1438 // There is no symbol in the nlist symbol table for this so we set
1439 // Sym effectivly to null and the rest of code in here must test for
1440 // it and not do things like Sym.getFlags() for it.
1441 B.Sym = BasicSymbolRef();
1442 B.SymFlags = SymbolRef::SF_Global | SymbolRef::SF_Undefined;
1443 B.NType = MachO::N_EXT | MachO::N_UNDF;
1444 B.NSect = 0;
1445 B.NDesc = 0;
1446 MachO::SET_LIBRARY_ORDINAL(B.NDesc, Entry.ordinal());
1447 B.Name = Entry.symbolName().str();
1448 SymbolList.push_back(B);
1449 BOS << Entry.symbolName();
1450 BOS << '\0';
1451 BindsAdded++;
1454 if (BErr)
1455 error(std::move(BErr), MachO.getFileName());
1456 // Set the symbol names and indirect names for the added symbols.
1457 if (BindsAdded) {
1458 BOS.flush();
1459 const char *Q = BindsNameBuffer.c_str();
1460 for (unsigned K = 0; K < BindsAdded; K++) {
1461 SymbolList[I].Name = Q;
1462 Q += strlen(Q) + 1;
1463 if (SymbolList[I].TypeChar == 'I') {
1464 SymbolList[I].IndirectName = Q;
1465 Q += strlen(Q) + 1;
1467 I++;
1471 // Add the undefined symbols from the lazy bind entries.
1472 unsigned LazysAdded = 0;
1473 Error LErr = Error::success();
1474 LastSymbolName = StringRef();
1475 for (const llvm::object::MachOBindEntry &Entry :
1476 MachO.lazyBindTable(LErr)) {
1477 bool found = false;
1478 if (LastSymbolName == Entry.symbolName())
1479 found = true;
1480 else {
1481 // Here we must check to see it this symbol is already in the
1482 // SymbolList as it might have already have been added above via a
1483 // non-lazy (bind) entry.
1484 for (unsigned J = 0; J < SymbolList.size() && !found; ++J) {
1485 if (SymbolList[J].Name == Entry.symbolName())
1486 found = true;
1489 if (!found) {
1490 LastSymbolName = Entry.symbolName();
1491 NMSymbol L = {};
1492 L.Name = Entry.symbolName().str();
1493 L.Address = 0;
1494 L.Size = 0;
1495 L.TypeChar = 'U';
1496 // There is no symbol in the nlist symbol table for this so we set
1497 // Sym effectivly to null and the rest of code in here must test for
1498 // it and not do things like Sym.getFlags() for it.
1499 L.Sym = BasicSymbolRef();
1500 L.SymFlags = SymbolRef::SF_Global | SymbolRef::SF_Undefined;
1501 L.NType = MachO::N_EXT | MachO::N_UNDF;
1502 L.NSect = 0;
1503 // The REFERENCE_FLAG_UNDEFINED_LAZY is no longer used but here it
1504 // makes sence since we are creating this from a lazy bind entry.
1505 L.NDesc = MachO::REFERENCE_FLAG_UNDEFINED_LAZY;
1506 MachO::SET_LIBRARY_ORDINAL(L.NDesc, Entry.ordinal());
1507 SymbolList.push_back(L);
1508 LOS << Entry.symbolName();
1509 LOS << '\0';
1510 LazysAdded++;
1513 if (LErr)
1514 error(std::move(LErr), MachO.getFileName());
1515 // Set the symbol names and indirect names for the added symbols.
1516 if (LazysAdded) {
1517 LOS.flush();
1518 const char *Q = LazysNameBuffer.c_str();
1519 for (unsigned K = 0; K < LazysAdded; K++) {
1520 SymbolList[I].Name = Q;
1521 Q += strlen(Q) + 1;
1522 if (SymbolList[I].TypeChar == 'I') {
1523 SymbolList[I].IndirectName = Q;
1524 Q += strlen(Q) + 1;
1526 I++;
1530 // Add the undefineds symbol from the weak bind entries which are not
1531 // strong symbols.
1532 unsigned WeaksAdded = 0;
1533 Error WErr = Error::success();
1534 LastSymbolName = StringRef();
1535 for (const llvm::object::MachOBindEntry &Entry :
1536 MachO.weakBindTable(WErr)) {
1537 bool found = false;
1538 unsigned J = 0;
1539 if (LastSymbolName == Entry.symbolName() ||
1540 Entry.flags() & MachO::BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION) {
1541 found = true;
1542 } else {
1543 for (J = 0; J < SymbolList.size() && !found; ++J) {
1544 if (SymbolList[J].Name == Entry.symbolName()) {
1545 found = true;
1546 break;
1550 if (!found) {
1551 LastSymbolName = Entry.symbolName();
1552 NMSymbol W = {};
1553 W.Name = Entry.symbolName().str();
1554 W.Address = 0;
1555 W.Size = 0;
1556 W.TypeChar = 'U';
1557 // There is no symbol in the nlist symbol table for this so we set
1558 // Sym effectivly to null and the rest of code in here must test for
1559 // it and not do things like Sym.getFlags() for it.
1560 W.Sym = BasicSymbolRef();
1561 W.SymFlags = SymbolRef::SF_Global | SymbolRef::SF_Undefined;
1562 W.NType = MachO::N_EXT | MachO::N_UNDF;
1563 W.NSect = 0;
1564 // Odd that we are using N_WEAK_DEF on an undefined symbol but that is
1565 // what is created in this case by the linker when there are real
1566 // symbols in the nlist structs.
1567 W.NDesc = MachO::N_WEAK_DEF;
1568 SymbolList.push_back(W);
1569 WOS << Entry.symbolName();
1570 WOS << '\0';
1571 WeaksAdded++;
1572 } else {
1573 // This is the case the symbol was previously been found and it could
1574 // have been added from a bind or lazy bind symbol. If so and not
1575 // a definition also mark it as weak.
1576 if (SymbolList[J].TypeChar == 'U')
1577 // See comment above about N_WEAK_DEF.
1578 SymbolList[J].NDesc |= MachO::N_WEAK_DEF;
1581 if (WErr)
1582 error(std::move(WErr), MachO.getFileName());
1583 // Set the symbol names and indirect names for the added symbols.
1584 if (WeaksAdded) {
1585 WOS.flush();
1586 const char *Q = WeaksNameBuffer.c_str();
1587 for (unsigned K = 0; K < WeaksAdded; K++) {
1588 SymbolList[I].Name = Q;
1589 Q += strlen(Q) + 1;
1590 if (SymbolList[I].TypeChar == 'I') {
1591 SymbolList[I].IndirectName = Q;
1592 Q += strlen(Q) + 1;
1594 I++;
1598 // Trying adding symbol from the function starts table and LC_MAIN entry
1599 // point.
1600 SmallVector<uint64_t, 8> FoundFns;
1601 uint64_t lc_main_offset = UINT64_MAX;
1602 for (const auto &Command : MachO.load_commands()) {
1603 if (Command.C.cmd == MachO::LC_FUNCTION_STARTS) {
1604 // We found a function starts segment, parse the addresses for
1605 // consumption.
1606 MachO::linkedit_data_command LLC =
1607 MachO.getLinkeditDataLoadCommand(Command);
1609 MachO.ReadULEB128s(LLC.dataoff, FoundFns);
1610 } else if (Command.C.cmd == MachO::LC_MAIN) {
1611 MachO::entry_point_command LCmain = MachO.getEntryPointCommand(Command);
1612 lc_main_offset = LCmain.entryoff;
1615 // See if these addresses are already in the symbol table.
1616 unsigned FunctionStartsAdded = 0;
1617 for (uint64_t f = 0; f < FoundFns.size(); f++) {
1618 bool found = false;
1619 for (unsigned J = 0; J < SymbolList.size() && !found; ++J) {
1620 if (SymbolList[J].Address == FoundFns[f] + BaseSegmentAddress)
1621 found = true;
1623 // See this address is not already in the symbol table fake up an
1624 // nlist for it.
1625 if (!found) {
1626 NMSymbol F = {};
1627 F.Name = "<redacted function X>";
1628 F.Address = FoundFns[f] + BaseSegmentAddress;
1629 F.Size = 0;
1630 // There is no symbol in the nlist symbol table for this so we set
1631 // Sym effectivly to null and the rest of code in here must test for
1632 // it and not do things like Sym.getFlags() for it.
1633 F.Sym = BasicSymbolRef();
1634 F.SymFlags = 0;
1635 F.NType = MachO::N_SECT;
1636 F.NSect = 0;
1637 StringRef SegmentName = StringRef();
1638 StringRef SectionName = StringRef();
1639 for (const SectionRef &Section : MachO.sections()) {
1640 if (Expected<StringRef> NameOrErr = Section.getName())
1641 SectionName = *NameOrErr;
1642 else
1643 consumeError(NameOrErr.takeError());
1645 SegmentName =
1646 MachO.getSectionFinalSegmentName(Section.getRawDataRefImpl());
1647 F.NSect++;
1648 if (F.Address >= Section.getAddress() &&
1649 F.Address < Section.getAddress() + Section.getSize()) {
1650 F.Section = Section;
1651 break;
1654 if (SegmentName == "__TEXT" && SectionName == "__text")
1655 F.TypeChar = 't';
1656 else if (SegmentName == "__DATA" && SectionName == "__data")
1657 F.TypeChar = 'd';
1658 else if (SegmentName == "__DATA" && SectionName == "__bss")
1659 F.TypeChar = 'b';
1660 else
1661 F.TypeChar = 's';
1662 F.NDesc = 0;
1663 SymbolList.push_back(F);
1664 if (FoundFns[f] == lc_main_offset)
1665 FOS << "<redacted LC_MAIN>";
1666 else
1667 FOS << "<redacted function " << f << ">";
1668 FOS << '\0';
1669 FunctionStartsAdded++;
1672 if (FunctionStartsAdded) {
1673 FOS.flush();
1674 const char *Q = FunctionStartsNameBuffer.c_str();
1675 for (unsigned K = 0; K < FunctionStartsAdded; K++) {
1676 SymbolList[I].Name = Q;
1677 Q += strlen(Q) + 1;
1678 if (SymbolList[I].TypeChar == 'I') {
1679 SymbolList[I].IndirectName = Q;
1680 Q += strlen(Q) + 1;
1682 I++;
1688 static bool shouldDump(SymbolicFile &Obj) {
1689 // The -X option is currently only implemented for XCOFF, ELF, and IR object
1690 // files. The option isn't fundamentally impossible with other formats, just
1691 // isn't implemented.
1692 if (!isa<XCOFFObjectFile>(Obj) && !isa<ELFObjectFileBase>(Obj) &&
1693 !isa<IRObjectFile>(Obj))
1694 return true;
1696 return Obj.is64Bit() ? BitMode != BitModeTy::Bit32
1697 : BitMode != BitModeTy::Bit64;
1700 static void getXCOFFExports(XCOFFObjectFile *XCOFFObj,
1701 std::vector<NMSymbol> &SymbolList,
1702 StringRef ArchiveName) {
1703 // Skip Shared object file.
1704 if (XCOFFObj->getFlags() & XCOFF::F_SHROBJ)
1705 return;
1707 for (SymbolRef Sym : XCOFFObj->symbols()) {
1708 // There is no visibility in old 32 bit XCOFF object file interpret.
1709 bool HasVisibilityAttr =
1710 XCOFFObj->is64Bit() || (XCOFFObj->auxiliaryHeader32() &&
1711 (XCOFFObj->auxiliaryHeader32()->getVersion() ==
1712 XCOFF::NEW_XCOFF_INTERPRET));
1714 if (HasVisibilityAttr) {
1715 XCOFFSymbolRef XCOFFSym = XCOFFObj->toSymbolRef(Sym.getRawDataRefImpl());
1716 uint16_t SymType = XCOFFSym.getSymbolType();
1717 if ((SymType & XCOFF::VISIBILITY_MASK) == XCOFF::SYM_V_INTERNAL)
1718 continue;
1719 if ((SymType & XCOFF::VISIBILITY_MASK) == XCOFF::SYM_V_HIDDEN)
1720 continue;
1723 Expected<section_iterator> SymSecOrErr = Sym.getSection();
1724 if (!SymSecOrErr) {
1725 warn(SymSecOrErr.takeError(), XCOFFObj->getFileName(),
1726 "for symbol with index " +
1727 Twine(XCOFFObj->getSymbolIndex(Sym.getRawDataRefImpl().p)),
1728 ArchiveName);
1729 continue;
1731 section_iterator SecIter = *SymSecOrErr;
1732 // If the symbol is not in a text or data section, it is not exported.
1733 if (SecIter == XCOFFObj->section_end())
1734 continue;
1735 if (!(SecIter->isText() || SecIter->isData() || SecIter->isBSS()))
1736 continue;
1738 StringRef SymName = cantFail(Sym.getName());
1739 if (SymName.empty())
1740 continue;
1741 if (SymName.startswith("__sinit") || SymName.startswith("__sterm") ||
1742 SymName.front() == '.' || SymName.front() == '(')
1743 continue;
1745 // Check the SymName regex matching with "^__[0-9]+__".
1746 if (SymName.size() > 4 && SymName.startswith("__") &&
1747 SymName.endswith("__")) {
1748 if (std::all_of(SymName.begin() + 2, SymName.end() - 2, isDigit))
1749 continue;
1752 if (SymName == "__rsrc" && NoRsrc)
1753 continue;
1755 if (SymName.startswith("__tf1"))
1756 SymName = SymName.substr(6);
1757 else if (SymName.startswith("__tf9"))
1758 SymName = SymName.substr(14);
1760 NMSymbol S = {};
1761 S.Name = SymName.str();
1762 S.Sym = Sym;
1764 if (HasVisibilityAttr) {
1765 XCOFFSymbolRef XCOFFSym = XCOFFObj->toSymbolRef(Sym.getRawDataRefImpl());
1766 uint16_t SymType = XCOFFSym.getSymbolType();
1767 if ((SymType & XCOFF::VISIBILITY_MASK) == XCOFF::SYM_V_PROTECTED)
1768 S.Visibility = "protected";
1769 else if ((SymType & XCOFF::VISIBILITY_MASK) == XCOFF::SYM_V_EXPORTED)
1770 S.Visibility = "export";
1772 if (S.initializeFlags(*XCOFFObj))
1773 SymbolList.push_back(S);
1777 static Expected<SymbolicFile::basic_symbol_iterator_range>
1778 getDynamicSyms(SymbolicFile &Obj) {
1779 const auto *E = dyn_cast<ELFObjectFileBase>(&Obj);
1780 if (!E)
1781 return createError("File format has no dynamic symbol table");
1782 return E->getDynamicSymbolIterators();
1785 // Returns false if there is error found or true otherwise.
1786 static bool getSymbolNamesFromObject(SymbolicFile &Obj,
1787 std::vector<NMSymbol> &SymbolList) {
1788 auto Symbols = Obj.symbols();
1789 std::vector<VersionEntry> SymbolVersions;
1791 if (DynamicSyms) {
1792 Expected<SymbolicFile::basic_symbol_iterator_range> SymbolsOrErr =
1793 getDynamicSyms(Obj);
1794 if (!SymbolsOrErr) {
1795 error(SymbolsOrErr.takeError(), Obj.getFileName());
1796 return false;
1798 Symbols = *SymbolsOrErr;
1799 if (const auto *E = dyn_cast<ELFObjectFileBase>(&Obj)) {
1800 if (Expected<std::vector<VersionEntry>> VersionsOrErr =
1801 E->readDynsymVersions())
1802 SymbolVersions = std::move(*VersionsOrErr);
1803 else
1804 WithColor::warning(errs(), ToolName)
1805 << "unable to read symbol versions: "
1806 << toString(VersionsOrErr.takeError()) << "\n";
1809 // If a "-s segname sectname" option was specified and this is a Mach-O
1810 // file get the section number for that section in this object file.
1811 unsigned int Nsect = 0;
1812 MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(&Obj);
1813 if (!SegSect.empty() && MachO) {
1814 Nsect = getNsectForSegSect(MachO);
1815 // If this section is not in the object file no symbols are printed.
1816 if (Nsect == 0)
1817 return false;
1820 if (!(MachO && DyldInfoOnly)) {
1821 size_t I = -1;
1822 for (BasicSymbolRef Sym : Symbols) {
1823 ++I;
1824 Expected<uint32_t> SymFlagsOrErr = Sym.getFlags();
1825 if (!SymFlagsOrErr) {
1826 error(SymFlagsOrErr.takeError(), Obj.getFileName());
1827 return false;
1830 // Don't drop format specifc symbols for ARM and AArch64 ELF targets, they
1831 // are used to repesent mapping symbols and needed to honor the
1832 // --special-syms option.
1833 auto *ELFObj = dyn_cast<ELFObjectFileBase>(&Obj);
1834 bool HasMappingSymbol =
1835 ELFObj && llvm::is_contained({ELF::EM_ARM, ELF::EM_AARCH64,
1836 ELF::EM_CSKY, ELF::EM_RISCV},
1837 ELFObj->getEMachine());
1838 if (!HasMappingSymbol && !DebugSyms &&
1839 (*SymFlagsOrErr & SymbolRef::SF_FormatSpecific))
1840 continue;
1841 if (WithoutAliases && (*SymFlagsOrErr & SymbolRef::SF_Indirect))
1842 continue;
1843 // If a "-s segname sectname" option was specified and this is a Mach-O
1844 // file and this section appears in this file, Nsect will be non-zero then
1845 // see if this symbol is a symbol from that section and if not skip it.
1846 if (Nsect && Nsect != getNsectInMachO(*MachO, Sym))
1847 continue;
1848 NMSymbol S = {};
1849 S.Size = 0;
1850 S.Address = 0;
1851 if (isa<ELFObjectFileBase>(&Obj))
1852 S.Size = ELFSymbolRef(Sym).getSize();
1854 if (const XCOFFObjectFile *XCOFFObj =
1855 dyn_cast<const XCOFFObjectFile>(&Obj))
1856 S.Size = XCOFFObj->getSymbolSize(Sym.getRawDataRefImpl());
1858 if (const WasmObjectFile *WasmObj = dyn_cast<WasmObjectFile>(&Obj)) {
1859 const WasmSymbol &WasmSym = WasmObj->getWasmSymbol(Sym);
1860 if (WasmSym.isTypeData() && !WasmSym.isUndefined())
1861 S.Size = WasmSym.Info.DataRef.Size;
1864 if (PrintAddress && isa<ObjectFile>(Obj)) {
1865 SymbolRef SymRef(Sym);
1866 Expected<uint64_t> AddressOrErr = SymRef.getAddress();
1867 if (!AddressOrErr) {
1868 consumeError(AddressOrErr.takeError());
1869 break;
1871 S.Address = *AddressOrErr;
1873 S.TypeName = getNMTypeName(Obj, Sym);
1874 S.TypeChar = getNMSectionTagAndName(Obj, Sym, S.SectionName);
1876 raw_string_ostream OS(S.Name);
1877 if (Error E = Sym.printName(OS)) {
1878 if (MachO) {
1879 OS << "bad string index";
1880 consumeError(std::move(E));
1881 } else
1882 error(std::move(E), Obj.getFileName());
1884 if (!SymbolVersions.empty() && !SymbolVersions[I].Name.empty())
1885 S.Name +=
1886 (SymbolVersions[I].IsVerDef ? "@@" : "@") + SymbolVersions[I].Name;
1888 S.Sym = Sym;
1889 if (S.initializeFlags(Obj))
1890 SymbolList.push_back(S);
1894 // If this is a Mach-O file where the nlist symbol table is out of sync
1895 // with the dyld export trie then look through exports and fake up symbols
1896 // for the ones that are missing (also done with the -add-dyldinfo flag).
1897 // This is needed if strip(1) -T is run on a binary containing swift
1898 // language symbols for example. The option -only-dyldinfo will fake up
1899 // all symbols from the dyld export trie as well as the bind info.
1900 if (MachO && !NoDyldInfo)
1901 dumpSymbolsFromDLInfoMachO(*MachO, SymbolList);
1903 return true;
1906 static void printObjectLabel(bool PrintArchiveName, StringRef ArchiveName,
1907 StringRef ArchitectureName,
1908 StringRef ObjectFileName) {
1909 outs() << "\n";
1910 if (ArchiveName.empty() || !PrintArchiveName)
1911 outs() << ObjectFileName;
1912 else
1913 outs() << ArchiveName << "(" << ObjectFileName << ")";
1914 if (!ArchitectureName.empty())
1915 outs() << " (for architecture " << ArchitectureName << ")";
1916 outs() << ":\n";
1919 static Expected<bool> hasSymbols(SymbolicFile &Obj) {
1920 if (DynamicSyms) {
1921 Expected<SymbolicFile::basic_symbol_iterator_range> DynamicSymsOrErr =
1922 getDynamicSyms(Obj);
1923 if (!DynamicSymsOrErr)
1924 return DynamicSymsOrErr.takeError();
1925 return !DynamicSymsOrErr->empty();
1927 return !Obj.symbols().empty();
1930 static void printSymbolNamesFromObject(
1931 SymbolicFile &Obj, std::vector<NMSymbol> &SymbolList,
1932 bool PrintSymbolObject, bool PrintObjectLabel, StringRef ArchiveName = {},
1933 StringRef ArchitectureName = {}, StringRef ObjectName = {},
1934 bool PrintArchiveName = true) {
1936 if (PrintObjectLabel && !ExportSymbols)
1937 printObjectLabel(PrintArchiveName, ArchiveName, ArchitectureName,
1938 ObjectName.empty() ? Obj.getFileName() : ObjectName);
1940 if (!getSymbolNamesFromObject(Obj, SymbolList) || ExportSymbols)
1941 return;
1943 // If there is an error in hasSymbols(), the error should be encountered in
1944 // function getSymbolNamesFromObject first.
1945 if (!cantFail(hasSymbols(Obj)) && SymbolList.empty() && !Quiet) {
1946 writeFileName(errs(), ArchiveName, ArchitectureName);
1947 errs() << "no symbols\n";
1950 sortSymbolList(SymbolList);
1951 printSymbolList(Obj, SymbolList, PrintSymbolObject, ArchiveName,
1952 ArchitectureName);
1955 static void dumpSymbolsNameFromMachOFilesetEntry(
1956 MachOObjectFile *Obj, std::vector<NMSymbol> &SymbolList,
1957 bool PrintSymbolObject, bool PrintObjectLabel) {
1958 auto Buf = Obj->getMemoryBufferRef();
1959 const auto *End = Obj->load_commands().end();
1960 for (const auto *It = Obj->load_commands().begin(); It != End; ++It) {
1961 const auto &Command = *It;
1962 if (Command.C.cmd != MachO::LC_FILESET_ENTRY)
1963 continue;
1965 MachO::fileset_entry_command Entry =
1966 Obj->getFilesetEntryLoadCommand(Command);
1967 auto MaybeMachO =
1968 MachOObjectFile::createMachOObjectFile(Buf, 0, 0, Entry.fileoff);
1970 if (Error Err = MaybeMachO.takeError())
1971 report_fatal_error(std::move(Err));
1973 const char *EntryName = Command.Ptr + Entry.entry_id.offset;
1974 if (EntryName)
1975 outs() << "Symbols for " << EntryName << ": \n";
1977 std::unique_ptr<MachOObjectFile> EntryMachO = std::move(MaybeMachO.get());
1978 printSymbolNamesFromObject(*EntryMachO, SymbolList, PrintSymbolObject,
1979 PrintObjectLabel);
1981 if (std::next(It) != End)
1982 outs() << "\n";
1986 static void dumpSymbolNamesFromObject(
1987 SymbolicFile &Obj, std::vector<NMSymbol> &SymbolList,
1988 bool PrintSymbolObject, bool PrintObjectLabel, StringRef ArchiveName = {},
1989 StringRef ArchitectureName = {}, StringRef ObjectName = {},
1990 bool PrintArchiveName = true) {
1991 if (!shouldDump(Obj))
1992 return;
1994 if (ExportSymbols && Obj.isXCOFF()) {
1995 XCOFFObjectFile *XCOFFObj = cast<XCOFFObjectFile>(&Obj);
1996 getXCOFFExports(XCOFFObj, SymbolList, ArchiveName);
1997 return;
2000 CurrentFilename = Obj.getFileName();
2002 // Are we handling a MachO of type MH_FILESET?
2003 if (Obj.isMachO() && Obj.is64Bit() &&
2004 cast<MachOObjectFile>(&Obj)->getHeader64().filetype ==
2005 MachO::MH_FILESET) {
2006 dumpSymbolsNameFromMachOFilesetEntry(cast<MachOObjectFile>(&Obj),
2007 SymbolList, PrintSymbolObject,
2008 PrintObjectLabel);
2009 return;
2012 printSymbolNamesFromObject(Obj, SymbolList, PrintSymbolObject,
2013 PrintObjectLabel, ArchiveName, ArchitectureName,
2014 ObjectName, PrintArchiveName);
2017 // checkMachOAndArchFlags() checks to see if the SymbolicFile is a Mach-O file
2018 // and if it is and there is a list of architecture flags is specified then
2019 // check to make sure this Mach-O file is one of those architectures or all
2020 // architectures was specificed. If not then an error is generated and this
2021 // routine returns false. Else it returns true.
2022 static bool checkMachOAndArchFlags(SymbolicFile *O, StringRef Filename) {
2023 auto *MachO = dyn_cast<MachOObjectFile>(O);
2025 if (!MachO || ArchAll || ArchFlags.empty())
2026 return true;
2028 MachO::mach_header H;
2029 MachO::mach_header_64 H_64;
2030 Triple T;
2031 const char *McpuDefault, *ArchFlag;
2032 if (MachO->is64Bit()) {
2033 H_64 = MachO->MachOObjectFile::getHeader64();
2034 T = MachOObjectFile::getArchTriple(H_64.cputype, H_64.cpusubtype,
2035 &McpuDefault, &ArchFlag);
2036 } else {
2037 H = MachO->MachOObjectFile::getHeader();
2038 T = MachOObjectFile::getArchTriple(H.cputype, H.cpusubtype,
2039 &McpuDefault, &ArchFlag);
2041 const std::string ArchFlagName(ArchFlag);
2042 if (!llvm::is_contained(ArchFlags, ArchFlagName)) {
2043 error("No architecture specified", Filename);
2044 return false;
2046 return true;
2049 static void printArchiveMap(iterator_range<Archive::symbol_iterator> &map,
2050 StringRef Filename) {
2051 for (auto I : map) {
2052 Expected<Archive::Child> C = I.getMember();
2053 if (!C) {
2054 error(C.takeError(), Filename);
2055 break;
2057 Expected<StringRef> FileNameOrErr = C->getName();
2058 if (!FileNameOrErr) {
2059 error(FileNameOrErr.takeError(), Filename);
2060 break;
2062 StringRef SymName = I.getName();
2063 outs() << SymName << " in " << FileNameOrErr.get() << "\n";
2066 outs() << "\n";
2069 static void dumpArchiveMap(Archive *A, StringRef Filename) {
2070 auto Map = A->symbols();
2071 if (!Map.empty()) {
2072 outs() << "Archive map\n";
2073 printArchiveMap(Map, Filename);
2076 auto ECMap = A->ec_symbols();
2077 if (!ECMap) {
2078 warn(ECMap.takeError(), Filename);
2079 } else if (!ECMap->empty()) {
2080 outs() << "Archive EC map\n";
2081 printArchiveMap(*ECMap, Filename);
2085 static void dumpArchive(Archive *A, std::vector<NMSymbol> &SymbolList,
2086 StringRef Filename, LLVMContext *ContextPtr) {
2087 if (ArchiveMap)
2088 dumpArchiveMap(A, Filename);
2090 Error Err = Error::success();
2091 for (auto &C : A->children(Err)) {
2092 Expected<std::unique_ptr<Binary>> ChildOrErr = C.getAsBinary(ContextPtr);
2093 if (!ChildOrErr) {
2094 if (auto E = isNotObjectErrorInvalidFileType(ChildOrErr.takeError()))
2095 error(std::move(E), Filename, C);
2096 continue;
2098 if (SymbolicFile *O = dyn_cast<SymbolicFile>(&*ChildOrErr.get())) {
2099 if (!MachOPrintSizeWarning && PrintSize && isa<MachOObjectFile>(O)) {
2100 WithColor::warning(errs(), ToolName)
2101 << "sizes with -print-size for Mach-O files are always zero.\n";
2102 MachOPrintSizeWarning = true;
2104 if (!checkMachOAndArchFlags(O, Filename))
2105 return;
2106 dumpSymbolNamesFromObject(*O, SymbolList, /*PrintSymbolObject=*/false,
2107 !PrintFileName, Filename,
2108 /*ArchitectureName=*/{}, O->getFileName(),
2109 /*PrintArchiveName=*/false);
2112 if (Err)
2113 error(std::move(Err), A->getFileName());
2116 static void dumpMachOUniversalBinaryMatchArchFlags(
2117 MachOUniversalBinary *UB, std::vector<NMSymbol> &SymbolList,
2118 StringRef Filename, LLVMContext *ContextPtr) {
2119 // Look for a slice in the universal binary that matches each ArchFlag.
2120 bool ArchFound;
2121 for (unsigned i = 0; i < ArchFlags.size(); ++i) {
2122 ArchFound = false;
2123 for (MachOUniversalBinary::object_iterator I = UB->begin_objects(),
2124 E = UB->end_objects();
2125 I != E; ++I) {
2126 if (ArchFlags[i] == I->getArchFlagName()) {
2127 ArchFound = true;
2128 Expected<std::unique_ptr<ObjectFile>> ObjOrErr = I->getAsObjectFile();
2129 std::string ArchiveName;
2130 std::string ArchitectureName;
2131 ArchiveName.clear();
2132 ArchitectureName.clear();
2133 if (ObjOrErr) {
2134 ObjectFile &Obj = *ObjOrErr.get();
2135 if (ArchFlags.size() > 1)
2136 ArchitectureName = I->getArchFlagName();
2137 dumpSymbolNamesFromObject(Obj, SymbolList,
2138 /*PrintSymbolObject=*/false,
2139 (ArchFlags.size() > 1) && !PrintFileName,
2140 ArchiveName, ArchitectureName);
2141 } else if (auto E =
2142 isNotObjectErrorInvalidFileType(ObjOrErr.takeError())) {
2143 error(std::move(E), Filename,
2144 ArchFlags.size() > 1 ? StringRef(I->getArchFlagName())
2145 : StringRef());
2146 continue;
2147 } else if (Expected<std::unique_ptr<Archive>> AOrErr =
2148 I->getAsArchive()) {
2149 std::unique_ptr<Archive> &A = *AOrErr;
2150 Error Err = Error::success();
2151 for (auto &C : A->children(Err)) {
2152 Expected<std::unique_ptr<Binary>> ChildOrErr =
2153 C.getAsBinary(ContextPtr);
2154 if (!ChildOrErr) {
2155 if (auto E =
2156 isNotObjectErrorInvalidFileType(ChildOrErr.takeError())) {
2157 error(std::move(E), Filename, C,
2158 ArchFlags.size() > 1 ? StringRef(I->getArchFlagName())
2159 : StringRef());
2161 continue;
2163 if (SymbolicFile *O = dyn_cast<SymbolicFile>(&*ChildOrErr.get())) {
2164 ArchiveName = std::string(A->getFileName());
2165 if (ArchFlags.size() > 1)
2166 ArchitectureName = I->getArchFlagName();
2167 dumpSymbolNamesFromObject(
2168 *O, SymbolList, /*PrintSymbolObject=*/false, !PrintFileName,
2169 ArchiveName, ArchitectureName);
2172 if (Err)
2173 error(std::move(Err), A->getFileName());
2174 } else {
2175 consumeError(AOrErr.takeError());
2176 error(Filename + " for architecture " +
2177 StringRef(I->getArchFlagName()) +
2178 " is not a Mach-O file or an archive file",
2179 "Mach-O universal file");
2183 if (!ArchFound) {
2184 error(ArchFlags[i],
2185 "file: " + Filename + " does not contain architecture");
2186 return;
2191 // Returns true If the binary contains a slice that matches the host
2192 // architecture, or false otherwise.
2193 static bool dumpMachOUniversalBinaryMatchHost(MachOUniversalBinary *UB,
2194 std::vector<NMSymbol> &SymbolList,
2195 StringRef Filename,
2196 LLVMContext *ContextPtr) {
2197 Triple HostTriple = MachOObjectFile::getHostArch();
2198 StringRef HostArchName = HostTriple.getArchName();
2199 for (MachOUniversalBinary::object_iterator I = UB->begin_objects(),
2200 E = UB->end_objects();
2201 I != E; ++I) {
2202 if (HostArchName == I->getArchFlagName()) {
2203 Expected<std::unique_ptr<ObjectFile>> ObjOrErr = I->getAsObjectFile();
2204 std::string ArchiveName;
2205 if (ObjOrErr) {
2206 ObjectFile &Obj = *ObjOrErr.get();
2207 dumpSymbolNamesFromObject(Obj, SymbolList, /*PrintSymbolObject=*/false,
2208 /*PrintObjectLabel=*/false);
2209 } else if (auto E = isNotObjectErrorInvalidFileType(ObjOrErr.takeError()))
2210 error(std::move(E), Filename);
2211 else if (Expected<std::unique_ptr<Archive>> AOrErr = I->getAsArchive()) {
2212 std::unique_ptr<Archive> &A = *AOrErr;
2213 Error Err = Error::success();
2214 for (auto &C : A->children(Err)) {
2215 Expected<std::unique_ptr<Binary>> ChildOrErr =
2216 C.getAsBinary(ContextPtr);
2217 if (!ChildOrErr) {
2218 if (auto E =
2219 isNotObjectErrorInvalidFileType(ChildOrErr.takeError()))
2220 error(std::move(E), Filename, C);
2221 continue;
2223 if (SymbolicFile *O = dyn_cast<SymbolicFile>(&*ChildOrErr.get())) {
2224 ArchiveName = std::string(A->getFileName());
2225 dumpSymbolNamesFromObject(*O, SymbolList,
2226 /*PrintSymbolObject=*/false,
2227 !PrintFileName, ArchiveName);
2230 if (Err)
2231 error(std::move(Err), A->getFileName());
2232 } else {
2233 consumeError(AOrErr.takeError());
2234 error(Filename + " for architecture " +
2235 StringRef(I->getArchFlagName()) +
2236 " is not a Mach-O file or an archive file",
2237 "Mach-O universal file");
2239 return true;
2242 return false;
2245 static void dumpMachOUniversalBinaryArchAll(MachOUniversalBinary *UB,
2246 std::vector<NMSymbol> &SymbolList,
2247 StringRef Filename,
2248 LLVMContext *ContextPtr) {
2249 bool moreThanOneArch = UB->getNumberOfObjects() > 1;
2250 for (const MachOUniversalBinary::ObjectForArch &O : UB->objects()) {
2251 Expected<std::unique_ptr<ObjectFile>> ObjOrErr = O.getAsObjectFile();
2252 std::string ArchiveName;
2253 std::string ArchitectureName;
2254 ArchiveName.clear();
2255 ArchitectureName.clear();
2256 if (ObjOrErr) {
2257 ObjectFile &Obj = *ObjOrErr.get();
2258 if (isa<MachOObjectFile>(Obj) && moreThanOneArch)
2259 ArchitectureName = O.getArchFlagName();
2260 dumpSymbolNamesFromObject(Obj, SymbolList, /*PrintSymbolObject=*/false,
2261 !PrintFileName, ArchiveName, ArchitectureName);
2262 } else if (auto E = isNotObjectErrorInvalidFileType(ObjOrErr.takeError())) {
2263 error(std::move(E), Filename,
2264 moreThanOneArch ? StringRef(O.getArchFlagName()) : StringRef());
2265 continue;
2266 } else if (Expected<std::unique_ptr<Archive>> AOrErr = O.getAsArchive()) {
2267 std::unique_ptr<Archive> &A = *AOrErr;
2268 Error Err = Error::success();
2269 for (auto &C : A->children(Err)) {
2270 Expected<std::unique_ptr<Binary>> ChildOrErr =
2271 C.getAsBinary(ContextPtr);
2272 if (!ChildOrErr) {
2273 if (auto E = isNotObjectErrorInvalidFileType(ChildOrErr.takeError()))
2274 error(std::move(E), Filename, C,
2275 moreThanOneArch ? StringRef(ArchitectureName) : StringRef());
2276 continue;
2278 if (SymbolicFile *F = dyn_cast<SymbolicFile>(&*ChildOrErr.get())) {
2279 ArchiveName = std::string(A->getFileName());
2280 if (isa<MachOObjectFile>(F) && moreThanOneArch)
2281 ArchitectureName = O.getArchFlagName();
2282 dumpSymbolNamesFromObject(*F, SymbolList, /*PrintSymbolObject=*/false,
2283 !PrintFileName, ArchiveName,
2284 ArchitectureName);
2287 if (Err)
2288 error(std::move(Err), A->getFileName());
2289 } else {
2290 consumeError(AOrErr.takeError());
2291 error(Filename + " for architecture " + StringRef(O.getArchFlagName()) +
2292 " is not a Mach-O file or an archive file",
2293 "Mach-O universal file");
2298 static void dumpMachOUniversalBinary(MachOUniversalBinary *UB,
2299 std::vector<NMSymbol> &SymbolList,
2300 StringRef Filename,
2301 LLVMContext *ContextPtr) {
2302 // If we have a list of architecture flags specified dump only those.
2303 if (!ArchAll && !ArchFlags.empty()) {
2304 dumpMachOUniversalBinaryMatchArchFlags(UB, SymbolList, Filename,
2305 ContextPtr);
2306 return;
2309 // No architecture flags were specified so if this contains a slice that
2310 // matches the host architecture dump only that.
2311 if (!ArchAll &&
2312 dumpMachOUniversalBinaryMatchHost(UB, SymbolList, Filename, ContextPtr))
2313 return;
2315 // Either all architectures have been specified or none have been specified
2316 // and this does not contain the host architecture so dump all the slices.
2317 dumpMachOUniversalBinaryArchAll(UB, SymbolList, Filename, ContextPtr);
2320 static void dumpTapiUniversal(TapiUniversal *TU,
2321 std::vector<NMSymbol> &SymbolList,
2322 StringRef Filename) {
2323 for (const TapiUniversal::ObjectForArch &I : TU->objects()) {
2324 StringRef ArchName = I.getArchFlagName();
2325 const bool ShowArch =
2326 ArchFlags.empty() || llvm::is_contained(ArchFlags, ArchName);
2327 if (!ShowArch)
2328 continue;
2329 if (!AddInlinedInfo && !I.isTopLevelLib())
2330 continue;
2331 if (auto ObjOrErr = I.getAsObjectFile())
2332 dumpSymbolNamesFromObject(
2333 *ObjOrErr.get(), SymbolList, /*PrintSymbolObject=*/false,
2334 /*PrintObjectLabel=*/true,
2335 /*ArchiveName=*/{}, ArchName, I.getInstallName());
2336 else if (Error E = isNotObjectErrorInvalidFileType(ObjOrErr.takeError())) {
2337 error(std::move(E), Filename, ArchName);
2342 static void dumpSymbolicFile(SymbolicFile *O, std::vector<NMSymbol> &SymbolList,
2343 StringRef Filename) {
2344 if (!MachOPrintSizeWarning && PrintSize && isa<MachOObjectFile>(O)) {
2345 WithColor::warning(errs(), ToolName)
2346 << "sizes with --print-size for Mach-O files are always zero.\n";
2347 MachOPrintSizeWarning = true;
2349 if (!checkMachOAndArchFlags(O, Filename))
2350 return;
2351 dumpSymbolNamesFromObject(*O, SymbolList, /*PrintSymbolObject=*/true,
2352 /*PrintObjectLabel=*/false);
2355 static std::vector<NMSymbol> dumpSymbolNamesFromFile(StringRef Filename) {
2356 std::vector<NMSymbol> SymbolList;
2357 ErrorOr<std::unique_ptr<MemoryBuffer>> BufferOrErr =
2358 MemoryBuffer::getFileOrSTDIN(Filename);
2359 if (error(BufferOrErr.getError(), Filename))
2360 return SymbolList;
2362 // Ignore AIX linker import files (these files start with "#!"), when
2363 // exporting symbols.
2364 const char *BuffStart = (*BufferOrErr)->getBufferStart();
2365 size_t BufferSize = (*BufferOrErr)->getBufferSize();
2366 if (ExportSymbols && BufferSize >= 2 && BuffStart[0] == '#' &&
2367 BuffStart[1] == '!')
2368 return SymbolList;
2370 LLVMContext Context;
2371 LLVMContext *ContextPtr = NoLLVMBitcode ? nullptr : &Context;
2372 Expected<std::unique_ptr<Binary>> BinaryOrErr =
2373 createBinary(BufferOrErr.get()->getMemBufferRef(), ContextPtr);
2374 if (!BinaryOrErr) {
2375 error(BinaryOrErr.takeError(), Filename);
2376 return SymbolList;
2378 Binary &Bin = *BinaryOrErr.get();
2379 if (Archive *A = dyn_cast<Archive>(&Bin))
2380 dumpArchive(A, SymbolList, Filename, ContextPtr);
2381 else if (MachOUniversalBinary *UB = dyn_cast<MachOUniversalBinary>(&Bin))
2382 dumpMachOUniversalBinary(UB, SymbolList, Filename, ContextPtr);
2383 else if (TapiUniversal *TU = dyn_cast<TapiUniversal>(&Bin))
2384 dumpTapiUniversal(TU, SymbolList, Filename);
2385 else if (SymbolicFile *O = dyn_cast<SymbolicFile>(&Bin))
2386 dumpSymbolicFile(O, SymbolList, Filename);
2387 return SymbolList;
2390 static void
2391 exportSymbolNamesFromFiles(const std::vector<std::string> &InputFilenames) {
2392 std::vector<NMSymbol> SymbolList;
2393 for (const auto &FileName : InputFilenames) {
2394 std::vector<NMSymbol> FileSymList = dumpSymbolNamesFromFile(FileName);
2395 SymbolList.insert(SymbolList.end(), FileSymList.begin(), FileSymList.end());
2398 // Delete symbols which should not be printed from SymolList.
2399 llvm::erase_if(SymbolList,
2400 [](const NMSymbol &s) { return !s.shouldPrint(); });
2401 sortSymbolList(SymbolList);
2402 SymbolList.erase(std::unique(SymbolList.begin(), SymbolList.end()),
2403 SymbolList.end());
2404 printExportSymbolList(SymbolList);
2407 int llvm_nm_main(int argc, char **argv, const llvm::ToolContext &) {
2408 InitLLVM X(argc, argv);
2409 BumpPtrAllocator A;
2410 StringSaver Saver(A);
2411 NmOptTable Tbl;
2412 ToolName = argv[0];
2413 opt::InputArgList Args =
2414 Tbl.parseArgs(argc, argv, OPT_UNKNOWN, Saver, [&](StringRef Msg) {
2415 error(Msg);
2416 exit(1);
2418 if (Args.hasArg(OPT_help)) {
2419 Tbl.printHelp(
2420 outs(),
2421 (Twine(ToolName) + " [options] <input object files>").str().c_str(),
2422 "LLVM symbol table dumper");
2423 // TODO Replace this with OptTable API once it adds extrahelp support.
2424 outs() << "\nPass @FILE as argument to read options from FILE.\n";
2425 return 0;
2427 if (Args.hasArg(OPT_version)) {
2428 // This needs to contain the word "GNU", libtool looks for that string.
2429 outs() << "llvm-nm, compatible with GNU nm" << '\n';
2430 cl::PrintVersionMessage();
2431 return 0;
2434 DebugSyms = Args.hasArg(OPT_debug_syms);
2435 DefinedOnly = Args.hasArg(OPT_defined_only);
2436 Demangle = Args.hasFlag(OPT_demangle, OPT_no_demangle, false);
2437 DynamicSyms = Args.hasArg(OPT_dynamic);
2438 ExternalOnly = Args.hasArg(OPT_extern_only);
2439 StringRef V = Args.getLastArgValue(OPT_format_EQ, "bsd");
2440 if (V == "bsd")
2441 OutputFormat = bsd;
2442 else if (V == "posix")
2443 OutputFormat = posix;
2444 else if (V == "sysv")
2445 OutputFormat = sysv;
2446 else if (V == "darwin")
2447 OutputFormat = darwin;
2448 else if (V == "just-symbols")
2449 OutputFormat = just_symbols;
2450 else
2451 error("--format value should be one of: bsd, posix, sysv, darwin, "
2452 "just-symbols");
2453 LineNumbers = Args.hasArg(OPT_line_numbers);
2454 NoLLVMBitcode = Args.hasArg(OPT_no_llvm_bc);
2455 NoSort = Args.hasArg(OPT_no_sort);
2456 NoWeakSymbols = Args.hasArg(OPT_no_weak);
2457 NumericSort = Args.hasArg(OPT_numeric_sort);
2458 ArchiveMap = Args.hasArg(OPT_print_armap);
2459 PrintFileName = Args.hasArg(OPT_print_file_name);
2460 PrintSize = Args.hasArg(OPT_print_size);
2461 ReverseSort = Args.hasArg(OPT_reverse_sort);
2462 ExportSymbols = Args.hasArg(OPT_export_symbols);
2463 if (ExportSymbols) {
2464 ExternalOnly = true;
2465 DefinedOnly = true;
2468 Quiet = Args.hasArg(OPT_quiet);
2469 V = Args.getLastArgValue(OPT_radix_EQ, "x");
2470 if (V == "o")
2471 AddressRadix = Radix::o;
2472 else if (V == "d")
2473 AddressRadix = Radix::d;
2474 else if (V == "x")
2475 AddressRadix = Radix::x;
2476 else
2477 error("--radix value should be one of: 'o' (octal), 'd' (decimal), 'x' "
2478 "(hexadecimal)");
2479 SizeSort = Args.hasArg(OPT_size_sort);
2480 SpecialSyms = Args.hasArg(OPT_special_syms);
2481 UndefinedOnly = Args.hasArg(OPT_undefined_only);
2482 WithoutAliases = Args.hasArg(OPT_without_aliases);
2484 // Get BitMode from enviornment variable "OBJECT_MODE" for AIX OS, if
2485 // specified.
2486 Triple HostTriple(sys::getProcessTriple());
2487 if (HostTriple.isOSAIX()) {
2488 BitMode = StringSwitch<BitModeTy>(getenv("OBJECT_MODE"))
2489 .Case("32", BitModeTy::Bit32)
2490 .Case("64", BitModeTy::Bit64)
2491 .Case("32_64", BitModeTy::Bit32_64)
2492 .Case("any", BitModeTy::Any)
2493 .Default(BitModeTy::Bit32);
2494 } else
2495 BitMode = BitModeTy::Any;
2497 if (Arg *A = Args.getLastArg(OPT_X)) {
2498 StringRef Mode = A->getValue();
2499 if (Mode == "32")
2500 BitMode = BitModeTy::Bit32;
2501 else if (Mode == "64")
2502 BitMode = BitModeTy::Bit64;
2503 else if (Mode == "32_64")
2504 BitMode = BitModeTy::Bit32_64;
2505 else if (Mode == "any")
2506 BitMode = BitModeTy::Any;
2507 else
2508 error("-X value should be one of: 32, 64, 32_64, (default) any");
2511 // Mach-O specific options.
2512 FormatMachOasHex = Args.hasArg(OPT_x);
2513 AddDyldInfo = Args.hasArg(OPT_add_dyldinfo);
2514 AddInlinedInfo = Args.hasArg(OPT_add_inlinedinfo);
2515 DyldInfoOnly = Args.hasArg(OPT_dyldinfo_only);
2516 NoDyldInfo = Args.hasArg(OPT_no_dyldinfo);
2518 // XCOFF specific options.
2519 NoRsrc = Args.hasArg(OPT_no_rsrc);
2521 // llvm-nm only reads binary files.
2522 if (error(sys::ChangeStdinToBinary()))
2523 return 1;
2525 // These calls are needed so that we can read bitcode correctly.
2526 llvm::InitializeAllTargetInfos();
2527 llvm::InitializeAllTargetMCs();
2528 llvm::InitializeAllAsmParsers();
2530 // The relative order of these is important. If you pass --size-sort it should
2531 // only print out the size. However, if you pass -S --size-sort, it should
2532 // print out both the size and address.
2533 if (SizeSort && !PrintSize)
2534 PrintAddress = false;
2535 if (OutputFormat == sysv || SizeSort)
2536 PrintSize = true;
2538 for (const auto *A : Args.filtered(OPT_arch_EQ)) {
2539 SmallVector<StringRef, 2> Values;
2540 llvm::SplitString(A->getValue(), Values, ",");
2541 for (StringRef V : Values) {
2542 if (V == "all")
2543 ArchAll = true;
2544 else if (MachOObjectFile::isValidArch(V))
2545 ArchFlags.push_back(V);
2546 else
2547 error("Unknown architecture named '" + V + "'",
2548 "for the --arch option");
2552 // Mach-O takes -s to accept two arguments. We emulate this by iterating over
2553 // both OPT_s and OPT_INPUT.
2554 std::vector<std::string> InputFilenames;
2555 int SegSectArgs = 0;
2556 for (opt::Arg *A : Args.filtered(OPT_s, OPT_INPUT)) {
2557 if (SegSectArgs > 0) {
2558 --SegSectArgs;
2559 SegSect.push_back(A->getValue());
2560 } else if (A->getOption().matches(OPT_s)) {
2561 SegSectArgs = 2;
2562 } else {
2563 InputFilenames.push_back(A->getValue());
2566 if (!SegSect.empty() && SegSect.size() != 2)
2567 error("bad number of arguments (must be two arguments)",
2568 "for the -s option");
2570 if (InputFilenames.empty())
2571 InputFilenames.push_back("a.out");
2572 if (InputFilenames.size() > 1)
2573 MultipleFiles = true;
2575 if (NoDyldInfo && (AddDyldInfo || DyldInfoOnly))
2576 error("--no-dyldinfo can't be used with --add-dyldinfo or --dyldinfo-only");
2578 if (ExportSymbols)
2579 exportSymbolNamesFromFiles(InputFilenames);
2580 else
2581 llvm::for_each(InputFilenames, dumpSymbolNamesFromFile);
2583 if (HadError)
2584 return 1;
2585 return 0;