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