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/SmallSet.h"
19#include "llvm/ADT/StringSwitch.h"
20#include "llvm/BinaryFormat/COFF.h"
21#include "llvm/BinaryFormat/MachO.h"
22#include "llvm/BinaryFormat/XCOFF.h"
23#include "llvm/DebugInfo/Symbolize/Symbolize.h"
24#include "llvm/Demangle/Demangle.h"
25#include "llvm/IR/Function.h"
26#include "llvm/IR/LLVMContext.h"
27#include "llvm/Object/Archive.h"
28#include "llvm/Object/COFF.h"
29#include "llvm/Object/COFFImportFile.h"
30#include "llvm/Object/ELFObjectFile.h"
31#include "llvm/Object/GOFFObjectFile.h"
32#include "llvm/Object/IRObjectFile.h"
33#include "llvm/Object/MachO.h"
34#include "llvm/Object/MachOUniversal.h"
35#include "llvm/Object/ObjectFile.h"
36#include "llvm/Object/SymbolicFile.h"
37#include "llvm/Object/TapiFile.h"
38#include "llvm/Object/TapiUniversal.h"
39#include "llvm/Object/Wasm.h"
40#include "llvm/Object/XCOFFObjectFile.h"
41#include "llvm/Option/Arg.h"
42#include "llvm/Option/ArgList.h"
43#include "llvm/Option/Option.h"
44#include "llvm/Support/CommandLine.h"
45#include "llvm/Support/FileSystem.h"
46#include "llvm/Support/Format.h"
47#include "llvm/Support/LLVMDriver.h"
48#include "llvm/Support/MemoryBuffer.h"
49#include "llvm/Support/Program.h"
50#include "llvm/Support/Signals.h"
51#include "llvm/Support/TargetSelect.h"
52#include "llvm/Support/WithColor.h"
53#include "llvm/Support/raw_ostream.h"
54#include "llvm/TargetParser/Host.h"
55#include "llvm/TargetParser/Triple.h"
56#include <vector>
57
58using namespace llvm;
59using namespace object;
60
61namespace {
62using namespace llvm::opt; // for HelpHidden in Opts.inc
63enum ID {
64 OPT_INVALID = 0, // This is not an option ID.
65#define OPTION(...) LLVM_MAKE_OPT_ID(__VA_ARGS__),
66#include "Opts.inc"
67#undef OPTION
68};
69
70#define OPTTABLE_STR_TABLE_CODE
71#include "Opts.inc"
72#undef OPTTABLE_STR_TABLE_CODE
73
74#define OPTTABLE_PREFIXES_TABLE_CODE
75#include "Opts.inc"
76#undef OPTTABLE_PREFIXES_TABLE_CODE
77
78static constexpr opt::OptTable::Info InfoTable[] = {
79#define OPTION(...) LLVM_CONSTRUCT_OPT_INFO(__VA_ARGS__),
80#include "Opts.inc"
81#undef OPTION
82};
83
84class NmOptTable : public opt::GenericOptTable {
85public:
86 NmOptTable()
87 : opt::GenericOptTable(OptionStrTable, OptionPrefixesTable, InfoTable) {
88 setGroupedShortOptions(true);
89 }
90};
91
92enum OutputFormatTy { bsd, sysv, posix, darwin, just_symbols };
93enum class BitModeTy { Bit32, Bit64, Bit32_64, Any };
94} // namespace
95
96static bool ArchiveMap;
97static BitModeTy BitMode;
98static bool DebugSyms;
99static bool DefinedOnly;
100static bool Demangle;
101static bool DynamicSyms;
102static bool ExportSymbols;
103static bool ExternalOnly;
104static bool LineNumbers;
105static OutputFormatTy OutputFormat;
106static bool NoLLVMBitcode;
107static bool NoSort;
108static bool NoWeakSymbols;
109static bool NumericSort;
110static bool PrintFileName;
111static bool PrintSize;
112static bool Quiet;
113static bool ReverseSort;
114static bool SpecialSyms;
115static bool SizeSort;
116static bool UndefinedOnly;
117static bool WithoutAliases;
118
119// XCOFF-specific options.
120static bool NoRsrc;
121
122namespace {
123enum Radix { d, o, x };
124} // namespace
125static Radix AddressRadix;
126
127// Mach-O specific options.
128static bool ArchAll = false;
129static std::vector<StringRef> ArchFlags;
130static bool AddDyldInfo;
131static bool AddInlinedInfo;
132static bool DyldInfoOnly;
133static bool FormatMachOasHex;
134static bool NoDyldInfo;
135static std::vector<StringRef> SegSect;
136static bool MachOPrintSizeWarning = false;
137
138// Miscellaneous states.
139static bool PrintAddress = true;
140static bool MultipleFiles = false;
141static bool HadError = false;
142
143static StringRef ToolName;
144
145static void warn(Error Err, Twine FileName, Twine Context = Twine(),
146 Twine Archive = Twine()) {
147 assert(Err);
148
149 // Flush the standard output so that the warning isn't interleaved with other
150 // output if stdout and stderr are writing to the same place.
151 outs().flush();
152
153 handleAllErrors(E: std::move(Err), Handlers: [&](const ErrorInfoBase &EI) {
154 WithColor::warning(OS&: errs(), Prefix: ToolName)
155 << (Archive.str().empty() ? FileName : Archive + "(" + FileName + ")")
156 << ": " << (Context.str().empty() ? "" : Context + ": ") << EI.message()
157 << "\n";
158 });
159}
160
161static void error(Twine Message, Twine Path = Twine()) {
162 HadError = true;
163 WithColor::error(OS&: errs(), Prefix: ToolName) << Path << ": " << Message << "\n";
164}
165
166static bool error(std::error_code EC, Twine Path = Twine()) {
167 if (EC) {
168 error(Message: EC.message(), Path);
169 return true;
170 }
171 return false;
172}
173
174// This version of error() prints the archive name and member name, for example:
175// "libx.a(foo.o)" after the ToolName before the error message. It sets
176// HadError but returns allowing the code to move on to other archive members.
177static void error(llvm::Error E, StringRef FileName, const Archive::Child &C,
178 StringRef ArchitectureName = StringRef()) {
179 HadError = true;
180 WithColor::error(OS&: errs(), Prefix: ToolName) << FileName;
181
182 Expected<StringRef> NameOrErr = C.getName();
183 // TODO: if we have a error getting the name then it would be nice to print
184 // the index of which archive member this is and or its offset in the
185 // archive instead of "???" as the name.
186 if (!NameOrErr) {
187 consumeError(Err: NameOrErr.takeError());
188 errs() << "(" << "???" << ")";
189 } else
190 errs() << "(" << NameOrErr.get() << ")";
191
192 if (!ArchitectureName.empty())
193 errs() << " (for architecture " << ArchitectureName << ")";
194
195 std::string Buf;
196 raw_string_ostream OS(Buf);
197 logAllUnhandledErrors(E: std::move(E), OS);
198 errs() << ": " << Buf << "\n";
199}
200
201// This version of error() prints the file name and which architecture slice it
202// is from, for example: "foo.o (for architecture i386)" after the ToolName
203// before the error message. It sets HadError but returns allowing the code to
204// move on to other architecture slices.
205static void error(llvm::Error E, StringRef FileName,
206 StringRef ArchitectureName = StringRef()) {
207 HadError = true;
208 WithColor::error(OS&: errs(), Prefix: ToolName) << FileName;
209
210 if (!ArchitectureName.empty())
211 errs() << " (for architecture " << ArchitectureName << ")";
212
213 std::string Buf;
214 raw_string_ostream OS(Buf);
215 logAllUnhandledErrors(E: std::move(E), OS);
216 errs() << ": " << Buf << "\n";
217}
218
219namespace {
220struct 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(E: SymFlagsOrErr.takeError(), FileName: 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
272bool operator<(const NMSymbol &A, const NMSymbol &B) {
273 if (NumericSort)
274 return std::make_tuple(args: A.isDefined(), args: A.Address, args: A.Name, args: A.Size) <
275 std::make_tuple(args: B.isDefined(), args: B.Address, args: B.Name, args: B.Size);
276 if (SizeSort)
277 return std::make_tuple(args: A.Size, args: A.Name, args: A.Address) <
278 std::make_tuple(args: B.Size, args: B.Name, args: B.Address);
279 if (ExportSymbols)
280 return std::make_tuple(args: A.Name, args: A.Visibility) <
281 std::make_tuple(args: B.Name, args: B.Visibility);
282 return std::make_tuple(args: A.Name, args: A.Size, args: A.Address) <
283 std::make_tuple(args: B.Name, args: B.Size, args: B.Address);
284}
285
286bool operator>(const NMSymbol &A, const NMSymbol &B) { return B < A; }
287bool operator==(const NMSymbol &A, const NMSymbol &B) {
288 return !(A < B) && !(B < A);
289}
290} // anonymous namespace
291
292static StringRef CurrentFilename;
293
294static 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.
301static 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>(Val: &Obj);
315 if (Obj.isIR()) {
316 uint32_t SymFlags = cantFail(ValOrErr: 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(DRI: 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(DRI: 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(Fmt: printFormat, Vals: NValue) << ' '
381 << format(Fmt: "%02x %02x %04x %08x", Vals: NType, Vals: NSect, Vals: NDesc, Vals: NStrx) << ' '
382 << S.Name;
383 if ((NType & MachO::N_TYPE) == MachO::N_INDR) {
384 outs() << " (indirect for ";
385 outs() << format(Fmt: printFormat, Vals: NValue) << ' ';
386 StringRef IndirectName;
387 if (S.Sym.getRawDataRefImpl().p) {
388 if (MachO->getIndirectName(Symb: S.Sym.getRawDataRefImpl(), Res&: 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(dest: SymbolAddrStr, src: printBlanks);
402 if (Obj.isIR() && (NType & MachO::N_TYPE) == MachO::N_TYPE)
403 strcpy(dest: SymbolAddrStr, src: 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(n_desc: NDesc) != 0)
412 outs() << "(alignment 2^" << (int)MachO::GET_COMM_ALIGN(n_desc: 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(Symb: S.Sym.getRawDataRefImpl());
455 if (!SecOrErr) {
456 consumeError(Err: 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(Sec: Ref))
471 SectionName = *NameOrErr;
472 StringRef SegmentName = MachO->getSectionFinalSegmentName(Sec: 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(Symb: S.Sym.getRawDataRefImpl(), Res&: 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(n_desc: 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(Index: 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.
560struct DarwinStabName {
561 uint8_t NType;
562 const char *Name;
563};
564const struct DarwinStabName DarwinStabNames[] = {
565 {.NType: MachO::N_GSYM, .Name: "GSYM"}, {.NType: MachO::N_FNAME, .Name: "FNAME"},
566 {.NType: MachO::N_FUN, .Name: "FUN"}, {.NType: MachO::N_STSYM, .Name: "STSYM"},
567 {.NType: MachO::N_LCSYM, .Name: "LCSYM"}, {.NType: MachO::N_BNSYM, .Name: "BNSYM"},
568 {.NType: MachO::N_PC, .Name: "PC"}, {.NType: MachO::N_AST, .Name: "AST"},
569 {.NType: MachO::N_OPT, .Name: "OPT"}, {.NType: MachO::N_RSYM, .Name: "RSYM"},
570 {.NType: MachO::N_SLINE, .Name: "SLINE"}, {.NType: MachO::N_ENSYM, .Name: "ENSYM"},
571 {.NType: MachO::N_SSYM, .Name: "SSYM"}, {.NType: MachO::N_SO, .Name: "SO"},
572 {.NType: MachO::N_OSO, .Name: "OSO"}, {.NType: MachO::N_LIB, .Name: "LIB"},
573 {.NType: MachO::N_LSYM, .Name: "LSYM"}, {.NType: MachO::N_BINCL, .Name: "BINCL"},
574 {.NType: MachO::N_SOL, .Name: "SOL"}, {.NType: MachO::N_PARAMS, .Name: "PARAM"},
575 {.NType: MachO::N_VERSION, .Name: "VERS"}, {.NType: MachO::N_OLEVEL, .Name: "OLEV"},
576 {.NType: MachO::N_PSYM, .Name: "PSYM"}, {.NType: MachO::N_EINCL, .Name: "EINCL"},
577 {.NType: MachO::N_ENTRY, .Name: "ENTRY"}, {.NType: MachO::N_LBRAC, .Name: "LBRAC"},
578 {.NType: MachO::N_EXCL, .Name: "EXCL"}, {.NType: MachO::N_RBRAC, .Name: "RBRAC"},
579 {.NType: MachO::N_BCOMM, .Name: "BCOMM"}, {.NType: MachO::N_ECOMM, .Name: "ECOMM"},
580 {.NType: MachO::N_ECOML, .Name: "ECOML"}, {.NType: MachO::N_LENG, .Name: "LENG"},
581};
582
583static 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.
592static 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(DRI: 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(DRI: SymDRI);
606 NType = STE.n_type;
607 NSect = STE.n_sect;
608 NDesc = STE.n_desc;
609 }
610
611 outs() << format(Fmt: " %02x %04x ", Vals: NSect, Vals: NDesc);
612 if (const char *stabString = getDarwinStabString(NType))
613 outs() << format(Fmt: "%5.5s", Vals: stabString);
614 else
615 outs() << format(Fmt: " %02x", Vals: NType);
616}
617
618static bool symbolIsDefined(const NMSymbol &Sym) {
619 return Sym.TypeChar != 'U' && Sym.TypeChar != 'w' && Sym.TypeChar != 'v';
620}
621
622static 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
635static void sortSymbolList(std::vector<NMSymbol> &SymbolList) {
636 if (NoSort)
637 return;
638
639 if (ReverseSort)
640 llvm::sort(C&: SymbolList, Comp: std::greater<>());
641 else
642 llvm::sort(C&: SymbolList);
643}
644
645static 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
654static void printLineNumbers(symbolize::LLVMSymbolizer &Symbolizer,
655 const NMSymbol &S) {
656 const auto *Obj = dyn_cast<ObjectFile>(Val: 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(ValOrErr: Sym.getSection());
662 if (Sec != Obj->section_end())
663 SectionIndex = Sec->getIndex();
664 object::SectionedAddress Address = {.Address: cantFail(ValOrErr: Sym.getAddress()), .SectionIndex: 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(ValOrErr: 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: *Obj, ModuleOffset: {.Address: TextSec.getAddress() + R.getOffset(), .SectionIndex: SectionIndex});
683 if (!ResOrErr) {
684 error(E: ResOrErr.takeError(), FileName: 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: *Obj, ModuleOffset: Address);
703 if (!ResOrErr) {
704 error(E: ResOrErr.takeError(), FileName: 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: *Obj, ModuleOffset: Address);
715 if (!ResOrErr) {
716 error(E: ResOrErr.takeError(), FileName: 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
729static 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>(Val: &Obj);
787 if (Demangle)
788 Name = demangle(MangledName: Name);
789
790 if (PrintFileName)
791 writeFileName(S&: 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(Sym: S)) {
803 if (OutputFormat == posix) {
804 format(Fmt: printFormat, Vals: S.Address)
805 .snprint(Buffer: SymbolAddrStr, BufferSize: sizeof(SymbolAddrStr));
806 format(Fmt: printFormat, Vals: S.Size)
807 .snprint(Buffer: SymbolSizeStr, BufferSize: sizeof(SymbolSizeStr));
808 } else {
809 strcpy(dest: SymbolAddrStr, src: printBlanks);
810 strcpy(dest: SymbolSizeStr, src: printBlanks);
811 }
812 }
813
814 if (symbolIsDefined(Sym: S)) {
815 // Otherwise, print the symbol address and size.
816 if (Obj.isIR())
817 strcpy(dest: SymbolAddrStr, src: printDashes);
818 else if (MachO && S.TypeChar == 'I')
819 strcpy(dest: SymbolAddrStr, src: printBlanks);
820 else
821 format(Fmt: printFormat, Vals: S.Address)
822 .snprint(Buffer: SymbolAddrStr, BufferSize: sizeof(SymbolAddrStr));
823 format(Fmt: printFormat, Vals: S.Size).snprint(Buffer: SymbolSizeStr, BufferSize: sizeof(SymbolSizeStr));
824 }
825
826 // If OutputFormat is darwin or we are printing Mach-O symbols in hex and
827 // we have a MachOObjectFile, call darwinPrintSymbol to print as darwin's
828 // nm(1) -m output or hex, else if OutputFormat is darwin or we are
829 // printing Mach-O symbols in hex and not a Mach-O object fall back to
830 // OutputFormat bsd (see below).
831 if ((OutputFormat == darwin || FormatMachOasHex) && (MachO || Obj.isIR())) {
832 darwinPrintSymbol(Obj, S, SymbolAddrStr, printBlanks, printDashes,
833 printFormat);
834 } else if (OutputFormat == posix) {
835 outs() << Name << " " << S.TypeChar << " " << SymbolAddrStr << " "
836 << (MachO ? "0" : SymbolSizeStr);
837 } else if (OutputFormat == bsd || (OutputFormat == darwin && !MachO)) {
838 if (PrintAddress)
839 outs() << SymbolAddrStr << ' ';
840 if (PrintSize)
841 outs() << SymbolSizeStr << ' ';
842 outs() << S.TypeChar;
843 if (S.TypeChar == '-' && MachO)
844 darwinPrintStab(MachO, S);
845 outs() << " " << Name;
846 if (S.TypeChar == 'I' && MachO) {
847 outs() << " (indirect for ";
848 if (S.Sym.getRawDataRefImpl().p) {
849 StringRef IndirectName;
850 if (MachO->getIndirectName(Symb: S.Sym.getRawDataRefImpl(), Res&: IndirectName))
851 outs() << "?)";
852 else
853 outs() << IndirectName << ")";
854 } else
855 outs() << S.IndirectName << ")";
856 }
857 } else if (OutputFormat == sysv) {
858 outs() << left_justify(Str: Name, Width: 20) << "|" << SymbolAddrStr << "| "
859 << S.TypeChar << " |" << right_justify(Str: S.TypeName, Width: 18) << "|"
860 << SymbolSizeStr << "| |" << S.SectionName;
861 }
862 if (LineNumbers)
863 printLineNumbers(Symbolizer&: *Symbolizer, S);
864 outs() << '\n';
865 }
866
867 SymbolList.clear();
868}
869
870static char getSymbolNMTypeChar(ELFObjectFileBase &Obj,
871 basic_symbol_iterator I) {
872 // OK, this is ELF
873 elf_symbol_iterator SymI(I);
874
875 Expected<elf_section_iterator> SecIOrErr = SymI->getSection();
876 if (!SecIOrErr) {
877 consumeError(Err: SecIOrErr.takeError());
878 return '?';
879 }
880
881 uint8_t Binding = SymI->getBinding();
882 if (Binding == ELF::STB_GNU_UNIQUE)
883 return 'u';
884
885 assert(Binding != ELF::STB_WEAK && "STB_WEAK not tested in calling function");
886 if (Binding != ELF::STB_GLOBAL && Binding != ELF::STB_LOCAL)
887 return '?';
888
889 elf_section_iterator SecI = *SecIOrErr;
890 if (SecI != Obj.section_end()) {
891 uint32_t Type = SecI->getType();
892 uint64_t Flags = SecI->getFlags();
893 if (Flags & ELF::SHF_EXECINSTR)
894 return 't';
895 if (Type == ELF::SHT_NOBITS)
896 return 'b';
897 if (Flags & ELF::SHF_ALLOC)
898 return Flags & ELF::SHF_WRITE ? 'd' : 'r';
899
900 auto NameOrErr = SecI->getName();
901 if (!NameOrErr) {
902 consumeError(Err: NameOrErr.takeError());
903 return '?';
904 }
905 if ((*NameOrErr).starts_with(Prefix: ".debug"))
906 return 'N';
907 if (!(Flags & ELF::SHF_WRITE))
908 return 'n';
909 }
910
911 return '?';
912}
913
914static char getSymbolNMTypeChar(COFFObjectFile &Obj, symbol_iterator I) {
915 COFFSymbolRef Symb = Obj.getCOFFSymbol(Symbol: *I);
916 // OK, this is COFF.
917 symbol_iterator SymI(I);
918
919 Expected<StringRef> Name = SymI->getName();
920 if (!Name) {
921 consumeError(Err: Name.takeError());
922 return '?';
923 }
924
925 char Ret = StringSwitch<char>(*Name)
926 .StartsWith(S: ".debug", Value: 'N')
927 .StartsWith(S: ".sxdata", Value: 'N')
928 .Default(Value: '?');
929
930 if (Ret != '?')
931 return Ret;
932
933 uint32_t Characteristics = 0;
934 if (!COFF::isReservedSectionNumber(SectionNumber: Symb.getSectionNumber())) {
935 Expected<section_iterator> SecIOrErr = SymI->getSection();
936 if (!SecIOrErr) {
937 consumeError(Err: SecIOrErr.takeError());
938 return '?';
939 }
940 section_iterator SecI = *SecIOrErr;
941 const coff_section *Section = Obj.getCOFFSection(Section: *SecI);
942 Characteristics = Section->Characteristics;
943 if (Expected<StringRef> NameOrErr = Obj.getSectionName(Sec: Section))
944 if (NameOrErr->starts_with(Prefix: ".idata"))
945 return 'i';
946 }
947
948 switch (Symb.getSectionNumber()) {
949 case COFF::IMAGE_SYM_DEBUG:
950 return 'n';
951 default:
952 // Check section type.
953 if (Characteristics & COFF::IMAGE_SCN_CNT_CODE)
954 return 't';
955 if (Characteristics & COFF::IMAGE_SCN_CNT_INITIALIZED_DATA)
956 return Characteristics & COFF::IMAGE_SCN_MEM_WRITE ? 'd' : 'r';
957 if (Characteristics & COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA)
958 return 'b';
959 if (Characteristics & COFF::IMAGE_SCN_LNK_INFO)
960 return 'i';
961 // Check for section symbol.
962 if (Symb.isSectionDefinition())
963 return 's';
964 }
965
966 return '?';
967}
968
969static char getSymbolNMTypeChar(XCOFFObjectFile &Obj, symbol_iterator I) {
970 Expected<uint32_t> TypeOrErr = I->getType();
971 if (!TypeOrErr) {
972 warn(Err: TypeOrErr.takeError(), FileName: Obj.getFileName(),
973 Context: "for symbol with index " +
974 Twine(Obj.getSymbolIndex(SymEntPtr: I->getRawDataRefImpl().p)));
975 return '?';
976 }
977
978 uint32_t SymType = *TypeOrErr;
979
980 if (SymType == SymbolRef::ST_File)
981 return 'f';
982
983 // If the I->getSection() call would return an error, the earlier I->getType()
984 // call will already have returned the same error first.
985 section_iterator SecIter = cantFail(ValOrErr: I->getSection());
986
987 if (SecIter == Obj.section_end())
988 return '?';
989
990 if (Obj.isDebugSection(Sec: SecIter->getRawDataRefImpl()))
991 return 'N';
992
993 if (SecIter->isText())
994 return 't';
995
996 if (SecIter->isData())
997 return 'd';
998
999 if (SecIter->isBSS())
1000 return 'b';
1001
1002 return '?';
1003}
1004
1005static char getSymbolNMTypeChar(COFFImportFile &Obj) {
1006 switch (Obj.getCOFFImportHeader()->getType()) {
1007 case COFF::IMPORT_CODE:
1008 return 't';
1009 case COFF::IMPORT_DATA:
1010 return 'd';
1011 case COFF::IMPORT_CONST:
1012 return 'r';
1013 }
1014 return '?';
1015}
1016
1017static char getSymbolNMTypeChar(GOFFObjectFile &, basic_symbol_iterator I) {
1018 GOFFSymbolRef Ref(*I);
1019 Expected<SymbolRef::Type> Type = Ref.getSymbolGOFFType();
1020 // TODO: Add a test using yaml2obj once GOFF ESD record support is
1021 // available in yaml2obj.
1022 if (!Type) {
1023 consumeError(Err: Type.takeError());
1024 return '?';
1025 }
1026 switch (*Type) {
1027 case SymbolRef::ST_Data:
1028 return 'd';
1029 case SymbolRef::ST_Function:
1030 return 't';
1031 default:
1032 llvm_unreachable("GOFFObjectFile::getSymbolType returned unexpected type");
1033 }
1034}
1035
1036static char getSymbolNMTypeChar(MachOObjectFile &Obj, basic_symbol_iterator I) {
1037 DataRefImpl Symb = I->getRawDataRefImpl();
1038 uint8_t NType = Obj.is64Bit() ? Obj.getSymbol64TableEntry(DRI: Symb).n_type
1039 : Obj.getSymbolTableEntry(DRI: Symb).n_type;
1040
1041 if (NType & MachO::N_STAB)
1042 return '-';
1043
1044 switch (NType & MachO::N_TYPE) {
1045 case MachO::N_ABS:
1046 return 's';
1047 case MachO::N_INDR:
1048 return 'i';
1049 case MachO::N_SECT: {
1050 Expected<section_iterator> SecOrErr = Obj.getSymbolSection(Symb);
1051 if (!SecOrErr) {
1052 consumeError(Err: SecOrErr.takeError());
1053 return 's';
1054 }
1055 section_iterator Sec = *SecOrErr;
1056 if (Sec == Obj.section_end())
1057 return 's';
1058 DataRefImpl Ref = Sec->getRawDataRefImpl();
1059 StringRef SectionName;
1060 if (Expected<StringRef> NameOrErr = Obj.getSectionName(Sec: Ref))
1061 SectionName = *NameOrErr;
1062 StringRef SegmentName = Obj.getSectionFinalSegmentName(Sec: Ref);
1063 if (Obj.is64Bit() && Obj.getHeader64().filetype == MachO::MH_KEXT_BUNDLE &&
1064 SegmentName == "__TEXT_EXEC" && SectionName == "__text")
1065 return 't';
1066 if (SegmentName == "__TEXT" && SectionName == "__text")
1067 return 't';
1068 if (SegmentName == "__DATA" && SectionName == "__data")
1069 return 'd';
1070 if (SegmentName == "__DATA" && SectionName == "__bss")
1071 return 'b';
1072 return 's';
1073 }
1074 }
1075
1076 return '?';
1077}
1078
1079static char getSymbolNMTypeChar(TapiFile &Obj, basic_symbol_iterator I) {
1080 auto Type = cantFail(ValOrErr: Obj.getSymbolType(DRI: I->getRawDataRefImpl()));
1081 switch (Type) {
1082 case SymbolRef::ST_Function:
1083 return 't';
1084 case SymbolRef::ST_Data:
1085 if (Obj.hasSegmentInfo())
1086 return 'd';
1087 [[fallthrough]];
1088 default:
1089 return 's';
1090 }
1091}
1092
1093static char getSymbolNMTypeChar(WasmObjectFile &Obj, basic_symbol_iterator I) {
1094 uint32_t Flags = cantFail(ValOrErr: I->getFlags());
1095 if (Flags & SymbolRef::SF_Executable)
1096 return 't';
1097 return 'd';
1098}
1099
1100static char getSymbolNMTypeChar(IRObjectFile &Obj, basic_symbol_iterator I) {
1101 uint32_t Flags = cantFail(ValOrErr: I->getFlags());
1102 // FIXME: should we print 'b'? At the IR level we cannot be sure if this
1103 // will be in bss or not, but we could approximate.
1104 if (Flags & SymbolRef::SF_Executable)
1105 return 't';
1106 else if (Triple(Obj.getTargetTriple()).isOSDarwin() &&
1107 (Flags & SymbolRef::SF_Const))
1108 return 's';
1109 else
1110 return 'd';
1111}
1112
1113static bool isObject(SymbolicFile &Obj, basic_symbol_iterator I) {
1114 return isa<ELFObjectFileBase>(Val: &Obj) &&
1115 elf_symbol_iterator(I)->getELFType() == ELF::STT_OBJECT;
1116}
1117
1118// For ELF object files, Set TypeName to the symbol typename, to be printed
1119// in the 'Type' column of the SYSV format output.
1120static StringRef getNMTypeName(SymbolicFile &Obj, basic_symbol_iterator I) {
1121 if (isa<ELFObjectFileBase>(Val: &Obj)) {
1122 elf_symbol_iterator SymI(I);
1123 return SymI->getELFTypeName();
1124 }
1125 return "";
1126}
1127
1128// Return Posix nm class type tag (single letter), but also set SecName and
1129// section and name, to be used in format=sysv output.
1130static char getNMSectionTagAndName(SymbolicFile &Obj, basic_symbol_iterator I,
1131 StringRef &SecName) {
1132 // Symbol Flags have been checked in the caller.
1133 uint32_t Symflags = cantFail(ValOrErr: I->getFlags());
1134 if (ELFObjectFileBase *ELFObj = dyn_cast<ELFObjectFileBase>(Val: &Obj)) {
1135 if (Symflags & object::SymbolRef::SF_Absolute)
1136 SecName = "*ABS*";
1137 else if (Symflags & object::SymbolRef::SF_Common)
1138 SecName = "*COM*";
1139 else if (Symflags & object::SymbolRef::SF_Undefined)
1140 SecName = "*UND*";
1141 else {
1142 elf_symbol_iterator SymI(I);
1143 Expected<elf_section_iterator> SecIOrErr = SymI->getSection();
1144 if (!SecIOrErr) {
1145 consumeError(Err: SecIOrErr.takeError());
1146 return '?';
1147 }
1148
1149 if (*SecIOrErr == ELFObj->section_end())
1150 return '?';
1151
1152 Expected<StringRef> NameOrErr = (*SecIOrErr)->getName();
1153 if (!NameOrErr) {
1154 consumeError(Err: NameOrErr.takeError());
1155 return '?';
1156 }
1157 SecName = *NameOrErr;
1158 }
1159 }
1160
1161 if (Symflags & object::SymbolRef::SF_Undefined) {
1162 if (isa<MachOObjectFile>(Val: Obj) || !(Symflags & object::SymbolRef::SF_Weak))
1163 return 'U';
1164 return isObject(Obj, I) ? 'v' : 'w';
1165 }
1166 if (isa<ELFObjectFileBase>(Val: &Obj))
1167 if (ELFSymbolRef(*I).getELFType() == ELF::STT_GNU_IFUNC)
1168 return 'i';
1169 if (!isa<MachOObjectFile>(Val: Obj) && (Symflags & object::SymbolRef::SF_Weak))
1170 return isObject(Obj, I) ? 'V' : 'W';
1171
1172 if (Symflags & object::SymbolRef::SF_Common)
1173 return 'C';
1174
1175 char Ret = '?';
1176 if (Symflags & object::SymbolRef::SF_Absolute)
1177 Ret = 'a';
1178 else if (IRObjectFile *IR = dyn_cast<IRObjectFile>(Val: &Obj))
1179 Ret = getSymbolNMTypeChar(Obj&: *IR, I);
1180 else if (COFFObjectFile *COFF = dyn_cast<COFFObjectFile>(Val: &Obj))
1181 Ret = getSymbolNMTypeChar(Obj&: *COFF, I);
1182 else if (XCOFFObjectFile *XCOFF = dyn_cast<XCOFFObjectFile>(Val: &Obj))
1183 Ret = getSymbolNMTypeChar(Obj&: *XCOFF, I);
1184 else if (COFFImportFile *COFFImport = dyn_cast<COFFImportFile>(Val: &Obj))
1185 Ret = getSymbolNMTypeChar(Obj&: *COFFImport);
1186 else if (MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(Val: &Obj))
1187 Ret = getSymbolNMTypeChar(Obj&: *MachO, I);
1188 else if (WasmObjectFile *Wasm = dyn_cast<WasmObjectFile>(Val: &Obj))
1189 Ret = getSymbolNMTypeChar(Obj&: *Wasm, I);
1190 else if (TapiFile *Tapi = dyn_cast<TapiFile>(Val: &Obj))
1191 Ret = getSymbolNMTypeChar(Obj&: *Tapi, I);
1192 else if (ELFObjectFileBase *ELF = dyn_cast<ELFObjectFileBase>(Val: &Obj)) {
1193 Ret = getSymbolNMTypeChar(Obj&: *ELF, I);
1194 if (ELFSymbolRef(*I).getBinding() == ELF::STB_GNU_UNIQUE)
1195 return Ret;
1196 } else if (GOFFObjectFile *GOFF = dyn_cast<GOFFObjectFile>(Val: &Obj)) {
1197 Ret = getSymbolNMTypeChar(*GOFF, I);
1198 } else
1199 llvm_unreachable("unknown binary format");
1200
1201 if (!(Symflags & object::SymbolRef::SF_Global))
1202 return Ret;
1203
1204 return toupper(c: Ret);
1205}
1206
1207// getNsectForSegSect() is used to implement the Mach-O "-s segname sectname"
1208// option to dump only those symbols from that section in a Mach-O file.
1209// It is called once for each Mach-O file from getSymbolNamesFromObject()
1210// to get the section number for that named section from the command line
1211// arguments. It returns the section number for that section in the Mach-O
1212// file or zero it is not present.
1213static unsigned getNsectForSegSect(MachOObjectFile *Obj) {
1214 unsigned Nsect = 1;
1215 for (auto &S : Obj->sections()) {
1216 DataRefImpl Ref = S.getRawDataRefImpl();
1217 StringRef SectionName;
1218 if (Expected<StringRef> NameOrErr = Obj->getSectionName(Sec: Ref))
1219 SectionName = *NameOrErr;
1220 StringRef SegmentName = Obj->getSectionFinalSegmentName(Sec: Ref);
1221 if (SegmentName == SegSect[0] && SectionName == SegSect[1])
1222 return Nsect;
1223 Nsect++;
1224 }
1225 return 0;
1226}
1227
1228// getNsectInMachO() is used to implement the Mach-O "-s segname sectname"
1229// option to dump only those symbols from that section in a Mach-O file.
1230// It is called once for each symbol in a Mach-O file from
1231// getSymbolNamesFromObject() and returns the section number for that symbol
1232// if it is in a section, else it returns 0.
1233static unsigned getNsectInMachO(MachOObjectFile &Obj, BasicSymbolRef Sym) {
1234 DataRefImpl Symb = Sym.getRawDataRefImpl();
1235 if (Obj.is64Bit()) {
1236 MachO::nlist_64 STE = Obj.getSymbol64TableEntry(DRI: Symb);
1237 return (STE.n_type & MachO::N_TYPE) == MachO::N_SECT ? STE.n_sect : 0;
1238 }
1239 MachO::nlist STE = Obj.getSymbolTableEntry(DRI: Symb);
1240 return (STE.n_type & MachO::N_TYPE) == MachO::N_SECT ? STE.n_sect : 0;
1241}
1242
1243static void dumpSymbolsFromDLInfoMachO(MachOObjectFile &MachO,
1244 std::vector<NMSymbol> &SymbolList) {
1245 size_t I = SymbolList.size();
1246 std::string ExportsNameBuffer;
1247 raw_string_ostream EOS(ExportsNameBuffer);
1248 std::string BindsNameBuffer;
1249 raw_string_ostream BOS(BindsNameBuffer);
1250 std::string LazysNameBuffer;
1251 raw_string_ostream LOS(LazysNameBuffer);
1252 std::string WeaksNameBuffer;
1253 raw_string_ostream WOS(WeaksNameBuffer);
1254 std::string FunctionStartsNameBuffer;
1255 raw_string_ostream FOS(FunctionStartsNameBuffer);
1256
1257 MachO::mach_header H;
1258 MachO::mach_header_64 H_64;
1259 uint32_t HFlags = 0;
1260 if (MachO.is64Bit()) {
1261 H_64 = MachO.MachOObjectFile::getHeader64();
1262 HFlags = H_64.flags;
1263 } else {
1264 H = MachO.MachOObjectFile::getHeader();
1265 HFlags = H.flags;
1266 }
1267 uint64_t BaseSegmentAddress = 0;
1268 for (const auto &Command : MachO.load_commands()) {
1269 if (Command.C.cmd == MachO::LC_SEGMENT) {
1270 MachO::segment_command Seg = MachO.getSegmentLoadCommand(L: Command);
1271 if (Seg.fileoff == 0 && Seg.filesize != 0) {
1272 BaseSegmentAddress = Seg.vmaddr;
1273 break;
1274 }
1275 } else if (Command.C.cmd == MachO::LC_SEGMENT_64) {
1276 MachO::segment_command_64 Seg = MachO.getSegment64LoadCommand(L: Command);
1277 if (Seg.fileoff == 0 && Seg.filesize != 0) {
1278 BaseSegmentAddress = Seg.vmaddr;
1279 break;
1280 }
1281 }
1282 }
1283 if (DyldInfoOnly || AddDyldInfo ||
1284 HFlags & MachO::MH_NLIST_OUTOFSYNC_WITH_DYLDINFO) {
1285 unsigned ExportsAdded = 0;
1286 Error Err = Error::success();
1287 for (const llvm::object::ExportEntry &Entry : MachO.exports(Err)) {
1288 bool found = false;
1289 bool ReExport = false;
1290 if (!DyldInfoOnly) {
1291 for (const NMSymbol &S : SymbolList)
1292 if (S.Address == Entry.address() + BaseSegmentAddress &&
1293 S.Name == Entry.name()) {
1294 found = true;
1295 break;
1296 }
1297 }
1298 if (!found) {
1299 NMSymbol S = {};
1300 S.Address = Entry.address() + BaseSegmentAddress;
1301 S.Size = 0;
1302 S.TypeChar = '\0';
1303 S.Name = Entry.name().str();
1304 // There is no symbol in the nlist symbol table for this so we set
1305 // Sym effectivly to null and the rest of code in here must test for
1306 // it and not do things like Sym.getFlags() for it.
1307 S.Sym = BasicSymbolRef();
1308 S.SymFlags = SymbolRef::SF_Global;
1309 S.Section = SectionRef();
1310 S.NType = 0;
1311 S.NSect = 0;
1312 S.NDesc = 0;
1313
1314 uint64_t EFlags = Entry.flags();
1315 bool Abs = ((EFlags & MachO::EXPORT_SYMBOL_FLAGS_KIND_MASK) ==
1316 MachO::EXPORT_SYMBOL_FLAGS_KIND_ABSOLUTE);
1317 bool Resolver = (EFlags & MachO::EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER);
1318 ReExport = (EFlags & MachO::EXPORT_SYMBOL_FLAGS_REEXPORT);
1319 bool WeakDef = (EFlags & MachO::EXPORT_SYMBOL_FLAGS_WEAK_DEFINITION);
1320 if (WeakDef)
1321 S.NDesc |= MachO::N_WEAK_DEF;
1322 if (Abs) {
1323 S.NType = MachO::N_EXT | MachO::N_ABS;
1324 S.TypeChar = 'A';
1325 } else if (ReExport) {
1326 S.NType = MachO::N_EXT | MachO::N_INDR;
1327 S.TypeChar = 'I';
1328 } else {
1329 S.NType = MachO::N_EXT | MachO::N_SECT;
1330 if (Resolver) {
1331 S.Address = Entry.other() + BaseSegmentAddress;
1332 if ((S.Address & 1) != 0 && !MachO.is64Bit() &&
1333 H.cputype == MachO::CPU_TYPE_ARM) {
1334 S.Address &= ~1LL;
1335 S.NDesc |= MachO::N_ARM_THUMB_DEF;
1336 }
1337 } else {
1338 S.Address = Entry.address() + BaseSegmentAddress;
1339 }
1340 StringRef SegmentName = StringRef();
1341 StringRef SectionName = StringRef();
1342 for (const SectionRef &Section : MachO.sections()) {
1343 S.NSect++;
1344
1345 if (Expected<StringRef> NameOrErr = Section.getName())
1346 SectionName = *NameOrErr;
1347 else
1348 consumeError(Err: NameOrErr.takeError());
1349
1350 SegmentName =
1351 MachO.getSectionFinalSegmentName(Sec: Section.getRawDataRefImpl());
1352 if (S.Address >= Section.getAddress() &&
1353 S.Address < Section.getAddress() + Section.getSize()) {
1354 S.Section = Section;
1355 break;
1356 } else if (Entry.name() == "__mh_execute_header" &&
1357 SegmentName == "__TEXT" && SectionName == "__text") {
1358 S.Section = Section;
1359 S.NDesc |= MachO::REFERENCED_DYNAMICALLY;
1360 break;
1361 }
1362 }
1363 if (SegmentName == "__TEXT" && SectionName == "__text")
1364 S.TypeChar = 'T';
1365 else if (SegmentName == "__DATA" && SectionName == "__data")
1366 S.TypeChar = 'D';
1367 else if (SegmentName == "__DATA" && SectionName == "__bss")
1368 S.TypeChar = 'B';
1369 else
1370 S.TypeChar = 'S';
1371 }
1372 SymbolList.push_back(x: S);
1373
1374 EOS << Entry.name();
1375 EOS << '\0';
1376 ExportsAdded++;
1377
1378 // For ReExports there are a two more things to do, first add the
1379 // indirect name and second create the undefined symbol using the
1380 // referened dynamic library.
1381 if (ReExport) {
1382
1383 // Add the indirect name.
1384 if (Entry.otherName().empty())
1385 EOS << Entry.name();
1386 else
1387 EOS << Entry.otherName();
1388 EOS << '\0';
1389
1390 // Now create the undefined symbol using the referened dynamic
1391 // library.
1392 NMSymbol U = {};
1393 U.Address = 0;
1394 U.Size = 0;
1395 U.TypeChar = 'U';
1396 if (Entry.otherName().empty())
1397 U.Name = Entry.name().str();
1398 else
1399 U.Name = Entry.otherName().str();
1400 // Again there is no symbol in the nlist symbol table for this so
1401 // we set Sym effectivly to null and the rest of code in here must
1402 // test for it and not do things like Sym.getFlags() for it.
1403 U.Sym = BasicSymbolRef();
1404 U.SymFlags = SymbolRef::SF_Global | SymbolRef::SF_Undefined;
1405 U.Section = SectionRef();
1406 U.NType = MachO::N_EXT | MachO::N_UNDF;
1407 U.NSect = 0;
1408 U.NDesc = 0;
1409 // The library ordinal for this undefined symbol is in the export
1410 // trie Entry.other().
1411 MachO::SET_LIBRARY_ORDINAL(n_desc&: U.NDesc, ordinal: Entry.other());
1412 SymbolList.push_back(x: U);
1413
1414 // Finally add the undefined symbol's name.
1415 if (Entry.otherName().empty())
1416 EOS << Entry.name();
1417 else
1418 EOS << Entry.otherName();
1419 EOS << '\0';
1420 ExportsAdded++;
1421 }
1422 }
1423 }
1424 if (Err)
1425 error(E: std::move(Err), FileName: MachO.getFileName());
1426 // Set the symbol names and indirect names for the added symbols.
1427 if (ExportsAdded) {
1428 const char *Q = ExportsNameBuffer.c_str();
1429 for (unsigned K = 0; K < ExportsAdded; K++) {
1430 SymbolList[I].Name = Q;
1431 Q += strlen(s: Q) + 1;
1432 if (SymbolList[I].TypeChar == 'I') {
1433 SymbolList[I].IndirectName = Q;
1434 Q += strlen(s: Q) + 1;
1435 }
1436 I++;
1437 }
1438 }
1439
1440 // Add the undefined symbols from the bind entries.
1441 unsigned BindsAdded = 0;
1442 Error BErr = Error::success();
1443 StringRef LastSymbolName = StringRef();
1444 for (const llvm::object::MachOBindEntry &Entry : MachO.bindTable(Err&: BErr)) {
1445 bool found = false;
1446 if (LastSymbolName == Entry.symbolName())
1447 found = true;
1448 else if (!DyldInfoOnly) {
1449 for (unsigned J = 0; J < SymbolList.size() && !found; ++J) {
1450 if (SymbolList[J].Name == Entry.symbolName())
1451 found = true;
1452 }
1453 }
1454 if (!found) {
1455 LastSymbolName = Entry.symbolName();
1456 NMSymbol B = {};
1457 B.Address = 0;
1458 B.Size = 0;
1459 B.TypeChar = 'U';
1460 // There is no symbol in the nlist symbol table for this so we set
1461 // Sym effectivly to null and the rest of code in here must test for
1462 // it and not do things like Sym.getFlags() for it.
1463 B.Sym = BasicSymbolRef();
1464 B.SymFlags = SymbolRef::SF_Global | SymbolRef::SF_Undefined;
1465 B.NType = MachO::N_EXT | MachO::N_UNDF;
1466 B.NSect = 0;
1467 B.NDesc = 0;
1468 MachO::SET_LIBRARY_ORDINAL(n_desc&: B.NDesc, ordinal: Entry.ordinal());
1469 B.Name = Entry.symbolName().str();
1470 SymbolList.push_back(x: B);
1471 BOS << Entry.symbolName();
1472 BOS << '\0';
1473 BindsAdded++;
1474 }
1475 }
1476 if (BErr)
1477 error(E: std::move(BErr), FileName: MachO.getFileName());
1478 // Set the symbol names and indirect names for the added symbols.
1479 if (BindsAdded) {
1480 const char *Q = BindsNameBuffer.c_str();
1481 for (unsigned K = 0; K < BindsAdded; K++) {
1482 SymbolList[I].Name = Q;
1483 Q += strlen(s: Q) + 1;
1484 if (SymbolList[I].TypeChar == 'I') {
1485 SymbolList[I].IndirectName = Q;
1486 Q += strlen(s: Q) + 1;
1487 }
1488 I++;
1489 }
1490 }
1491
1492 // Add the undefined symbols from the lazy bind entries.
1493 unsigned LazysAdded = 0;
1494 Error LErr = Error::success();
1495 LastSymbolName = StringRef();
1496 for (const llvm::object::MachOBindEntry &Entry :
1497 MachO.lazyBindTable(Err&: LErr)) {
1498 bool found = false;
1499 if (LastSymbolName == Entry.symbolName())
1500 found = true;
1501 else {
1502 // Here we must check to see it this symbol is already in the
1503 // SymbolList as it might have already have been added above via a
1504 // non-lazy (bind) entry.
1505 for (unsigned J = 0; J < SymbolList.size() && !found; ++J) {
1506 if (SymbolList[J].Name == Entry.symbolName())
1507 found = true;
1508 }
1509 }
1510 if (!found) {
1511 LastSymbolName = Entry.symbolName();
1512 NMSymbol L = {};
1513 L.Name = Entry.symbolName().str();
1514 L.Address = 0;
1515 L.Size = 0;
1516 L.TypeChar = 'U';
1517 // There is no symbol in the nlist symbol table for this so we set
1518 // Sym effectivly to null and the rest of code in here must test for
1519 // it and not do things like Sym.getFlags() for it.
1520 L.Sym = BasicSymbolRef();
1521 L.SymFlags = SymbolRef::SF_Global | SymbolRef::SF_Undefined;
1522 L.NType = MachO::N_EXT | MachO::N_UNDF;
1523 L.NSect = 0;
1524 // The REFERENCE_FLAG_UNDEFINED_LAZY is no longer used but here it
1525 // makes sence since we are creating this from a lazy bind entry.
1526 L.NDesc = MachO::REFERENCE_FLAG_UNDEFINED_LAZY;
1527 MachO::SET_LIBRARY_ORDINAL(n_desc&: L.NDesc, ordinal: Entry.ordinal());
1528 SymbolList.push_back(x: L);
1529 LOS << Entry.symbolName();
1530 LOS << '\0';
1531 LazysAdded++;
1532 }
1533 }
1534 if (LErr)
1535 error(E: std::move(LErr), FileName: MachO.getFileName());
1536 // Set the symbol names and indirect names for the added symbols.
1537 if (LazysAdded) {
1538 const char *Q = LazysNameBuffer.c_str();
1539 for (unsigned K = 0; K < LazysAdded; K++) {
1540 SymbolList[I].Name = Q;
1541 Q += strlen(s: Q) + 1;
1542 if (SymbolList[I].TypeChar == 'I') {
1543 SymbolList[I].IndirectName = Q;
1544 Q += strlen(s: Q) + 1;
1545 }
1546 I++;
1547 }
1548 }
1549
1550 // Add the undefineds symbol from the weak bind entries which are not
1551 // strong symbols.
1552 unsigned WeaksAdded = 0;
1553 Error WErr = Error::success();
1554 LastSymbolName = StringRef();
1555 for (const llvm::object::MachOBindEntry &Entry :
1556 MachO.weakBindTable(Err&: WErr)) {
1557 bool found = false;
1558 unsigned J = 0;
1559 if (LastSymbolName == Entry.symbolName() ||
1560 Entry.flags() & MachO::BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION) {
1561 found = true;
1562 } else {
1563 for (J = 0; J < SymbolList.size() && !found; ++J) {
1564 if (SymbolList[J].Name == Entry.symbolName()) {
1565 found = true;
1566 break;
1567 }
1568 }
1569 }
1570 if (!found) {
1571 LastSymbolName = Entry.symbolName();
1572 NMSymbol W = {};
1573 W.Name = Entry.symbolName().str();
1574 W.Address = 0;
1575 W.Size = 0;
1576 W.TypeChar = 'U';
1577 // There is no symbol in the nlist symbol table for this so we set
1578 // Sym effectivly to null and the rest of code in here must test for
1579 // it and not do things like Sym.getFlags() for it.
1580 W.Sym = BasicSymbolRef();
1581 W.SymFlags = SymbolRef::SF_Global | SymbolRef::SF_Undefined;
1582 W.NType = MachO::N_EXT | MachO::N_UNDF;
1583 W.NSect = 0;
1584 // Odd that we are using N_WEAK_DEF on an undefined symbol but that is
1585 // what is created in this case by the linker when there are real
1586 // symbols in the nlist structs.
1587 W.NDesc = MachO::N_WEAK_DEF;
1588 SymbolList.push_back(x: W);
1589 WOS << Entry.symbolName();
1590 WOS << '\0';
1591 WeaksAdded++;
1592 } else {
1593 // This is the case the symbol was previously been found and it could
1594 // have been added from a bind or lazy bind symbol. If so and not
1595 // a definition also mark it as weak.
1596 if (SymbolList[J].TypeChar == 'U')
1597 // See comment above about N_WEAK_DEF.
1598 SymbolList[J].NDesc |= MachO::N_WEAK_DEF;
1599 }
1600 }
1601 if (WErr)
1602 error(E: std::move(WErr), FileName: MachO.getFileName());
1603 // Set the symbol names and indirect names for the added symbols.
1604 if (WeaksAdded) {
1605 const char *Q = WeaksNameBuffer.c_str();
1606 for (unsigned K = 0; K < WeaksAdded; K++) {
1607 SymbolList[I].Name = Q;
1608 Q += strlen(s: Q) + 1;
1609 if (SymbolList[I].TypeChar == 'I') {
1610 SymbolList[I].IndirectName = Q;
1611 Q += strlen(s: Q) + 1;
1612 }
1613 I++;
1614 }
1615 }
1616
1617 // Trying adding symbol from the function starts table and LC_MAIN entry
1618 // point.
1619 SmallVector<uint64_t, 8> FoundFns;
1620 uint64_t lc_main_offset = UINT64_MAX;
1621 for (const auto &Command : MachO.load_commands()) {
1622 if (Command.C.cmd == MachO::LC_FUNCTION_STARTS) {
1623 // We found a function starts segment, parse the addresses for
1624 // consumption.
1625 MachO::linkedit_data_command LLC =
1626 MachO.getLinkeditDataLoadCommand(L: Command);
1627
1628 MachO.ReadULEB128s(Index: LLC.dataoff, Out&: FoundFns);
1629 } else if (Command.C.cmd == MachO::LC_MAIN) {
1630 MachO::entry_point_command LCmain = MachO.getEntryPointCommand(L: Command);
1631 lc_main_offset = LCmain.entryoff;
1632 }
1633 }
1634 // See if these addresses are already in the symbol table.
1635 unsigned FunctionStartsAdded = 0;
1636 // The addresses from FoundFns come from LC_FUNCTION_STARTS. Its contents
1637 // are delta encoded addresses from the start of __TEXT, ending when zero
1638 // is found. Because of this, the addresses should be unique, and even if
1639 // we create fake entries on SymbolList in the second loop, SymbolAddresses
1640 // should not need to be updated there.
1641 SmallSet<uint64_t, 32> SymbolAddresses;
1642 for (const auto &S : SymbolList)
1643 SymbolAddresses.insert(V: S.Address);
1644 for (uint64_t f = 0; f < FoundFns.size(); f++) {
1645 // See if this address is already in the symbol table, otherwise fake up
1646 // an nlist for it.
1647 if (!SymbolAddresses.contains(V: FoundFns[f] + BaseSegmentAddress)) {
1648 NMSymbol F = {};
1649 F.Name = "<redacted function X>";
1650 F.Address = FoundFns[f] + BaseSegmentAddress;
1651 F.Size = 0;
1652 // There is no symbol in the nlist symbol table for this so we set
1653 // Sym effectivly to null and the rest of code in here must test for
1654 // it and not do things like Sym.getFlags() for it.
1655 F.Sym = BasicSymbolRef();
1656 F.SymFlags = 0;
1657 F.NType = MachO::N_SECT;
1658 F.NSect = 0;
1659 StringRef SegmentName = StringRef();
1660 StringRef SectionName = StringRef();
1661 for (const SectionRef &Section : MachO.sections()) {
1662 if (Expected<StringRef> NameOrErr = Section.getName())
1663 SectionName = *NameOrErr;
1664 else
1665 consumeError(Err: NameOrErr.takeError());
1666
1667 SegmentName =
1668 MachO.getSectionFinalSegmentName(Sec: Section.getRawDataRefImpl());
1669 F.NSect++;
1670 if (F.Address >= Section.getAddress() &&
1671 F.Address < Section.getAddress() + Section.getSize()) {
1672 F.Section = Section;
1673 break;
1674 }
1675 }
1676 if (SegmentName == "__TEXT" && SectionName == "__text")
1677 F.TypeChar = 't';
1678 else if (SegmentName == "__DATA" && SectionName == "__data")
1679 F.TypeChar = 'd';
1680 else if (SegmentName == "__DATA" && SectionName == "__bss")
1681 F.TypeChar = 'b';
1682 else
1683 F.TypeChar = 's';
1684 F.NDesc = 0;
1685 SymbolList.push_back(x: F);
1686 if (FoundFns[f] == lc_main_offset)
1687 FOS << "<redacted LC_MAIN>";
1688 else
1689 FOS << "<redacted function " << f << ">";
1690 FOS << '\0';
1691 FunctionStartsAdded++;
1692 }
1693 }
1694 if (FunctionStartsAdded) {
1695 const char *Q = FunctionStartsNameBuffer.c_str();
1696 for (unsigned K = 0; K < FunctionStartsAdded; K++) {
1697 SymbolList[I].Name = Q;
1698 Q += strlen(s: Q) + 1;
1699 if (SymbolList[I].TypeChar == 'I') {
1700 SymbolList[I].IndirectName = Q;
1701 Q += strlen(s: Q) + 1;
1702 }
1703 I++;
1704 }
1705 }
1706 }
1707}
1708
1709static bool shouldDump(SymbolicFile &Obj) {
1710 // The -X option is currently only implemented for XCOFF, ELF, and IR object
1711 // files. The option isn't fundamentally impossible with other formats, just
1712 // isn't implemented.
1713 if (!isa<XCOFFObjectFile>(Val: Obj) && !isa<ELFObjectFileBase>(Val: Obj) &&
1714 !isa<IRObjectFile>(Val: Obj))
1715 return true;
1716
1717 return Obj.is64Bit() ? BitMode != BitModeTy::Bit32
1718 : BitMode != BitModeTy::Bit64;
1719}
1720
1721static void getXCOFFExports(XCOFFObjectFile *XCOFFObj,
1722 std::vector<NMSymbol> &SymbolList,
1723 StringRef ArchiveName) {
1724 // Skip Shared object file.
1725 if (XCOFFObj->getFlags() & XCOFF::F_SHROBJ)
1726 return;
1727
1728 for (SymbolRef Sym : XCOFFObj->symbols()) {
1729 // There is no visibility in old 32 bit XCOFF object file interpret.
1730 bool HasVisibilityAttr =
1731 XCOFFObj->is64Bit() || (XCOFFObj->auxiliaryHeader32() &&
1732 (XCOFFObj->auxiliaryHeader32()->getVersion() ==
1733 XCOFF::NEW_XCOFF_INTERPRET));
1734
1735 if (HasVisibilityAttr) {
1736 XCOFFSymbolRef XCOFFSym = XCOFFObj->toSymbolRef(Ref: Sym.getRawDataRefImpl());
1737 uint16_t SymType = XCOFFSym.getSymbolType();
1738 if ((SymType & XCOFF::VISIBILITY_MASK) == XCOFF::SYM_V_INTERNAL)
1739 continue;
1740 if ((SymType & XCOFF::VISIBILITY_MASK) == XCOFF::SYM_V_HIDDEN)
1741 continue;
1742 }
1743
1744 Expected<section_iterator> SymSecOrErr = Sym.getSection();
1745 if (!SymSecOrErr) {
1746 warn(Err: SymSecOrErr.takeError(), FileName: XCOFFObj->getFileName(),
1747 Context: "for symbol with index " +
1748 Twine(XCOFFObj->getSymbolIndex(SymEntPtr: Sym.getRawDataRefImpl().p)),
1749 Archive: ArchiveName);
1750 continue;
1751 }
1752 section_iterator SecIter = *SymSecOrErr;
1753 // If the symbol is not in a text or data section, it is not exported.
1754 if (SecIter == XCOFFObj->section_end())
1755 continue;
1756 if (!(SecIter->isText() || SecIter->isData() || SecIter->isBSS()))
1757 continue;
1758
1759 StringRef SymName = cantFail(ValOrErr: Sym.getName());
1760 if (SymName.empty())
1761 continue;
1762 if (SymName.starts_with(Prefix: "__sinit") || SymName.starts_with(Prefix: "__sterm") ||
1763 SymName.front() == '.' || SymName.front() == '(')
1764 continue;
1765
1766 // Check the SymName regex matching with "^__[0-9]+__".
1767 if (SymName.size() > 4 && SymName.starts_with(Prefix: "__") &&
1768 SymName.ends_with(Suffix: "__")) {
1769 if (std::all_of(first: SymName.begin() + 2, last: SymName.end() - 2, pred: isDigit))
1770 continue;
1771 }
1772
1773 if (SymName == "__rsrc" && NoRsrc)
1774 continue;
1775
1776 if (SymName.starts_with(Prefix: "__tf1"))
1777 SymName = SymName.substr(Start: 6);
1778 else if (SymName.starts_with(Prefix: "__tf9"))
1779 SymName = SymName.substr(Start: 14);
1780
1781 NMSymbol S = {};
1782 S.Name = SymName.str();
1783 S.Sym = Sym;
1784
1785 if (HasVisibilityAttr) {
1786 XCOFFSymbolRef XCOFFSym = XCOFFObj->toSymbolRef(Ref: Sym.getRawDataRefImpl());
1787 uint16_t SymType = XCOFFSym.getSymbolType();
1788 if ((SymType & XCOFF::VISIBILITY_MASK) == XCOFF::SYM_V_PROTECTED)
1789 S.Visibility = "protected";
1790 else if ((SymType & XCOFF::VISIBILITY_MASK) == XCOFF::SYM_V_EXPORTED)
1791 S.Visibility = "export";
1792 }
1793 if (S.initializeFlags(Obj: *XCOFFObj))
1794 SymbolList.push_back(x: S);
1795 }
1796}
1797
1798static Expected<SymbolicFile::basic_symbol_iterator_range>
1799getDynamicSyms(SymbolicFile &Obj) {
1800 const auto *E = dyn_cast<ELFObjectFileBase>(Val: &Obj);
1801 if (!E)
1802 return createError(Err: "File format has no dynamic symbol table");
1803 return E->getDynamicSymbolIterators();
1804}
1805
1806// Returns false if there is error found or true otherwise.
1807static bool getSymbolNamesFromObject(SymbolicFile &Obj,
1808 std::vector<NMSymbol> &SymbolList) {
1809 auto Symbols = Obj.symbols();
1810 std::vector<VersionEntry> SymbolVersions;
1811
1812 if (DynamicSyms) {
1813 Expected<SymbolicFile::basic_symbol_iterator_range> SymbolsOrErr =
1814 getDynamicSyms(Obj);
1815 if (!SymbolsOrErr) {
1816 error(E: SymbolsOrErr.takeError(), FileName: Obj.getFileName());
1817 return false;
1818 }
1819 Symbols = *SymbolsOrErr;
1820 if (const auto *E = dyn_cast<ELFObjectFileBase>(Val: &Obj)) {
1821 if (Expected<std::vector<VersionEntry>> VersionsOrErr =
1822 E->readDynsymVersions())
1823 SymbolVersions = std::move(*VersionsOrErr);
1824 else
1825 WithColor::warning(OS&: errs(), Prefix: ToolName)
1826 << "unable to read symbol versions: "
1827 << toString(E: VersionsOrErr.takeError()) << "\n";
1828 }
1829 }
1830 // If a "-s segname sectname" option was specified and this is a Mach-O
1831 // file get the section number for that section in this object file.
1832 unsigned int Nsect = 0;
1833 MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(Val: &Obj);
1834 if (!SegSect.empty() && MachO) {
1835 Nsect = getNsectForSegSect(Obj: MachO);
1836 // If this section is not in the object file no symbols are printed.
1837 if (Nsect == 0)
1838 return false;
1839 }
1840
1841 if (!(MachO && DyldInfoOnly)) {
1842 size_t I = -1;
1843 for (BasicSymbolRef Sym : Symbols) {
1844 ++I;
1845 Expected<uint32_t> SymFlagsOrErr = Sym.getFlags();
1846 if (!SymFlagsOrErr) {
1847 error(E: SymFlagsOrErr.takeError(), FileName: Obj.getFileName());
1848 return false;
1849 }
1850
1851 // Drop format-specific symbols (STT_FILE, STT_SECTION, etc.) but
1852 // retain mapping symbols (STT_NOTYPE such as $d, $x) on ARM, AArch64,
1853 // CSKY, and RISC-V targets to honor the --special-syms option.
1854 if (!DebugSyms && (*SymFlagsOrErr & SymbolRef::SF_FormatSpecific)) {
1855 auto *ELFObj = dyn_cast<ELFObjectFileBase>(Val: &Obj);
1856 bool IsMappingSymbol =
1857 ELFObj &&
1858 llvm::is_contained(
1859 Set: {ELF::EM_ARM, ELF::EM_AARCH64, ELF::EM_CSKY, ELF::EM_RISCV},
1860 Element: ELFObj->getEMachine()) &&
1861 ELFSymbolRef(Sym).getELFType() == ELF::STT_NOTYPE;
1862 if (!IsMappingSymbol)
1863 continue;
1864 }
1865 if (WithoutAliases && (*SymFlagsOrErr & SymbolRef::SF_Indirect))
1866 continue;
1867 // If a "-s segname sectname" option was specified and this is a Mach-O
1868 // file and this section appears in this file, Nsect will be non-zero then
1869 // see if this symbol is a symbol from that section and if not skip it.
1870 if (Nsect && Nsect != getNsectInMachO(Obj&: *MachO, Sym))
1871 continue;
1872 NMSymbol S = {};
1873 S.Size = 0;
1874 S.Address = 0;
1875 if (isa<ELFObjectFileBase>(Val: &Obj))
1876 S.Size = ELFSymbolRef(Sym).getSize();
1877 else if (isa<GOFFObjectFile>(Val: &Obj))
1878 S.Size = GOFFSymbolRef(Sym).getSize();
1879
1880 if (const XCOFFObjectFile *XCOFFObj =
1881 dyn_cast<const XCOFFObjectFile>(Val: &Obj))
1882 S.Size = XCOFFObj->getSymbolSize(Symb: Sym.getRawDataRefImpl());
1883
1884 if (const WasmObjectFile *WasmObj = dyn_cast<WasmObjectFile>(Val: &Obj))
1885 S.Size = WasmObj->getSymbolSize(Sym);
1886
1887 if (PrintAddress && isa<ObjectFile>(Val: Obj)) {
1888 SymbolRef SymRef(Sym);
1889 Expected<uint64_t> AddressOrErr = SymRef.getAddress();
1890 if (!AddressOrErr) {
1891 consumeError(Err: AddressOrErr.takeError());
1892 break;
1893 }
1894 S.Address = *AddressOrErr;
1895 }
1896 S.TypeName = getNMTypeName(Obj, I: Sym);
1897 S.TypeChar = getNMSectionTagAndName(Obj, I: Sym, SecName&: S.SectionName);
1898
1899 raw_string_ostream OS(S.Name);
1900 if (Error E = Sym.printName(OS)) {
1901 if (MachO) {
1902 OS << "bad string index";
1903 consumeError(Err: std::move(E));
1904 } else
1905 error(E: std::move(E), FileName: Obj.getFileName());
1906 }
1907 if (!SymbolVersions.empty() && !SymbolVersions[I].Name.empty())
1908 S.Name +=
1909 (SymbolVersions[I].IsVerDef ? "@@" : "@") + SymbolVersions[I].Name;
1910
1911 S.Sym = Sym;
1912 if (S.initializeFlags(Obj))
1913 SymbolList.push_back(x: S);
1914 }
1915 }
1916
1917 // If this is a Mach-O file where the nlist symbol table is out of sync
1918 // with the dyld export trie then look through exports and fake up symbols
1919 // for the ones that are missing (also done with the -add-dyldinfo flag).
1920 // This is needed if strip(1) -T is run on a binary containing swift
1921 // language symbols for example. The option -only-dyldinfo will fake up
1922 // all symbols from the dyld export trie as well as the bind info.
1923 if (MachO && !NoDyldInfo)
1924 dumpSymbolsFromDLInfoMachO(MachO&: *MachO, SymbolList);
1925
1926 return true;
1927}
1928
1929static void printObjectLabel(bool PrintArchiveName, StringRef ArchiveName,
1930 StringRef ArchitectureName,
1931 StringRef ObjectFileName) {
1932 outs() << "\n";
1933 if (ArchiveName.empty() || !PrintArchiveName)
1934 outs() << ObjectFileName;
1935 else
1936 outs() << ArchiveName << "(" << ObjectFileName << ")";
1937 if (!ArchitectureName.empty())
1938 outs() << " (for architecture " << ArchitectureName << ")";
1939 outs() << ":\n";
1940}
1941
1942static Expected<bool> hasSymbols(SymbolicFile &Obj) {
1943 if (DynamicSyms) {
1944 Expected<SymbolicFile::basic_symbol_iterator_range> DynamicSymsOrErr =
1945 getDynamicSyms(Obj);
1946 if (!DynamicSymsOrErr)
1947 return DynamicSymsOrErr.takeError();
1948 return !DynamicSymsOrErr->empty();
1949 }
1950 return !Obj.symbols().empty();
1951}
1952
1953static void printSymbolNamesFromObject(
1954 SymbolicFile &Obj, std::vector<NMSymbol> &SymbolList,
1955 bool PrintSymbolObject, bool PrintObjectLabel, StringRef ArchiveName = {},
1956 StringRef ArchitectureName = {}, StringRef ObjectName = {},
1957 bool PrintArchiveName = true) {
1958
1959 if (PrintObjectLabel && !ExportSymbols)
1960 printObjectLabel(PrintArchiveName, ArchiveName, ArchitectureName,
1961 ObjectFileName: ObjectName.empty() ? Obj.getFileName() : ObjectName);
1962
1963 if (!getSymbolNamesFromObject(Obj, SymbolList) || ExportSymbols)
1964 return;
1965
1966 // If there is an error in hasSymbols(), the error should be encountered in
1967 // function getSymbolNamesFromObject first.
1968 if (!cantFail(ValOrErr: hasSymbols(Obj)) && SymbolList.empty() && !Quiet) {
1969 writeFileName(S&: errs(), ArchiveName, ArchitectureName);
1970 errs() << "no symbols\n";
1971 }
1972
1973 sortSymbolList(SymbolList);
1974 printSymbolList(Obj, SymbolList, printName: PrintSymbolObject, ArchiveName,
1975 ArchitectureName);
1976}
1977
1978static void dumpSymbolsNameFromMachOFilesetEntry(
1979 MachOObjectFile *Obj, std::vector<NMSymbol> &SymbolList,
1980 bool PrintSymbolObject, bool PrintObjectLabel) {
1981 auto Buf = Obj->getMemoryBufferRef();
1982 const auto *End = Obj->load_commands().end();
1983 for (const auto *It = Obj->load_commands().begin(); It != End; ++It) {
1984 const auto &Command = *It;
1985 if (Command.C.cmd != MachO::LC_FILESET_ENTRY)
1986 continue;
1987
1988 MachO::fileset_entry_command Entry =
1989 Obj->getFilesetEntryLoadCommand(L: Command);
1990 auto MaybeMachO =
1991 MachOObjectFile::createMachOObjectFile(Object: Buf, UniversalCputype: 0, UniversalIndex: 0, MachOFilesetEntryOffset: Entry.fileoff);
1992
1993 if (Error Err = MaybeMachO.takeError())
1994 report_fatal_error(Err: std::move(Err));
1995
1996 const char *EntryName = Command.Ptr + Entry.entry_id.offset;
1997 if (EntryName)
1998 outs() << "Symbols for " << EntryName << ": \n";
1999
2000 std::unique_ptr<MachOObjectFile> EntryMachO = std::move(MaybeMachO.get());
2001 printSymbolNamesFromObject(Obj&: *EntryMachO, SymbolList, PrintSymbolObject,
2002 PrintObjectLabel);
2003
2004 if (std::next(x: It) != End)
2005 outs() << "\n";
2006 }
2007}
2008
2009static void dumpSymbolNamesFromObject(
2010 SymbolicFile &Obj, std::vector<NMSymbol> &SymbolList,
2011 bool PrintSymbolObject, bool PrintObjectLabel, StringRef ArchiveName = {},
2012 StringRef ArchitectureName = {}, StringRef ObjectName = {},
2013 bool PrintArchiveName = true) {
2014 if (!shouldDump(Obj))
2015 return;
2016
2017 if (ExportSymbols && Obj.isXCOFF()) {
2018 XCOFFObjectFile *XCOFFObj = cast<XCOFFObjectFile>(Val: &Obj);
2019 getXCOFFExports(XCOFFObj, SymbolList, ArchiveName);
2020 return;
2021 }
2022
2023 CurrentFilename = Obj.getFileName();
2024
2025 // Are we handling a MachO of type MH_FILESET?
2026 if (Obj.isMachO() && Obj.is64Bit() &&
2027 cast<MachOObjectFile>(Val: &Obj)->getHeader64().filetype ==
2028 MachO::MH_FILESET) {
2029 dumpSymbolsNameFromMachOFilesetEntry(Obj: cast<MachOObjectFile>(Val: &Obj),
2030 SymbolList, PrintSymbolObject,
2031 PrintObjectLabel);
2032 return;
2033 }
2034
2035 printSymbolNamesFromObject(Obj, SymbolList, PrintSymbolObject,
2036 PrintObjectLabel, ArchiveName, ArchitectureName,
2037 ObjectName, PrintArchiveName);
2038}
2039
2040// checkMachOAndArchFlags() checks to see if the SymbolicFile is a Mach-O file
2041// and if it is and there is a list of architecture flags is specified then
2042// check to make sure this Mach-O file is one of those architectures or all
2043// architectures was specificed. If not then an error is generated and this
2044// routine returns false. Else it returns true.
2045static bool checkMachOAndArchFlags(SymbolicFile *O, StringRef Filename) {
2046 auto *MachO = dyn_cast<MachOObjectFile>(Val: O);
2047
2048 if (!MachO || ArchAll || ArchFlags.empty())
2049 return true;
2050
2051 MachO::mach_header H;
2052 MachO::mach_header_64 H_64;
2053 Triple T;
2054 const char *McpuDefault, *ArchFlag;
2055 if (MachO->is64Bit()) {
2056 H_64 = MachO->MachOObjectFile::getHeader64();
2057 T = MachOObjectFile::getArchTriple(CPUType: H_64.cputype, CPUSubType: H_64.cpusubtype,
2058 McpuDefault: &McpuDefault, ArchFlag: &ArchFlag);
2059 } else {
2060 H = MachO->MachOObjectFile::getHeader();
2061 T = MachOObjectFile::getArchTriple(CPUType: H.cputype, CPUSubType: H.cpusubtype,
2062 McpuDefault: &McpuDefault, ArchFlag: &ArchFlag);
2063 }
2064 const std::string ArchFlagName(ArchFlag);
2065 if (!llvm::is_contained(Range&: ArchFlags, Element: ArchFlagName)) {
2066 error(Message: "No architecture specified", Path: Filename);
2067 return false;
2068 }
2069 return true;
2070}
2071
2072/// Decode the low 3 bits of a z/OS archive symbol attribute word into a
2073/// human-readable description written to OS, e.g. "[64-bit + XPLink]".
2074/// Any bits above the known 3-bit mask produce a trailing "?" flag.
2075static void decodeZOSAttributes(raw_ostream &OS, uint32_t Attrs) {
2076 bool Unknown = (Attrs & ~Archive::Symbol::ZOSKnownAttrMask) != 0;
2077 bool Is64Bit = (Attrs & Archive::Symbol::ZOSAttr64Bit) != 0;
2078 bool IsXPLink = (Attrs & Archive::Symbol::ZOSAttrXPLink) != 0;
2079 bool IsWSA = (Attrs & Archive::Symbol::ZOSAttrWSA) != 0;
2080
2081 OS << "[";
2082 bool NeedPlus = false;
2083 auto Append = [&](const char *S) {
2084 if (NeedPlus)
2085 OS << " + ";
2086 OS << S;
2087 NeedPlus = true;
2088 };
2089 if (Is64Bit)
2090 Append("64-bit");
2091 if (IsXPLink)
2092 Append("XPLink");
2093 if (IsWSA)
2094 Append("WSA");
2095 if (Unknown)
2096 Append("?");
2097 if (!NeedPlus)
2098 Append("none");
2099 OS << "]";
2100}
2101
2102static void printArchiveMap(iterator_range<Archive::symbol_iterator> &Map,
2103 StringRef Filename, Archive::Kind Kind) {
2104 for (auto I : Map) {
2105 Expected<Archive::Child> C = I.getMember();
2106 if (!C) {
2107 error(E: C.takeError(), FileName: Filename);
2108 break;
2109 }
2110 Expected<StringRef> FileNameOrErr = C->getName();
2111 if (!FileNameOrErr) {
2112 error(E: FileNameOrErr.takeError(), FileName: Filename);
2113 break;
2114 }
2115 StringRef SymName = I.getName();
2116 outs() << SymName << " in " << FileNameOrErr.get();
2117 if (Kind == Archive::K_ZOS) {
2118 uint32_t Attrs = I.getZOSAttributes();
2119 outs() << format(Fmt: " (flags: 0x%08x ", Vals: Attrs);
2120 decodeZOSAttributes(OS&: outs(), Attrs);
2121 outs() << ")";
2122 }
2123 outs() << "\n";
2124 }
2125
2126 outs() << "\n";
2127}
2128
2129static void dumpArchiveMap(Archive *A, StringRef Filename) {
2130 auto Map = A->symbols();
2131 if (!Map.empty()) {
2132 outs() << "Archive map\n";
2133 printArchiveMap(Map, Filename, Kind: A->kind());
2134 }
2135
2136 auto ECMap = A->ec_symbols();
2137 if (!ECMap) {
2138 warn(Err: ECMap.takeError(), FileName: Filename);
2139 } else if (!ECMap->empty()) {
2140 outs() << "Archive EC map\n";
2141 printArchiveMap(Map&: *ECMap, Filename, Kind: A->kind());
2142 }
2143}
2144
2145static void dumpArchive(Archive *A, std::vector<NMSymbol> &SymbolList,
2146 StringRef Filename, LLVMContext *ContextPtr) {
2147 if (ArchiveMap)
2148 dumpArchiveMap(A, Filename);
2149
2150 Error Err = Error::success();
2151 for (auto &C : A->children(Err)) {
2152 Expected<std::unique_ptr<Binary>> ChildOrErr = C.getAsBinary(Context: ContextPtr);
2153 if (!ChildOrErr) {
2154 if (auto E = isNotObjectErrorInvalidFileType(Err: ChildOrErr.takeError()))
2155 error(E: std::move(E), FileName: Filename, C);
2156 continue;
2157 }
2158 if (SymbolicFile *O = dyn_cast<SymbolicFile>(Val: &*ChildOrErr.get())) {
2159 if (!MachOPrintSizeWarning && PrintSize && isa<MachOObjectFile>(Val: O)) {
2160 WithColor::warning(OS&: errs(), Prefix: ToolName)
2161 << "sizes with -print-size for Mach-O files are always zero.\n";
2162 MachOPrintSizeWarning = true;
2163 }
2164 if (!checkMachOAndArchFlags(O, Filename))
2165 return;
2166 dumpSymbolNamesFromObject(Obj&: *O, SymbolList, /*PrintSymbolObject=*/false,
2167 PrintObjectLabel: !PrintFileName, ArchiveName: Filename,
2168 /*ArchitectureName=*/{}, ObjectName: O->getFileName(),
2169 /*PrintArchiveName=*/false);
2170 }
2171 }
2172 if (Err)
2173 error(E: std::move(Err), FileName: A->getFileName());
2174}
2175
2176static void dumpMachOUniversalBinaryMatchArchFlags(
2177 MachOUniversalBinary *UB, std::vector<NMSymbol> &SymbolList,
2178 StringRef Filename, LLVMContext *ContextPtr) {
2179 // Look for a slice in the universal binary that matches each ArchFlag.
2180 bool ArchFound;
2181 for (unsigned i = 0; i < ArchFlags.size(); ++i) {
2182 ArchFound = false;
2183 for (MachOUniversalBinary::object_iterator I = UB->begin_objects(),
2184 E = UB->end_objects();
2185 I != E; ++I) {
2186 if (ArchFlags[i] == I->getArchFlagName()) {
2187 ArchFound = true;
2188 Expected<std::unique_ptr<ObjectFile>> ObjOrErr = I->getAsObjectFile();
2189 std::string ArchiveName;
2190 std::string ArchitectureName;
2191 ArchiveName.clear();
2192 ArchitectureName.clear();
2193 if (ObjOrErr) {
2194 ObjectFile &Obj = *ObjOrErr.get();
2195 if (ArchFlags.size() > 1)
2196 ArchitectureName = I->getArchFlagName();
2197 dumpSymbolNamesFromObject(Obj, SymbolList,
2198 /*PrintSymbolObject=*/false,
2199 PrintObjectLabel: (ArchFlags.size() > 1) && !PrintFileName,
2200 ArchiveName, ArchitectureName);
2201 } else if (auto E =
2202 isNotObjectErrorInvalidFileType(Err: ObjOrErr.takeError())) {
2203 error(E: std::move(E), FileName: Filename,
2204 ArchitectureName: ArchFlags.size() > 1 ? StringRef(I->getArchFlagName())
2205 : StringRef());
2206 continue;
2207 } else if (Expected<std::unique_ptr<Archive>> AOrErr =
2208 I->getAsArchive()) {
2209 std::unique_ptr<Archive> &A = *AOrErr;
2210 Error Err = Error::success();
2211 for (auto &C : A->children(Err)) {
2212 Expected<std::unique_ptr<Binary>> ChildOrErr =
2213 C.getAsBinary(Context: ContextPtr);
2214 if (!ChildOrErr) {
2215 if (auto E =
2216 isNotObjectErrorInvalidFileType(Err: ChildOrErr.takeError())) {
2217 error(E: std::move(E), FileName: Filename, C,
2218 ArchitectureName: ArchFlags.size() > 1 ? StringRef(I->getArchFlagName())
2219 : StringRef());
2220 }
2221 continue;
2222 }
2223 if (SymbolicFile *O = dyn_cast<SymbolicFile>(Val: &*ChildOrErr.get())) {
2224 ArchiveName = std::string(A->getFileName());
2225 if (ArchFlags.size() > 1)
2226 ArchitectureName = I->getArchFlagName();
2227 dumpSymbolNamesFromObject(
2228 Obj&: *O, SymbolList, /*PrintSymbolObject=*/false, PrintObjectLabel: !PrintFileName,
2229 ArchiveName, ArchitectureName);
2230 }
2231 }
2232 if (Err)
2233 error(E: std::move(Err), FileName: A->getFileName());
2234 } else {
2235 consumeError(Err: AOrErr.takeError());
2236 error(Message: Filename + " for architecture " +
2237 StringRef(I->getArchFlagName()) +
2238 " is not a Mach-O file or an archive file",
2239 Path: "Mach-O universal file");
2240 }
2241 }
2242 }
2243 if (!ArchFound) {
2244 error(Message: ArchFlags[i],
2245 Path: "file: " + Filename + " does not contain architecture");
2246 return;
2247 }
2248 }
2249}
2250
2251// Returns true If the binary contains a slice that matches the host
2252// architecture, or false otherwise.
2253static bool dumpMachOUniversalBinaryMatchHost(MachOUniversalBinary *UB,
2254 std::vector<NMSymbol> &SymbolList,
2255 StringRef Filename,
2256 LLVMContext *ContextPtr) {
2257 Triple HostTriple = MachOObjectFile::getHostArch();
2258 StringRef HostArchName = HostTriple.getArchName();
2259 for (MachOUniversalBinary::object_iterator I = UB->begin_objects(),
2260 E = UB->end_objects();
2261 I != E; ++I) {
2262 if (HostArchName == I->getArchFlagName()) {
2263 Expected<std::unique_ptr<ObjectFile>> ObjOrErr = I->getAsObjectFile();
2264 std::string ArchiveName;
2265 if (ObjOrErr) {
2266 ObjectFile &Obj = *ObjOrErr.get();
2267 dumpSymbolNamesFromObject(Obj, SymbolList, /*PrintSymbolObject=*/false,
2268 /*PrintObjectLabel=*/false);
2269 } else if (auto E = isNotObjectErrorInvalidFileType(Err: ObjOrErr.takeError()))
2270 error(E: std::move(E), FileName: Filename);
2271 else if (Expected<std::unique_ptr<Archive>> AOrErr = I->getAsArchive()) {
2272 std::unique_ptr<Archive> &A = *AOrErr;
2273 Error Err = Error::success();
2274 for (auto &C : A->children(Err)) {
2275 Expected<std::unique_ptr<Binary>> ChildOrErr =
2276 C.getAsBinary(Context: ContextPtr);
2277 if (!ChildOrErr) {
2278 if (auto E =
2279 isNotObjectErrorInvalidFileType(Err: ChildOrErr.takeError()))
2280 error(E: std::move(E), FileName: Filename, C);
2281 continue;
2282 }
2283 if (SymbolicFile *O = dyn_cast<SymbolicFile>(Val: &*ChildOrErr.get())) {
2284 ArchiveName = std::string(A->getFileName());
2285 dumpSymbolNamesFromObject(Obj&: *O, SymbolList,
2286 /*PrintSymbolObject=*/false,
2287 PrintObjectLabel: !PrintFileName, ArchiveName);
2288 }
2289 }
2290 if (Err)
2291 error(E: std::move(Err), FileName: A->getFileName());
2292 } else {
2293 consumeError(Err: AOrErr.takeError());
2294 error(Message: Filename + " for architecture " +
2295 StringRef(I->getArchFlagName()) +
2296 " is not a Mach-O file or an archive file",
2297 Path: "Mach-O universal file");
2298 }
2299 return true;
2300 }
2301 }
2302 return false;
2303}
2304
2305static void dumpMachOUniversalBinaryArchAll(MachOUniversalBinary *UB,
2306 std::vector<NMSymbol> &SymbolList,
2307 StringRef Filename,
2308 LLVMContext *ContextPtr) {
2309 bool moreThanOneArch = UB->getNumberOfObjects() > 1;
2310 for (const MachOUniversalBinary::ObjectForArch &O : UB->objects()) {
2311 Expected<std::unique_ptr<ObjectFile>> ObjOrErr = O.getAsObjectFile();
2312 std::string ArchiveName;
2313 std::string ArchitectureName;
2314 ArchiveName.clear();
2315 ArchitectureName.clear();
2316 if (ObjOrErr) {
2317 ObjectFile &Obj = *ObjOrErr.get();
2318 if (isa<MachOObjectFile>(Val: Obj) && moreThanOneArch)
2319 ArchitectureName = O.getArchFlagName();
2320 dumpSymbolNamesFromObject(Obj, SymbolList, /*PrintSymbolObject=*/false,
2321 PrintObjectLabel: !PrintFileName, ArchiveName, ArchitectureName);
2322 } else if (auto E = isNotObjectErrorInvalidFileType(Err: ObjOrErr.takeError())) {
2323 error(E: std::move(E), FileName: Filename,
2324 ArchitectureName: moreThanOneArch ? StringRef(O.getArchFlagName()) : StringRef());
2325 continue;
2326 } else if (Expected<std::unique_ptr<Archive>> AOrErr = O.getAsArchive()) {
2327 std::unique_ptr<Archive> &A = *AOrErr;
2328 Error Err = Error::success();
2329 for (auto &C : A->children(Err)) {
2330 Expected<std::unique_ptr<Binary>> ChildOrErr =
2331 C.getAsBinary(Context: ContextPtr);
2332 if (!ChildOrErr) {
2333 if (auto E = isNotObjectErrorInvalidFileType(Err: ChildOrErr.takeError()))
2334 error(E: std::move(E), FileName: Filename, C,
2335 ArchitectureName: moreThanOneArch ? StringRef(ArchitectureName) : StringRef());
2336 continue;
2337 }
2338 if (SymbolicFile *F = dyn_cast<SymbolicFile>(Val: &*ChildOrErr.get())) {
2339 ArchiveName = std::string(A->getFileName());
2340 if (isa<MachOObjectFile>(Val: F) && moreThanOneArch)
2341 ArchitectureName = O.getArchFlagName();
2342 dumpSymbolNamesFromObject(Obj&: *F, SymbolList, /*PrintSymbolObject=*/false,
2343 PrintObjectLabel: !PrintFileName, ArchiveName,
2344 ArchitectureName);
2345 }
2346 }
2347 if (Err)
2348 error(E: std::move(Err), FileName: A->getFileName());
2349 } else {
2350 consumeError(Err: AOrErr.takeError());
2351 error(Message: Filename + " for architecture " + StringRef(O.getArchFlagName()) +
2352 " is not a Mach-O file or an archive file",
2353 Path: "Mach-O universal file");
2354 }
2355 }
2356}
2357
2358static void dumpMachOUniversalBinary(MachOUniversalBinary *UB,
2359 std::vector<NMSymbol> &SymbolList,
2360 StringRef Filename,
2361 LLVMContext *ContextPtr) {
2362 // If we have a list of architecture flags specified dump only those.
2363 if (!ArchAll && !ArchFlags.empty()) {
2364 dumpMachOUniversalBinaryMatchArchFlags(UB, SymbolList, Filename,
2365 ContextPtr);
2366 return;
2367 }
2368
2369 // No architecture flags were specified so if this contains a slice that
2370 // matches the host architecture dump only that.
2371 if (!ArchAll &&
2372 dumpMachOUniversalBinaryMatchHost(UB, SymbolList, Filename, ContextPtr))
2373 return;
2374
2375 // Either all architectures have been specified or none have been specified
2376 // and this does not contain the host architecture so dump all the slices.
2377 dumpMachOUniversalBinaryArchAll(UB, SymbolList, Filename, ContextPtr);
2378}
2379
2380static void dumpTapiUniversal(TapiUniversal *TU,
2381 std::vector<NMSymbol> &SymbolList,
2382 StringRef Filename) {
2383 for (const TapiUniversal::ObjectForArch &I : TU->objects()) {
2384 StringRef ArchName = I.getArchFlagName();
2385 const bool ShowArch =
2386 ArchFlags.empty() || llvm::is_contained(Range&: ArchFlags, Element: ArchName);
2387 if (!ShowArch)
2388 continue;
2389 if (!AddInlinedInfo && !I.isTopLevelLib())
2390 continue;
2391 if (auto ObjOrErr = I.getAsObjectFile())
2392 dumpSymbolNamesFromObject(
2393 Obj&: *ObjOrErr.get(), SymbolList, /*PrintSymbolObject=*/false,
2394 /*PrintObjectLabel=*/true,
2395 /*ArchiveName=*/{}, ArchitectureName: ArchName, ObjectName: I.getInstallName());
2396 else if (Error E = isNotObjectErrorInvalidFileType(Err: ObjOrErr.takeError())) {
2397 error(E: std::move(E), FileName: Filename, ArchitectureName: ArchName);
2398 }
2399 }
2400}
2401
2402static void dumpSymbolicFile(SymbolicFile *O, std::vector<NMSymbol> &SymbolList,
2403 StringRef Filename) {
2404 if (!MachOPrintSizeWarning && PrintSize && isa<MachOObjectFile>(Val: O)) {
2405 WithColor::warning(OS&: errs(), Prefix: ToolName)
2406 << "sizes with --print-size for Mach-O files are always zero.\n";
2407 MachOPrintSizeWarning = true;
2408 }
2409 if (!checkMachOAndArchFlags(O, Filename))
2410 return;
2411 dumpSymbolNamesFromObject(Obj&: *O, SymbolList, /*PrintSymbolObject=*/true,
2412 /*PrintObjectLabel=*/false);
2413}
2414
2415static std::vector<NMSymbol> dumpSymbolNamesFromFile(StringRef Filename) {
2416 std::vector<NMSymbol> SymbolList;
2417 ErrorOr<std::unique_ptr<MemoryBuffer>> BufferOrErr =
2418 MemoryBuffer::getFileOrSTDIN(Filename);
2419 if (error(EC: BufferOrErr.getError(), Path: Filename))
2420 return SymbolList;
2421
2422 // Ignore AIX linker import files (these files start with "#!"), when
2423 // exporting symbols.
2424 const char *BuffStart = (*BufferOrErr)->getBufferStart();
2425 size_t BufferSize = (*BufferOrErr)->getBufferSize();
2426 if (ExportSymbols && BufferSize >= 2 && BuffStart[0] == '#' &&
2427 BuffStart[1] == '!')
2428 return SymbolList;
2429
2430 LLVMContext Context;
2431 LLVMContext *ContextPtr = NoLLVMBitcode ? nullptr : &Context;
2432 Expected<std::unique_ptr<Binary>> BinaryOrErr =
2433 createBinary(Source: BufferOrErr.get()->getMemBufferRef(), Context: ContextPtr);
2434 if (!BinaryOrErr) {
2435 error(E: BinaryOrErr.takeError(), FileName: Filename);
2436 return SymbolList;
2437 }
2438 Binary &Bin = *BinaryOrErr.get();
2439 if (Archive *A = dyn_cast<Archive>(Val: &Bin))
2440 dumpArchive(A, SymbolList, Filename, ContextPtr);
2441 else if (MachOUniversalBinary *UB = dyn_cast<MachOUniversalBinary>(Val: &Bin))
2442 dumpMachOUniversalBinary(UB, SymbolList, Filename, ContextPtr);
2443 else if (TapiUniversal *TU = dyn_cast<TapiUniversal>(Val: &Bin))
2444 dumpTapiUniversal(TU, SymbolList, Filename);
2445 else if (SymbolicFile *O = dyn_cast<SymbolicFile>(Val: &Bin))
2446 dumpSymbolicFile(O, SymbolList, Filename);
2447 return SymbolList;
2448}
2449
2450static void
2451exportSymbolNamesFromFiles(const std::vector<std::string> &InputFilenames) {
2452 std::vector<NMSymbol> SymbolList;
2453 for (const auto &FileName : InputFilenames) {
2454 std::vector<NMSymbol> FileSymList = dumpSymbolNamesFromFile(Filename: FileName);
2455 llvm::append_range(C&: SymbolList, R&: FileSymList);
2456 }
2457
2458 // Delete symbols which should not be printed from SymolList.
2459 llvm::erase_if(C&: SymbolList,
2460 P: [](const NMSymbol &s) { return !s.shouldPrint(); });
2461 sortSymbolList(SymbolList);
2462 SymbolList.erase(first: llvm::unique(R&: SymbolList), last: SymbolList.end());
2463 printExportSymbolList(SymbolList);
2464}
2465
2466int llvm_nm_main(int argc, char **argv, const llvm::ToolContext &) {
2467 BumpPtrAllocator A;
2468 StringSaver Saver(A);
2469 NmOptTable Tbl;
2470 ToolName = argv[0];
2471 opt::InputArgList Args =
2472 Tbl.parseArgs(Argc: argc, Argv: argv, Unknown: OPT_UNKNOWN, Saver, ErrorFn: [&](StringRef Msg) {
2473 error(Message: Msg);
2474 exit(status: 1);
2475 });
2476 if (Args.hasArg(Ids: OPT_help)) {
2477 Tbl.printHelp(
2478 OS&: outs(),
2479 Usage: (Twine(ToolName) + " [options] <input object files>").str().c_str(),
2480 Title: "LLVM symbol table dumper");
2481 // TODO Replace this with OptTable API once it adds extrahelp support.
2482 outs() << "\nPass @FILE as argument to read options from FILE.\n";
2483 return 0;
2484 }
2485 if (Args.hasArg(Ids: OPT_version)) {
2486 // This needs to contain the word "GNU", libtool looks for that string.
2487 outs() << "llvm-nm, compatible with GNU nm" << '\n';
2488 cl::PrintVersionMessage();
2489 return 0;
2490 }
2491
2492 DebugSyms = Args.hasArg(Ids: OPT_debug_syms);
2493 DefinedOnly = Args.hasArg(Ids: OPT_defined_only);
2494 Demangle = Args.hasFlag(Pos: OPT_demangle, Neg: OPT_no_demangle, Default: false);
2495 DynamicSyms = Args.hasArg(Ids: OPT_dynamic);
2496 ExternalOnly = Args.hasArg(Ids: OPT_extern_only);
2497 StringRef V = Args.getLastArgValue(Id: OPT_format_EQ, Default: "bsd");
2498 if (V == "bsd")
2499 OutputFormat = bsd;
2500 else if (V == "posix")
2501 OutputFormat = posix;
2502 else if (V == "sysv")
2503 OutputFormat = sysv;
2504 else if (V == "darwin")
2505 OutputFormat = darwin;
2506 else if (V == "just-symbols")
2507 OutputFormat = just_symbols;
2508 else
2509 error(Message: "--format value should be one of: bsd, posix, sysv, darwin, "
2510 "just-symbols");
2511 LineNumbers = Args.hasArg(Ids: OPT_line_numbers);
2512 NoLLVMBitcode = Args.hasArg(Ids: OPT_no_llvm_bc);
2513 NoSort = Args.hasArg(Ids: OPT_no_sort);
2514 NoWeakSymbols = Args.hasArg(Ids: OPT_no_weak);
2515 NumericSort = Args.hasArg(Ids: OPT_numeric_sort);
2516 ArchiveMap = Args.hasArg(Ids: OPT_print_armap);
2517 PrintFileName = Args.hasArg(Ids: OPT_print_file_name);
2518 PrintSize = Args.hasArg(Ids: OPT_print_size);
2519 ReverseSort = Args.hasArg(Ids: OPT_reverse_sort);
2520 ExportSymbols = Args.hasArg(Ids: OPT_export_symbols);
2521 if (ExportSymbols) {
2522 ExternalOnly = true;
2523 DefinedOnly = true;
2524 }
2525
2526 Quiet = Args.hasArg(Ids: OPT_quiet);
2527 V = Args.getLastArgValue(Id: OPT_radix_EQ, Default: "x");
2528 if (V == "o")
2529 AddressRadix = Radix::o;
2530 else if (V == "d")
2531 AddressRadix = Radix::d;
2532 else if (V == "x")
2533 AddressRadix = Radix::x;
2534 else
2535 error(Message: "--radix value should be one of: 'o' (octal), 'd' (decimal), 'x' "
2536 "(hexadecimal)");
2537 SizeSort = Args.hasArg(Ids: OPT_size_sort);
2538 SpecialSyms = Args.hasArg(Ids: OPT_special_syms);
2539 UndefinedOnly = Args.hasArg(Ids: OPT_undefined_only);
2540 WithoutAliases = Args.hasArg(Ids: OPT_without_aliases);
2541
2542 // Get BitMode from enviornment variable "OBJECT_MODE" for AIX OS, if
2543 // specified.
2544 Triple HostTriple(sys::getProcessTriple());
2545 if (HostTriple.isOSAIX()) {
2546 BitMode = StringSwitch<BitModeTy>(getenv(name: "OBJECT_MODE"))
2547 .Case(S: "32", Value: BitModeTy::Bit32)
2548 .Case(S: "64", Value: BitModeTy::Bit64)
2549 .Case(S: "32_64", Value: BitModeTy::Bit32_64)
2550 .Case(S: "any", Value: BitModeTy::Any)
2551 .Default(Value: BitModeTy::Bit32);
2552 } else
2553 BitMode = BitModeTy::Any;
2554
2555 if (Arg *A = Args.getLastArg(Ids: OPT_X)) {
2556 StringRef Mode = A->getValue();
2557 if (Mode == "32")
2558 BitMode = BitModeTy::Bit32;
2559 else if (Mode == "64")
2560 BitMode = BitModeTy::Bit64;
2561 else if (Mode == "32_64")
2562 BitMode = BitModeTy::Bit32_64;
2563 else if (Mode == "any")
2564 BitMode = BitModeTy::Any;
2565 else
2566 error(Message: "-X value should be one of: 32, 64, 32_64, (default) any");
2567 }
2568
2569 // Mach-O specific options.
2570 FormatMachOasHex = Args.hasArg(Ids: OPT_x);
2571 AddDyldInfo = Args.hasArg(Ids: OPT_add_dyldinfo);
2572 AddInlinedInfo = Args.hasArg(Ids: OPT_add_inlinedinfo);
2573 DyldInfoOnly = Args.hasArg(Ids: OPT_dyldinfo_only);
2574 NoDyldInfo = Args.hasArg(Ids: OPT_no_dyldinfo);
2575
2576 // XCOFF specific options.
2577 NoRsrc = Args.hasArg(Ids: OPT_no_rsrc);
2578
2579 // llvm-nm only reads binary files.
2580 if (error(EC: sys::ChangeStdinToBinary()))
2581 return 1;
2582
2583 // These calls are needed so that we can read bitcode correctly.
2584 llvm::InitializeAllTargetInfos();
2585 llvm::InitializeAllTargetMCs();
2586 llvm::InitializeAllAsmParsers();
2587
2588 // The relative order of these is important. If you pass --size-sort it should
2589 // only print out the size. However, if you pass -S --size-sort, it should
2590 // print out both the size and address.
2591 if (SizeSort && !PrintSize)
2592 PrintAddress = false;
2593 if (OutputFormat == sysv || SizeSort)
2594 PrintSize = true;
2595
2596 for (const auto *A : Args.filtered(Ids: OPT_arch_EQ)) {
2597 SmallVector<StringRef, 2> Values;
2598 llvm::SplitString(Source: A->getValue(), OutFragments&: Values, Delimiters: ",");
2599 for (StringRef V : Values) {
2600 if (V == "all")
2601 ArchAll = true;
2602 else if (MachOObjectFile::isValidArch(ArchFlag: V))
2603 ArchFlags.push_back(x: V);
2604 else
2605 error(Message: "Unknown architecture named '" + V + "'",
2606 Path: "for the --arch option");
2607 }
2608 }
2609
2610 // Mach-O takes -s to accept two arguments. We emulate this by iterating over
2611 // both OPT_s and OPT_INPUT.
2612 std::vector<std::string> InputFilenames;
2613 int SegSectArgs = 0;
2614 for (opt::Arg *A : Args.filtered(Ids: OPT_s, Ids: OPT_INPUT)) {
2615 if (SegSectArgs > 0) {
2616 --SegSectArgs;
2617 SegSect.push_back(x: A->getValue());
2618 } else if (A->getOption().matches(ID: OPT_s)) {
2619 SegSectArgs = 2;
2620 } else {
2621 InputFilenames.push_back(x: A->getValue());
2622 }
2623 }
2624 if (!SegSect.empty() && SegSect.size() != 2)
2625 error(Message: "bad number of arguments (must be two arguments)",
2626 Path: "for the -s option");
2627
2628 if (InputFilenames.empty())
2629 InputFilenames.push_back(x: "a.out");
2630 if (InputFilenames.size() > 1)
2631 MultipleFiles = true;
2632
2633 if (NoDyldInfo && (AddDyldInfo || DyldInfoOnly))
2634 error(Message: "--no-dyldinfo can't be used with --add-dyldinfo or --dyldinfo-only");
2635
2636 if (ExportSymbols)
2637 exportSymbolNamesFromFiles(InputFilenames);
2638 else
2639 llvm::for_each(Range&: InputFilenames, F: dumpSymbolNamesFromFile);
2640
2641 if (HadError)
2642 return 1;
2643 return 0;
2644}
2645