xref: /llvm-project/llvm/tools/llvm-nm/llvm-nm.cpp (revision dd647e3e608ed0b2bac7c588d5859b80ef4a5976)
1 //===-- llvm-nm.cpp - Symbol table dumping utility for llvm ---------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This program is a utility that works like traditional Unix "nm", that is, it
10 // prints out the names of symbols in a bitcode or object file, along with some
11 // information about each symbol.
12 //
13 // This "nm" supports many of the features of GNU "nm", including its different
14 // output formats.
15 //
16 //===----------------------------------------------------------------------===//
17 
18 #include "llvm/ADT/StringSwitch.h"
19 #include "llvm/BinaryFormat/COFF.h"
20 #include "llvm/BinaryFormat/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>
55 
56 using namespace llvm;
57 using namespace object;
58 
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
66 };
67 
68 #define OPTTABLE_STR_TABLE_CODE
69 #include "Opts.inc"
70 #undef OPTTABLE_STR_TABLE_CODE
71 
72 #define OPTTABLE_PREFIXES_TABLE_CODE
73 #include "Opts.inc"
74 #undef OPTTABLE_PREFIXES_TABLE_CODE
75 
76 static constexpr opt::OptTable::Info InfoTable[] = {
77 #define OPTION(...) LLVM_CONSTRUCT_OPT_INFO(__VA_ARGS__),
78 #include "Opts.inc"
79 #undef OPTION
80 };
81 
82 class NmOptTable : public opt::GenericOptTable {
83 public:
84   NmOptTable()
85       : opt::GenericOptTable(OptionStrTable, OptionPrefixesTable, InfoTable) {
86     setGroupedShortOptions(true);
87   }
88 };
89 
90 enum OutputFormatTy { bsd, sysv, posix, darwin, just_symbols };
91 enum class BitModeTy { Bit32, Bit64, Bit32_64, Any };
92 } // namespace
93 
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;
116 
117 // XCOFF-specific options.
118 static bool NoRsrc;
119 
120 namespace {
121 enum Radix { d, o, x };
122 } // namespace
123 static Radix AddressRadix;
124 
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;
135 
136 // Miscellaneous states.
137 static bool PrintAddress = true;
138 static bool MultipleFiles = false;
139 static bool HadError = false;
140 
141 static StringRef ToolName;
142 
143 static void warn(Error Err, Twine FileName, Twine Context = Twine(),
144                  Twine Archive = Twine()) {
145   assert(Err);
146 
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();
150 
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";
156   });
157 }
158 
159 static void error(Twine Message, Twine Path = Twine()) {
160   HadError = true;
161   WithColor::error(errs(), ToolName) << Path << ": " << Message << "\n";
162 }
163 
164 static bool error(std::error_code EC, Twine Path = Twine()) {
165   if (EC) {
166     error(EC.message(), Path);
167     return true;
168   }
169   return false;
170 }
171 
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;
179 
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() << ")";
189 
190   if (!ArchitectureName.empty())
191     errs() << " (for architecture " << ArchitectureName << ")";
192 
193   std::string Buf;
194   raw_string_ostream OS(Buf);
195   logAllUnhandledErrors(std::move(E), OS);
196   OS.flush();
197   errs() << ": " << Buf << "\n";
198 }
199 
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;
208 
209   if (!ArchitectureName.empty())
210     errs() << " (for architecture " << ArchitectureName << ")";
211 
212   std::string Buf;
213   raw_string_ostream OS(Buf);
214   logAllUnhandledErrors(std::move(E), OS);
215   OS.flush();
216   errs() << ": " << Buf << "\n";
217 }
218 
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;
229 
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;
241 
242   bool isDefined() const {
243     if (Sym.getRawDataRefImpl().p)
244       return !(SymFlags & SymbolRef::SF_Undefined);
245     return TypeChar != 'U';
246   }
247 
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;
254     }
255     SymFlags = *SymFlagsOrErr;
256     return true;
257   }
258 
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;
269   }
270 };
271 
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);
284 }
285 
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);
289 }
290 } // anonymous namespace
291 
292 static StringRef CurrentFilename;
293 
294 static char getSymbolNMTypeChar(IRObjectFile &Obj, basic_symbol_iterator I);
295 
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;
334     }
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;
356       }
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;
374       }
375     }
376   }
377 
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 << ")";
394     }
395     outs() << "\n";
396     return;
397   }
398 
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 << ' ';
405   }
406 
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) ";
429     }
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;
450     }
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;
459       }
460       Sec = *SecOrErr;
461       if (Sec == MachO->section_end()) {
462         outs() << "(?,?) ";
463         break;
464       }
465     } else {
466       Sec = S.Section;
467     }
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;
475   }
476   default:
477     outs() << "(?) ";
478     break;
479   }
480 
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 ";
499     }
500   } else {
501     if (NType & MachO::N_PEXT)
502       outs() << "non-external (was a private external) ";
503     else
504       outs() << "non-external ";
505   }
506 
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] ";
517   }
518 
519   if ((NDesc & MachO::N_ARM_THUMB_DEF) == MachO::N_ARM_THUMB_DEF)
520     outs() << "[Thumb] ";
521 
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;
537 
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 << ")";
554       }
555     }
556   }
557 }
558 
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;
563 };
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"},
581 };
582 
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;
588 }
589 
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;
609   }
610 
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);
616 }
617 
618 static bool symbolIsDefined(const NMSymbol &Sym) {
619   return Sym.TypeChar != 'U' && Sym.TypeChar != 'w' && Sym.TypeChar != 'v';
620 }
621 
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 << ": ";
632   }
633 }
634 
635 static void sortSymbolList(std::vector<NMSymbol> &SymbolList) {
636   if (NoSort)
637     return;
638 
639   if (ReverseSort)
640     llvm::sort(SymbolList, std::greater<>());
641   else
642     llvm::sort(SymbolList);
643 }
644 
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';
651   }
652 }
653 
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};
665 
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;
686         }
687         if (ResOrErr->FileName == DILineInfo::BadString)
688           return;
689         FileName = std::move(ResOrErr->FileName);
690         Line = ResOrErr->Line;
691         break;
692       }
693       if (!FileName.empty())
694         break;
695     }
696     if (FileName.empty())
697       return;
698     break;
699   }
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;
706     }
707     if (ResOrErr->FileName == DILineInfo::BadString)
708       return;
709     FileName = std::move(ResOrErr->FileName);
710     Line = ResOrErr->Line;
711     break;
712   }
713   default: {
714     Expected<DIGlobal> ResOrErr = Symbolizer.symbolizeData(*Obj, Address);
715     if (!ResOrErr) {
716       error(ResOrErr.takeError(), Obj->getFileName());
717       return;
718     }
719     if (ResOrErr->DeclFile.empty())
720       return;
721     FileName = std::move(ResOrErr->DeclFile);
722     Line = ResOrErr->DeclLine;
723     break;
724   }
725   }
726   outs() << '\t' << FileName << ':' << Line;
727 }
728 
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();
735 
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";
749     }
750   }
751 
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;
765     }
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;
778     }
779   }
780 
781   for (const NMSymbol &S : SymbolList) {
782     if (!S.shouldPrint())
783       continue;
784 
785     std::string Name = S.Name;
786     MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(&Obj);
787     if (Demangle)
788       Name = demangle(Name);
789 
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;
797     }
798 
799     char SymbolAddrStr[23], SymbolSizeStr[23];
800 
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);
810       }
811     }
812 
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));
823     }
824 
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 << ")";
855       }
856     } else if (OutputFormat == sysv) {
857       outs() << left_justify(Name, 20) << "|" << SymbolAddrStr << "|   "
858              << S.TypeChar << "  |" << right_justify(S.TypeName, 18) << "|"
859              << SymbolSizeStr << "|     |" << S.SectionName;
860     }
861     if (LineNumbers)
862       printLineNumbers(*Symbolizer, S);
863     outs() << '\n';
864   }
865 
866   SymbolList.clear();
867 }
868 
869 static char getSymbolNMTypeChar(ELFObjectFileBase &Obj,
870                                 basic_symbol_iterator I) {
871   // OK, this is ELF
872   elf_symbol_iterator SymI(I);
873 
874   Expected<elf_section_iterator> SecIOrErr = SymI->getSection();
875   if (!SecIOrErr) {
876     consumeError(SecIOrErr.takeError());
877     return '?';
878   }
879 
880   uint8_t Binding = SymI->getBinding();
881   if (Binding == ELF::STB_GNU_UNIQUE)
882     return 'u';
883 
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 '?';
887 
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';
898 
899     auto NameOrErr = SecI->getName();
900     if (!NameOrErr) {
901       consumeError(NameOrErr.takeError());
902       return '?';
903     }
904     if ((*NameOrErr).starts_with(".debug"))
905       return 'N';
906     if (!(Flags & ELF::SHF_WRITE))
907       return 'n';
908   }
909 
910   return '?';
911 }
912 
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);
917 
918   Expected<StringRef> Name = SymI->getName();
919   if (!Name) {
920     consumeError(Name.takeError());
921     return '?';
922   }
923 
924   char Ret = StringSwitch<char>(*Name)
925                  .StartsWith(".debug", 'N')
926                  .StartsWith(".sxdata", 'N')
927                  .Default('?');
928 
929   if (Ret != '?')
930     return Ret;
931 
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 '?';
938     }
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';
945   }
946 
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';
963   }
964 
965   return '?';
966 }
967 
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 '?';
975   }
976 
977   uint32_t SymType = *TypeOrErr;
978 
979   if (SymType == SymbolRef::ST_File)
980     return 'f';
981 
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());
985 
986   if (SecIter == Obj.section_end())
987     return '?';
988 
989   if (Obj.isDebugSection(SecIter->getRawDataRefImpl()))
990     return 'N';
991 
992   if (SecIter->isText())
993     return 't';
994 
995   if (SecIter->isData())
996     return 'd';
997 
998   if (SecIter->isBSS())
999     return 'b';
1000 
1001   return '?';
1002 }
1003 
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';
1012   }
1013   return '?';
1014 }
1015 
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;
1020 
1021   if (NType & MachO::N_STAB)
1022     return '-';
1023 
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';
1034     }
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';
1053   }
1054   }
1055 
1056   return '?';
1057 }
1058 
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';
1070   }
1071 }
1072 
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';
1078 }
1079 
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';
1091 }
1092 
1093 static bool isObject(SymbolicFile &Obj, basic_symbol_iterator I) {
1094   return isa<ELFObjectFileBase>(&Obj) &&
1095          elf_symbol_iterator(I)->getELFType() == ELF::STT_OBJECT;
1096 }
1097 
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();
1104   }
1105   return "";
1106 }
1107 
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 '?';
1127       }
1128 
1129       if (*SecIOrErr == ELFObj->section_end())
1130         return '?';
1131 
1132       Expected<StringRef> NameOrErr = (*SecIOrErr)->getName();
1133       if (!NameOrErr) {
1134         consumeError(NameOrErr.takeError());
1135         return '?';
1136       }
1137       SecName = *NameOrErr;
1138     }
1139   }
1140 
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';
1145   }
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';
1151 
1152   if (Symflags & object::SymbolRef::SF_Common)
1153     return 'C';
1154 
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");
1178 
1179   if (!(Symflags & object::SymbolRef::SF_Global))
1180     return Ret;
1181 
1182   return toupper(Ret);
1183 }
1184 
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++;
1202   }
1203   return 0;
1204 }
1205 
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;
1216   }
1217   MachO::nlist STE = Obj.getSymbolTableEntry(Symb);
1218   return (STE.n_type & MachO::N_TYPE) == MachO::N_SECT ? STE.n_sect : 0;
1219 }
1220 
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);
1234 
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;
1244   }
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;
1252       }
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;
1258       }
1259     }
1260   }
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;
1274           }
1275       }
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;
1291 
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;
1314             }
1315           } else {
1316             S.Address = Entry.address() + BaseSegmentAddress;
1317           }
1318           StringRef SegmentName = StringRef();
1319           StringRef SectionName = StringRef();
1320           for (const SectionRef &Section : MachO.sections()) {
1321             S.NSect++;
1322 
1323             if (Expected<StringRef> NameOrErr = Section.getName())
1324               SectionName = *NameOrErr;
1325             else
1326               consumeError(NameOrErr.takeError());
1327 
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;
1339             }
1340           }
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';
1349         }
1350         SymbolList.push_back(S);
1351 
1352         EOS << Entry.name();
1353         EOS << '\0';
1354         ExportsAdded++;
1355 
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) {
1360 
1361           // Add the indirect name.
1362           if (Entry.otherName().empty())
1363             EOS << Entry.name();
1364           else
1365             EOS << Entry.otherName();
1366           EOS << '\0';
1367 
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);
1391 
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++;
1399         }
1400       }
1401     }
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;
1414         }
1415         I++;
1416       }
1417     }
1418 
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;
1431         }
1432       }
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++;
1453       }
1454     }
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;
1467         }
1468         I++;
1469       }
1470     }
1471 
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;
1488         }
1489       }
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++;
1512       }
1513     }
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;
1526         }
1527         I++;
1528       }
1529     }
1530 
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;
1548           }
1549         }
1550       }
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;
1580       }
1581     }
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;
1594         }
1595         I++;
1596       }
1597     }
1598 
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);
1609 
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;
1614       }
1615     }
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;
1623       }
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());
1645 
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;
1653           }
1654         }
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++;
1671       }
1672     }
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;
1682         }
1683         I++;
1684       }
1685     }
1686   }
1687 }
1688 
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;
1696 
1697   return Obj.is64Bit() ? BitMode != BitModeTy::Bit32
1698                        : BitMode != BitModeTy::Bit64;
1699 }
1700 
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;
1707 
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));
1714 
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;
1722     }
1723 
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;
1731     }
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;
1738 
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;
1745 
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;
1751     }
1752 
1753     if (SymName == "__rsrc" && NoRsrc)
1754       continue;
1755 
1756     if (SymName.starts_with("__tf1"))
1757       SymName = SymName.substr(6);
1758     else if (SymName.starts_with("__tf9"))
1759       SymName = SymName.substr(14);
1760 
1761     NMSymbol S = {};
1762     S.Name = SymName.str();
1763     S.Sym = Sym;
1764 
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";
1772     }
1773     if (S.initializeFlags(*XCOFFObj))
1774       SymbolList.push_back(S);
1775   }
1776 }
1777 
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();
1784 }
1785 
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;
1791 
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;
1798     }
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";
1808     }
1809   }
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;
1819   }
1820 
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;
1829       }
1830 
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();
1854 
1855       if (const XCOFFObjectFile *XCOFFObj =
1856               dyn_cast<const XCOFFObjectFile>(&Obj))
1857         S.Size = XCOFFObj->getSymbolSize(Sym.getRawDataRefImpl());
1858 
1859       if (const WasmObjectFile *WasmObj = dyn_cast<WasmObjectFile>(&Obj))
1860         S.Size = WasmObj->getSymbolSize(Sym);
1861 
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;
1868         }
1869         S.Address = *AddressOrErr;
1870       }
1871       S.TypeName = getNMTypeName(Obj, Sym);
1872       S.TypeChar = getNMSectionTagAndName(Obj, Sym, S.SectionName);
1873 
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());
1881       }
1882       if (!SymbolVersions.empty() && !SymbolVersions[I].Name.empty())
1883         S.Name +=
1884             (SymbolVersions[I].IsVerDef ? "@@" : "@") + SymbolVersions[I].Name;
1885 
1886       S.Sym = Sym;
1887       if (S.initializeFlags(Obj))
1888         SymbolList.push_back(S);
1889     }
1890   }
1891 
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);
1900 
1901   return true;
1902 }
1903 
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";
1915 }
1916 
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();
1924   }
1925   return !Obj.symbols().empty();
1926 }
1927 
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) {
1933 
1934   if (PrintObjectLabel && !ExportSymbols)
1935     printObjectLabel(PrintArchiveName, ArchiveName, ArchitectureName,
1936                      ObjectName.empty() ? Obj.getFileName() : ObjectName);
1937 
1938   if (!getSymbolNamesFromObject(Obj, SymbolList) || ExportSymbols)
1939     return;
1940 
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";
1946   }
1947 
1948   sortSymbolList(SymbolList);
1949   printSymbolList(Obj, SymbolList, PrintSymbolObject, ArchiveName,
1950                   ArchitectureName);
1951 }
1952 
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;
1962 
1963     MachO::fileset_entry_command Entry =
1964         Obj->getFilesetEntryLoadCommand(Command);
1965     auto MaybeMachO =
1966         MachOObjectFile::createMachOObjectFile(Buf, 0, 0, Entry.fileoff);
1967 
1968     if (Error Err = MaybeMachO.takeError())
1969       report_fatal_error(std::move(Err));
1970 
1971     const char *EntryName = Command.Ptr + Entry.entry_id.offset;
1972     if (EntryName)
1973       outs() << "Symbols for " << EntryName << ": \n";
1974 
1975     std::unique_ptr<MachOObjectFile> EntryMachO = std::move(MaybeMachO.get());
1976     printSymbolNamesFromObject(*EntryMachO, SymbolList, PrintSymbolObject,
1977                                PrintObjectLabel);
1978 
1979     if (std::next(It) != End)
1980       outs() << "\n";
1981   }
1982 }
1983 
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;
1991 
1992   if (ExportSymbols && Obj.isXCOFF()) {
1993     XCOFFObjectFile *XCOFFObj = cast<XCOFFObjectFile>(&Obj);
1994     getXCOFFExports(XCOFFObj, SymbolList, ArchiveName);
1995     return;
1996   }
1997 
1998   CurrentFilename = Obj.getFileName();
1999 
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;
2008   }
2009 
2010   printSymbolNamesFromObject(Obj, SymbolList, PrintSymbolObject,
2011                              PrintObjectLabel, ArchiveName, ArchitectureName,
2012                              ObjectName, PrintArchiveName);
2013 }
2014 
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);
2022 
2023   if (!MachO || ArchAll || ArchFlags.empty())
2024     return true;
2025 
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);
2038   }
2039   const std::string ArchFlagName(ArchFlag);
2040   if (!llvm::is_contained(ArchFlags, ArchFlagName)) {
2041     error("No architecture specified", Filename);
2042     return false;
2043   }
2044   return true;
2045 }
2046 
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;
2054     }
2055     Expected<StringRef> FileNameOrErr = C->getName();
2056     if (!FileNameOrErr) {
2057       error(FileNameOrErr.takeError(), Filename);
2058       break;
2059     }
2060     StringRef SymName = I.getName();
2061     outs() << SymName << " in " << FileNameOrErr.get() << "\n";
2062   }
2063 
2064   outs() << "\n";
2065 }
2066 
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);
2072   }
2073 
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);
2080   }
2081 }
2082 
2083 static void dumpArchive(Archive *A, std::vector<NMSymbol> &SymbolList,
2084                         StringRef Filename, LLVMContext *ContextPtr) {
2085   if (ArchiveMap)
2086     dumpArchiveMap(A, Filename);
2087 
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;
2095     }
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;
2101       }
2102       if (!checkMachOAndArchFlags(O, Filename))
2103         return;
2104       dumpSymbolNamesFromObject(*O, SymbolList, /*PrintSymbolObject=*/false,
2105                                 !PrintFileName, Filename,
2106                                 /*ArchitectureName=*/{}, O->getFileName(),
2107                                 /*PrintArchiveName=*/false);
2108     }
2109   }
2110   if (Err)
2111     error(std::move(Err), A->getFileName());
2112 }
2113 
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());
2158               }
2159               continue;
2160             }
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);
2168             }
2169           }
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");
2178         }
2179       }
2180     }
2181     if (!ArchFound) {
2182       error(ArchFlags[i],
2183             "file: " + Filename + " does not contain architecture");
2184       return;
2185     }
2186   }
2187 }
2188 
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;
2220           }
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);
2226           }
2227         }
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");
2236       }
2237       return true;
2238     }
2239   }
2240   return false;
2241 }
2242 
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;
2275         }
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);
2283         }
2284       }
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");
2292     }
2293   }
2294 }
2295 
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;
2305   }
2306 
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;
2312 
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);
2316 }
2317 
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);
2336     }
2337   }
2338 }
2339 
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;
2346   }
2347   if (!checkMachOAndArchFlags(O, Filename))
2348     return;
2349   dumpSymbolNamesFromObject(*O, SymbolList, /*PrintSymbolObject=*/true,
2350                             /*PrintObjectLabel=*/false);
2351 }
2352 
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;
2359 
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;
2367 
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;
2375   }
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;
2386 }
2387 
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());
2394   }
2395 
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);
2402 }
2403 
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);
2413       });
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;
2422   }
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;
2428   }
2429 
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;
2462   }
2463 
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);
2479 
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;
2492 
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");
2505   }
2506 
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);
2513 
2514   // XCOFF specific options.
2515   NoRsrc = Args.hasArg(OPT_no_rsrc);
2516 
2517   // llvm-nm only reads binary files.
2518   if (error(sys::ChangeStdinToBinary()))
2519     return 1;
2520 
2521   // These calls are needed so that we can read bitcode correctly.
2522   llvm::InitializeAllTargetInfos();
2523   llvm::InitializeAllTargetMCs();
2524   llvm::InitializeAllAsmParsers();
2525 
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;
2533 
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");
2545     }
2546   }
2547 
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());
2560     }
2561   }
2562   if (!SegSect.empty() && SegSect.size() != 2)
2563     error("bad number of arguments (must be two arguments)",
2564           "for the -s option");
2565 
2566   if (InputFilenames.empty())
2567     InputFilenames.push_back("a.out");
2568   if (InputFilenames.size() > 1)
2569     MultipleFiles = true;
2570 
2571   if (NoDyldInfo && (AddDyldInfo || DyldInfoOnly))
2572     error("--no-dyldinfo can't be used with --add-dyldinfo or --dyldinfo-only");
2573 
2574   if (ExportSymbols)
2575     exportSymbolNamesFromFiles(InputFilenames);
2576   else
2577     llvm::for_each(InputFilenames, dumpSymbolNamesFromFile);
2578 
2579   if (HadError)
2580     return 1;
2581   return 0;
2582 }
2583