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