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