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/IRObjectFile.h"
32#include "llvm/Object/MachO.h"
33#include "llvm/Object/MachOUniversal.h"
34#include "llvm/Object/ObjectFile.h"
35#include "llvm/Object/SymbolicFile.h"
36#include "llvm/Object/TapiFile.h"
37#include "llvm/Object/TapiUniversal.h"
38#include "llvm/Object/Wasm.h"
39#include "llvm/Object/XCOFFObjectFile.h"
40#include "llvm/Option/Arg.h"
41#include "llvm/Option/ArgList.h"
42#include "llvm/Option/Option.h"
43#include "llvm/Support/CommandLine.h"
44#include "llvm/Support/FileSystem.h"
45#include "llvm/Support/Format.h"
46#include "llvm/Support/LLVMDriver.h"
47#include "llvm/Support/MemoryBuffer.h"
48#include "llvm/Support/Program.h"
49#include "llvm/Support/Signals.h"
50#include "llvm/Support/TargetSelect.h"
51#include "llvm/Support/WithColor.h"
52#include "llvm/Support/raw_ostream.h"
53#include "llvm/TargetParser/Host.h"
54#include "llvm/TargetParser/Triple.h"
55#include <vector>
56
57using namespace llvm;
58using namespace object;
59
60namespace {
61using namespace llvm::opt; // for HelpHidden in Opts.inc
62enum ID {
63 OPT_INVALID = 0, // This is not an option ID.
64#define OPTION(...) LLVM_MAKE_OPT_ID(__VA_ARGS__),
65#include "Opts.inc"
66#undef OPTION
67};
68
69#define OPTTABLE_STR_TABLE_CODE
70#include "Opts.inc"
71#undef OPTTABLE_STR_TABLE_CODE
72
73#define OPTTABLE_PREFIXES_TABLE_CODE
74#include "Opts.inc"
75#undef OPTTABLE_PREFIXES_TABLE_CODE
76
77static constexpr opt::OptTable::Info InfoTable[] = {
78#define OPTION(...) LLVM_CONSTRUCT_OPT_INFO(__VA_ARGS__),
79#include "Opts.inc"
80#undef OPTION
81};
82
83class NmOptTable : public opt::GenericOptTable {
84public:
85 NmOptTable()
86 : opt::GenericOptTable(OptionStrTable, OptionPrefixesTable, InfoTable) {
87 setGroupedShortOptions(true);
88 }
89};
90
91enum OutputFormatTy { bsd, sysv, posix, darwin, just_symbols };
92enum class BitModeTy { Bit32, Bit64, Bit32_64, Any };
93} // namespace
94
95static bool ArchiveMap;
96static BitModeTy BitMode;
97static bool DebugSyms;
98static bool DefinedOnly;
99static bool Demangle;
100static bool DynamicSyms;
101static bool ExportSymbols;
102static bool ExternalOnly;
103static bool LineNumbers;
104static OutputFormatTy OutputFormat;
105static bool NoLLVMBitcode;
106static bool NoSort;
107static bool NoWeakSymbols;
108static bool NumericSort;
109static bool PrintFileName;
110static bool PrintSize;
111static bool Quiet;
112static bool ReverseSort;
113static bool SpecialSyms;
114static bool SizeSort;
115static bool UndefinedOnly;
116static bool WithoutAliases;
117
118// XCOFF-specific options.
119static bool NoRsrc;
120
121namespace {
122enum Radix { d, o, x };
123} // namespace
124static Radix AddressRadix;
125
126// Mach-O specific options.
127static bool ArchAll = false;
128static std::vector<StringRef> ArchFlags;
129static bool AddDyldInfo;
130static bool AddInlinedInfo;
131static bool DyldInfoOnly;
132static bool FormatMachOasHex;
133static bool NoDyldInfo;
134static std::vector<StringRef> SegSect;
135static bool MachOPrintSizeWarning = false;
136
137// Miscellaneous states.
138static bool PrintAddress = true;
139static bool MultipleFiles = false;
140static bool HadError = false;
141
142static StringRef ToolName;
143
144static void warn(Error Err, Twine FileName, Twine Context = Twine(),
145 Twine Archive = Twine()) {
146 assert(Err);
147
148 // Flush the standard output so that the warning isn't interleaved with other
149 // output if stdout and stderr are writing to the same place.
150 outs().flush();
151
152 handleAllErrors(E: std::move(Err), Handlers: [&](const ErrorInfoBase &EI) {
153 WithColor::warning(OS&: errs(), Prefix: ToolName)
154 << (Archive.str().empty() ? FileName : Archive + "(" + FileName + ")")
155 << ": " << (Context.str().empty() ? "" : Context + ": ") << EI.message()
156 << "\n";
157 });
158}
159
160static void error(Twine Message, Twine Path = Twine()) {
161 HadError = true;
162 WithColor::error(OS&: errs(), Prefix: ToolName) << Path << ": " << Message << "\n";
163}
164
165static bool error(std::error_code EC, Twine Path = Twine()) {
166 if (EC) {
167 error(Message: EC.message(), Path);
168 return true;
169 }
170 return false;
171}
172
173// This version of error() prints the archive name and member name, for example:
174// "libx.a(foo.o)" after the ToolName before the error message. It sets
175// HadError but returns allowing the code to move on to other archive members.
176static void error(llvm::Error E, StringRef FileName, const Archive::Child &C,
177 StringRef ArchitectureName = StringRef()) {
178 HadError = true;
179 WithColor::error(OS&: errs(), Prefix: ToolName) << FileName;
180
181 Expected<StringRef> NameOrErr = C.getName();
182 // TODO: if we have a error getting the name then it would be nice to print
183 // the index of which archive member this is and or its offset in the
184 // archive instead of "???" as the name.
185 if (!NameOrErr) {
186 consumeError(Err: NameOrErr.takeError());
187 errs() << "(" << "???" << ")";
188 } else
189 errs() << "(" << NameOrErr.get() << ")";
190
191 if (!ArchitectureName.empty())
192 errs() << " (for architecture " << ArchitectureName << ")";
193
194 std::string Buf;
195 raw_string_ostream OS(Buf);
196 logAllUnhandledErrors(E: std::move(E), OS);
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 errs() << ": " << Buf << "\n";
216}
217
218namespace {
219struct NMSymbol {
220 uint64_t Address;
221 uint64_t Size;
222 char TypeChar;
223 std::string Name;
224 StringRef SectionName;
225 StringRef TypeName;
226 BasicSymbolRef Sym;
227 StringRef Visibility;
228
229 // The Sym field above points to the native symbol in the object file,
230 // for Mach-O when we are creating symbols from the dyld info the above
231 // pointer is null as there is no native symbol. In these cases the fields
232 // below are filled in to represent what would have been a Mach-O nlist
233 // native symbol.
234 uint32_t SymFlags;
235 SectionRef Section;
236 uint8_t NType;
237 uint8_t NSect;
238 uint16_t NDesc;
239 std::string IndirectName;
240
241 bool isDefined() const {
242 if (Sym.getRawDataRefImpl().p)
243 return !(SymFlags & SymbolRef::SF_Undefined);
244 return TypeChar != 'U';
245 }
246
247 bool initializeFlags(const SymbolicFile &Obj) {
248 Expected<uint32_t> SymFlagsOrErr = Sym.getFlags();
249 if (!SymFlagsOrErr) {
250 // TODO: Test this error.
251 error(E: SymFlagsOrErr.takeError(), FileName: Obj.getFileName());
252 return false;
253 }
254 SymFlags = *SymFlagsOrErr;
255 return true;
256 }
257
258 bool shouldPrint() const {
259 bool Undefined = SymFlags & SymbolRef::SF_Undefined;
260 bool Global = SymFlags & SymbolRef::SF_Global;
261 bool Weak = SymFlags & SymbolRef::SF_Weak;
262 bool FormatSpecific = SymFlags & SymbolRef::SF_FormatSpecific;
263 if ((!Undefined && UndefinedOnly) || (Undefined && DefinedOnly) ||
264 (!Global && ExternalOnly) || (Weak && NoWeakSymbols) ||
265 (FormatSpecific && !(SpecialSyms || DebugSyms)))
266 return false;
267 return true;
268 }
269};
270
271bool operator<(const NMSymbol &A, const NMSymbol &B) {
272 if (NumericSort)
273 return std::make_tuple(args: A.isDefined(), args: A.Address, args: A.Name, args: A.Size) <
274 std::make_tuple(args: B.isDefined(), args: B.Address, args: B.Name, args: B.Size);
275 if (SizeSort)
276 return std::make_tuple(args: A.Size, args: A.Name, args: A.Address) <
277 std::make_tuple(args: B.Size, args: B.Name, args: B.Address);
278 if (ExportSymbols)
279 return std::make_tuple(args: A.Name, args: A.Visibility) <
280 std::make_tuple(args: B.Name, args: B.Visibility);
281 return std::make_tuple(args: A.Name, args: A.Size, args: A.Address) <
282 std::make_tuple(args: B.Name, args: B.Size, args: B.Address);
283}
284
285bool operator>(const NMSymbol &A, const NMSymbol &B) { return B < A; }
286bool operator==(const NMSymbol &A, const NMSymbol &B) {
287 return !(A < B) && !(B < A);
288}
289} // anonymous namespace
290
291static StringRef CurrentFilename;
292
293static char getSymbolNMTypeChar(IRObjectFile &Obj, basic_symbol_iterator I);
294
295// darwinPrintSymbol() is used to print a symbol from a Mach-O file when the
296// the OutputFormat is darwin or we are printing Mach-O symbols in hex. For
297// the darwin format it produces the same output as darwin's nm(1) -m output
298// and when printing Mach-O symbols in hex it produces the same output as
299// darwin's nm(1) -x format.
300static void darwinPrintSymbol(SymbolicFile &Obj, const NMSymbol &S,
301 char *SymbolAddrStr, const char *printBlanks,
302 const char *printDashes,
303 const char *printFormat) {
304 MachO::mach_header H;
305 MachO::mach_header_64 H_64;
306 uint32_t Filetype = MachO::MH_OBJECT;
307 uint32_t Flags = 0;
308 uint8_t NType = 0;
309 uint8_t NSect = 0;
310 uint16_t NDesc = 0;
311 uint32_t NStrx = 0;
312 uint64_t NValue = 0;
313 MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(Val: &Obj);
314 if (Obj.isIR()) {
315 uint32_t SymFlags = cantFail(ValOrErr: S.Sym.getFlags());
316 if (SymFlags & SymbolRef::SF_Global)
317 NType |= MachO::N_EXT;
318 if (SymFlags & SymbolRef::SF_Hidden)
319 NType |= MachO::N_PEXT;
320 if (SymFlags & SymbolRef::SF_Undefined)
321 NType |= MachO::N_EXT | MachO::N_UNDF;
322 else {
323 // Here we have a symbol definition. So to fake out a section name we
324 // use 1, 2 and 3 for section numbers. See below where they are used to
325 // print out fake section names.
326 NType |= MachO::N_SECT;
327 if (SymFlags & SymbolRef::SF_Const)
328 NSect = 3;
329 else if (SymFlags & SymbolRef::SF_Executable)
330 NSect = 1;
331 else
332 NSect = 2;
333 }
334 if (SymFlags & SymbolRef::SF_Weak)
335 NDesc |= MachO::N_WEAK_DEF;
336 } else {
337 DataRefImpl SymDRI = S.Sym.getRawDataRefImpl();
338 if (MachO->is64Bit()) {
339 H_64 = MachO->MachOObjectFile::getHeader64();
340 Filetype = H_64.filetype;
341 Flags = H_64.flags;
342 if (SymDRI.p){
343 MachO::nlist_64 STE_64 = MachO->getSymbol64TableEntry(DRI: SymDRI);
344 NType = STE_64.n_type;
345 NSect = STE_64.n_sect;
346 NDesc = STE_64.n_desc;
347 NStrx = STE_64.n_strx;
348 NValue = STE_64.n_value;
349 } else {
350 NType = S.NType;
351 NSect = S.NSect;
352 NDesc = S.NDesc;
353 NStrx = 0;
354 NValue = S.Address;
355 }
356 } else {
357 H = MachO->MachOObjectFile::getHeader();
358 Filetype = H.filetype;
359 Flags = H.flags;
360 if (SymDRI.p){
361 MachO::nlist STE = MachO->getSymbolTableEntry(DRI: SymDRI);
362 NType = STE.n_type;
363 NSect = STE.n_sect;
364 NDesc = STE.n_desc;
365 NStrx = STE.n_strx;
366 NValue = STE.n_value;
367 } else {
368 NType = S.NType;
369 NSect = S.NSect;
370 NDesc = S.NDesc;
371 NStrx = 0;
372 NValue = S.Address;
373 }
374 }
375 }
376
377 // If we are printing Mach-O symbols in hex do that and return.
378 if (FormatMachOasHex) {
379 outs() << format(Fmt: printFormat, Vals: NValue) << ' '
380 << format(Fmt: "%02x %02x %04x %08x", Vals: NType, Vals: NSect, Vals: NDesc, Vals: NStrx) << ' '
381 << S.Name;
382 if ((NType & MachO::N_TYPE) == MachO::N_INDR) {
383 outs() << " (indirect for ";
384 outs() << format(Fmt: printFormat, Vals: NValue) << ' ';
385 StringRef IndirectName;
386 if (S.Sym.getRawDataRefImpl().p) {
387 if (MachO->getIndirectName(Symb: S.Sym.getRawDataRefImpl(), Res&: IndirectName))
388 outs() << "?)";
389 else
390 outs() << IndirectName << ")";
391 } else
392 outs() << S.IndirectName << ")";
393 }
394 outs() << "\n";
395 return;
396 }
397
398 if (PrintAddress) {
399 if ((NType & MachO::N_TYPE) == MachO::N_INDR)
400 strcpy(dest: SymbolAddrStr, src: printBlanks);
401 if (Obj.isIR() && (NType & MachO::N_TYPE) == MachO::N_TYPE)
402 strcpy(dest: SymbolAddrStr, src: printDashes);
403 outs() << SymbolAddrStr << ' ';
404 }
405
406 switch (NType & MachO::N_TYPE) {
407 case MachO::N_UNDF:
408 if (NValue != 0) {
409 outs() << "(common) ";
410 if (MachO::GET_COMM_ALIGN(n_desc: NDesc) != 0)
411 outs() << "(alignment 2^" << (int)MachO::GET_COMM_ALIGN(n_desc: NDesc) << ") ";
412 } else {
413 if ((NType & MachO::N_TYPE) == MachO::N_PBUD)
414 outs() << "(prebound ";
415 else
416 outs() << "(";
417 if ((NDesc & MachO::REFERENCE_TYPE) ==
418 MachO::REFERENCE_FLAG_UNDEFINED_LAZY)
419 outs() << "undefined [lazy bound]) ";
420 else if ((NDesc & MachO::REFERENCE_TYPE) ==
421 MachO::REFERENCE_FLAG_PRIVATE_UNDEFINED_LAZY)
422 outs() << "undefined [private lazy bound]) ";
423 else if ((NDesc & MachO::REFERENCE_TYPE) ==
424 MachO::REFERENCE_FLAG_PRIVATE_UNDEFINED_NON_LAZY)
425 outs() << "undefined [private]) ";
426 else
427 outs() << "undefined) ";
428 }
429 break;
430 case MachO::N_ABS:
431 outs() << "(absolute) ";
432 break;
433 case MachO::N_INDR:
434 outs() << "(indirect) ";
435 break;
436 case MachO::N_SECT: {
437 if (Obj.isIR()) {
438 // For llvm bitcode files print out a fake section name using the values
439 // use 1, 2 and 3 for section numbers as set above.
440 if (NSect == 1)
441 outs() << "(LTO,CODE) ";
442 else if (NSect == 2)
443 outs() << "(LTO,DATA) ";
444 else if (NSect == 3)
445 outs() << "(LTO,RODATA) ";
446 else
447 outs() << "(?,?) ";
448 break;
449 }
450 section_iterator Sec = SectionRef();
451 if (S.Sym.getRawDataRefImpl().p) {
452 Expected<section_iterator> SecOrErr =
453 MachO->getSymbolSection(Symb: S.Sym.getRawDataRefImpl());
454 if (!SecOrErr) {
455 consumeError(Err: SecOrErr.takeError());
456 outs() << "(?,?) ";
457 break;
458 }
459 Sec = *SecOrErr;
460 if (Sec == MachO->section_end()) {
461 outs() << "(?,?) ";
462 break;
463 }
464 } else {
465 Sec = S.Section;
466 }
467 DataRefImpl Ref = Sec->getRawDataRefImpl();
468 StringRef SectionName;
469 if (Expected<StringRef> NameOrErr = MachO->getSectionName(Sec: Ref))
470 SectionName = *NameOrErr;
471 StringRef SegmentName = MachO->getSectionFinalSegmentName(Sec: Ref);
472 outs() << "(" << SegmentName << "," << SectionName << ") ";
473 break;
474 }
475 default:
476 outs() << "(?) ";
477 break;
478 }
479
480 if (NType & MachO::N_EXT) {
481 if (NDesc & MachO::REFERENCED_DYNAMICALLY)
482 outs() << "[referenced dynamically] ";
483 if (NType & MachO::N_PEXT) {
484 if ((NDesc & MachO::N_WEAK_DEF) == MachO::N_WEAK_DEF)
485 outs() << "weak private external ";
486 else
487 outs() << "private external ";
488 } else {
489 if ((NDesc & MachO::N_WEAK_REF) == MachO::N_WEAK_REF ||
490 (NDesc & MachO::N_WEAK_DEF) == MachO::N_WEAK_DEF) {
491 if ((NDesc & (MachO::N_WEAK_REF | MachO::N_WEAK_DEF)) ==
492 (MachO::N_WEAK_REF | MachO::N_WEAK_DEF))
493 outs() << "weak external automatically hidden ";
494 else
495 outs() << "weak external ";
496 } else
497 outs() << "external ";
498 }
499 } else {
500 if (NType & MachO::N_PEXT)
501 outs() << "non-external (was a private external) ";
502 else
503 outs() << "non-external ";
504 }
505
506 if (Filetype == MachO::MH_OBJECT) {
507 if (NDesc & MachO::N_NO_DEAD_STRIP)
508 outs() << "[no dead strip] ";
509 if ((NType & MachO::N_TYPE) != MachO::N_UNDF &&
510 NDesc & MachO::N_SYMBOL_RESOLVER)
511 outs() << "[symbol resolver] ";
512 if ((NType & MachO::N_TYPE) != MachO::N_UNDF && NDesc & MachO::N_ALT_ENTRY)
513 outs() << "[alt entry] ";
514 if ((NType & MachO::N_TYPE) != MachO::N_UNDF && NDesc & MachO::N_COLD_FUNC)
515 outs() << "[cold func] ";
516 }
517
518 if ((NDesc & MachO::N_ARM_THUMB_DEF) == MachO::N_ARM_THUMB_DEF)
519 outs() << "[Thumb] ";
520
521 if ((NType & MachO::N_TYPE) == MachO::N_INDR) {
522 outs() << S.Name << " (for ";
523 StringRef IndirectName;
524 if (MachO) {
525 if (S.Sym.getRawDataRefImpl().p) {
526 if (MachO->getIndirectName(Symb: S.Sym.getRawDataRefImpl(), Res&: IndirectName))
527 outs() << "?)";
528 else
529 outs() << IndirectName << ")";
530 } else
531 outs() << S.IndirectName << ")";
532 } else
533 outs() << "?)";
534 } else
535 outs() << S.Name;
536
537 if ((Flags & MachO::MH_TWOLEVEL) == MachO::MH_TWOLEVEL &&
538 (((NType & MachO::N_TYPE) == MachO::N_UNDF && NValue == 0) ||
539 (NType & MachO::N_TYPE) == MachO::N_PBUD)) {
540 uint32_t LibraryOrdinal = MachO::GET_LIBRARY_ORDINAL(n_desc: NDesc);
541 if (LibraryOrdinal != 0) {
542 if (LibraryOrdinal == MachO::EXECUTABLE_ORDINAL)
543 outs() << " (from executable)";
544 else if (LibraryOrdinal == MachO::DYNAMIC_LOOKUP_ORDINAL)
545 outs() << " (dynamically looked up)";
546 else {
547 StringRef LibraryName;
548 if (!MachO ||
549 MachO->getLibraryShortNameByIndex(Index: LibraryOrdinal - 1, LibraryName))
550 outs() << " (from bad library ordinal " << LibraryOrdinal << ")";
551 else
552 outs() << " (from " << LibraryName << ")";
553 }
554 }
555 }
556}
557
558// Table that maps Darwin's Mach-O stab constants to strings to allow printing.
559struct DarwinStabName {
560 uint8_t NType;
561 const char *Name;
562};
563const struct DarwinStabName DarwinStabNames[] = {
564 {.NType: MachO::N_GSYM, .Name: "GSYM"}, {.NType: MachO::N_FNAME, .Name: "FNAME"},
565 {.NType: MachO::N_FUN, .Name: "FUN"}, {.NType: MachO::N_STSYM, .Name: "STSYM"},
566 {.NType: MachO::N_LCSYM, .Name: "LCSYM"}, {.NType: MachO::N_BNSYM, .Name: "BNSYM"},
567 {.NType: MachO::N_PC, .Name: "PC"}, {.NType: MachO::N_AST, .Name: "AST"},
568 {.NType: MachO::N_OPT, .Name: "OPT"}, {.NType: MachO::N_RSYM, .Name: "RSYM"},
569 {.NType: MachO::N_SLINE, .Name: "SLINE"}, {.NType: MachO::N_ENSYM, .Name: "ENSYM"},
570 {.NType: MachO::N_SSYM, .Name: "SSYM"}, {.NType: MachO::N_SO, .Name: "SO"},
571 {.NType: MachO::N_OSO, .Name: "OSO"}, {.NType: MachO::N_LIB, .Name: "LIB"},
572 {.NType: MachO::N_LSYM, .Name: "LSYM"}, {.NType: MachO::N_BINCL, .Name: "BINCL"},
573 {.NType: MachO::N_SOL, .Name: "SOL"}, {.NType: MachO::N_PARAMS, .Name: "PARAM"},
574 {.NType: MachO::N_VERSION, .Name: "VERS"}, {.NType: MachO::N_OLEVEL, .Name: "OLEV"},
575 {.NType: MachO::N_PSYM, .Name: "PSYM"}, {.NType: MachO::N_EINCL, .Name: "EINCL"},
576 {.NType: MachO::N_ENTRY, .Name: "ENTRY"}, {.NType: MachO::N_LBRAC, .Name: "LBRAC"},
577 {.NType: MachO::N_EXCL, .Name: "EXCL"}, {.NType: MachO::N_RBRAC, .Name: "RBRAC"},
578 {.NType: MachO::N_BCOMM, .Name: "BCOMM"}, {.NType: MachO::N_ECOMM, .Name: "ECOMM"},
579 {.NType: MachO::N_ECOML, .Name: "ECOML"}, {.NType: MachO::N_LENG, .Name: "LENG"},
580};
581
582static const char *getDarwinStabString(uint8_t NType) {
583 for (auto I : ArrayRef(DarwinStabNames))
584 if (I.NType == NType)
585 return I.Name;
586 return nullptr;
587}
588
589// darwinPrintStab() prints the n_sect, n_desc along with a symbolic name of
590// a stab n_type value in a Mach-O file.
591static void darwinPrintStab(MachOObjectFile *MachO, const NMSymbol &S) {
592 MachO::nlist_64 STE_64;
593 MachO::nlist STE;
594 uint8_t NType;
595 uint8_t NSect;
596 uint16_t NDesc;
597 DataRefImpl SymDRI = S.Sym.getRawDataRefImpl();
598 if (MachO->is64Bit()) {
599 STE_64 = MachO->getSymbol64TableEntry(DRI: SymDRI);
600 NType = STE_64.n_type;
601 NSect = STE_64.n_sect;
602 NDesc = STE_64.n_desc;
603 } else {
604 STE = MachO->getSymbolTableEntry(DRI: SymDRI);
605 NType = STE.n_type;
606 NSect = STE.n_sect;
607 NDesc = STE.n_desc;
608 }
609
610 outs() << format(Fmt: " %02x %04x ", Vals: NSect, Vals: NDesc);
611 if (const char *stabString = getDarwinStabString(NType))
612 outs() << format(Fmt: "%5.5s", Vals: stabString);
613 else
614 outs() << format(Fmt: " %02x", Vals: NType);
615}
616
617static bool symbolIsDefined(const NMSymbol &Sym) {
618 return Sym.TypeChar != 'U' && Sym.TypeChar != 'w' && Sym.TypeChar != 'v';
619}
620
621static void writeFileName(raw_ostream &S, StringRef ArchiveName,
622 StringRef ArchitectureName) {
623 if (!ArchitectureName.empty())
624 S << "(for architecture " << ArchitectureName << "):";
625 if (OutputFormat == posix && !ArchiveName.empty())
626 S << ArchiveName << "[" << CurrentFilename << "]: ";
627 else {
628 if (!ArchiveName.empty())
629 S << ArchiveName << ":";
630 S << CurrentFilename << ": ";
631 }
632}
633
634static void sortSymbolList(std::vector<NMSymbol> &SymbolList) {
635 if (NoSort)
636 return;
637
638 if (ReverseSort)
639 llvm::sort(C&: SymbolList, Comp: std::greater<>());
640 else
641 llvm::sort(C&: SymbolList);
642}
643
644static void printExportSymbolList(const std::vector<NMSymbol> &SymbolList) {
645 for (const NMSymbol &Sym : SymbolList) {
646 outs() << Sym.Name;
647 if (!Sym.Visibility.empty())
648 outs() << ' ' << Sym.Visibility;
649 outs() << '\n';
650 }
651}
652
653static void printLineNumbers(symbolize::LLVMSymbolizer &Symbolizer,
654 const NMSymbol &S) {
655 const auto *Obj = dyn_cast<ObjectFile>(Val: S.Sym.getObject());
656 if (!Obj)
657 return;
658 const SymbolRef Sym(S.Sym);
659 uint64_t SectionIndex = object::SectionedAddress::UndefSection;
660 section_iterator Sec = cantFail(ValOrErr: Sym.getSection());
661 if (Sec != Obj->section_end())
662 SectionIndex = Sec->getIndex();
663 object::SectionedAddress Address = {.Address: cantFail(ValOrErr: Sym.getAddress()), .SectionIndex: SectionIndex};
664
665 std::string FileName;
666 uint32_t Line;
667 switch (S.TypeChar) {
668 // For undefined symbols, find the first relocation for that symbol with a
669 // line number.
670 case 'U': {
671 for (const SectionRef RelocsSec : Obj->sections()) {
672 if (RelocsSec.relocations().empty())
673 continue;
674 SectionRef TextSec = *cantFail(ValOrErr: RelocsSec.getRelocatedSection());
675 if (!TextSec.isText())
676 continue;
677 for (const RelocationRef R : RelocsSec.relocations()) {
678 if (R.getSymbol() != Sym)
679 continue;
680 Expected<DILineInfo> ResOrErr = Symbolizer.symbolizeCode(
681 Obj: *Obj, ModuleOffset: {.Address: TextSec.getAddress() + R.getOffset(), .SectionIndex: SectionIndex});
682 if (!ResOrErr) {
683 error(E: ResOrErr.takeError(), FileName: Obj->getFileName());
684 return;
685 }
686 if (ResOrErr->FileName == DILineInfo::BadString)
687 return;
688 FileName = std::move(ResOrErr->FileName);
689 Line = ResOrErr->Line;
690 break;
691 }
692 if (!FileName.empty())
693 break;
694 }
695 if (FileName.empty())
696 return;
697 break;
698 }
699 case 't':
700 case 'T': {
701 Expected<DILineInfo> ResOrErr = Symbolizer.symbolizeCode(Obj: *Obj, ModuleOffset: Address);
702 if (!ResOrErr) {
703 error(E: ResOrErr.takeError(), FileName: Obj->getFileName());
704 return;
705 }
706 if (ResOrErr->FileName == DILineInfo::BadString)
707 return;
708 FileName = std::move(ResOrErr->FileName);
709 Line = ResOrErr->Line;
710 break;
711 }
712 default: {
713 Expected<DIGlobal> ResOrErr = Symbolizer.symbolizeData(Obj: *Obj, ModuleOffset: Address);
714 if (!ResOrErr) {
715 error(E: ResOrErr.takeError(), FileName: Obj->getFileName());
716 return;
717 }
718 if (ResOrErr->DeclFile.empty())
719 return;
720 FileName = std::move(ResOrErr->DeclFile);
721 Line = ResOrErr->DeclLine;
722 break;
723 }
724 }
725 outs() << '\t' << FileName << ':' << Line;
726}
727
728static void printSymbolList(SymbolicFile &Obj,
729 std::vector<NMSymbol> &SymbolList, bool printName,
730 StringRef ArchiveName, StringRef ArchitectureName) {
731 std::optional<symbolize::LLVMSymbolizer> Symbolizer;
732 if (LineNumbers)
733 Symbolizer.emplace();
734
735 if (!PrintFileName) {
736 if ((OutputFormat == bsd || OutputFormat == posix ||
737 OutputFormat == just_symbols) &&
738 MultipleFiles && printName) {
739 outs() << '\n' << CurrentFilename << ":\n";
740 } else if (OutputFormat == sysv) {
741 outs() << "\n\nSymbols from " << CurrentFilename << ":\n\n";
742 if (Obj.is64Bit())
743 outs() << "Name Value Class Type"
744 << " Size Line Section\n";
745 else
746 outs() << "Name Value Class Type"
747 << " Size Line Section\n";
748 }
749 }
750
751 const char *printBlanks, *printDashes, *printFormat;
752 if (Obj.is64Bit()) {
753 printBlanks = " ";
754 printDashes = "----------------";
755 switch (AddressRadix) {
756 case Radix::o:
757 printFormat = OutputFormat == posix ? "%" PRIo64 : "%016" PRIo64;
758 break;
759 case Radix::x:
760 printFormat = OutputFormat == posix ? "%" PRIx64 : "%016" PRIx64;
761 break;
762 default:
763 printFormat = OutputFormat == posix ? "%" PRId64 : "%016" PRId64;
764 }
765 } else {
766 printBlanks = " ";
767 printDashes = "--------";
768 switch (AddressRadix) {
769 case Radix::o:
770 printFormat = OutputFormat == posix ? "%" PRIo64 : "%08" PRIo64;
771 break;
772 case Radix::x:
773 printFormat = OutputFormat == posix ? "%" PRIx64 : "%08" PRIx64;
774 break;
775 default:
776 printFormat = OutputFormat == posix ? "%" PRId64 : "%08" PRId64;
777 }
778 }
779
780 for (const NMSymbol &S : SymbolList) {
781 if (!S.shouldPrint())
782 continue;
783
784 std::string Name = S.Name;
785 MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(Val: &Obj);
786 if (Demangle)
787 Name = demangle(MangledName: Name);
788
789 if (PrintFileName)
790 writeFileName(S&: outs(), ArchiveName, ArchitectureName);
791 if ((OutputFormat == just_symbols ||
792 (UndefinedOnly && MachO && OutputFormat != darwin)) &&
793 OutputFormat != posix) {
794 outs() << Name << "\n";
795 continue;
796 }
797
798 char SymbolAddrStr[23], SymbolSizeStr[23];
799
800 // If the format is SysV or the symbol isn't defined, then print spaces.
801 if (OutputFormat == sysv || !symbolIsDefined(Sym: S)) {
802 if (OutputFormat == posix) {
803 format(Fmt: printFormat, Vals: S.Address)
804 .snprint(Buffer: SymbolAddrStr, BufferSize: sizeof(SymbolAddrStr));
805 format(Fmt: printFormat, Vals: S.Size)
806 .snprint(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 .snprint(Buffer: SymbolAddrStr, BufferSize: sizeof(SymbolAddrStr));
822 format(Fmt: printFormat, Vals: S.Size).snprint(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 const char *Q = ExportsNameBuffer.c_str();
1407 for (unsigned K = 0; K < ExportsAdded; K++) {
1408 SymbolList[I].Name = Q;
1409 Q += strlen(s: Q) + 1;
1410 if (SymbolList[I].TypeChar == 'I') {
1411 SymbolList[I].IndirectName = Q;
1412 Q += strlen(s: Q) + 1;
1413 }
1414 I++;
1415 }
1416 }
1417
1418 // Add the undefined symbols from the bind entries.
1419 unsigned BindsAdded = 0;
1420 Error BErr = Error::success();
1421 StringRef LastSymbolName = StringRef();
1422 for (const llvm::object::MachOBindEntry &Entry : MachO.bindTable(Err&: BErr)) {
1423 bool found = false;
1424 if (LastSymbolName == Entry.symbolName())
1425 found = true;
1426 else if (!DyldInfoOnly) {
1427 for (unsigned J = 0; J < SymbolList.size() && !found; ++J) {
1428 if (SymbolList[J].Name == Entry.symbolName())
1429 found = true;
1430 }
1431 }
1432 if (!found) {
1433 LastSymbolName = Entry.symbolName();
1434 NMSymbol B = {};
1435 B.Address = 0;
1436 B.Size = 0;
1437 B.TypeChar = 'U';
1438 // There is no symbol in the nlist symbol table for this so we set
1439 // Sym effectivly to null and the rest of code in here must test for
1440 // it and not do things like Sym.getFlags() for it.
1441 B.Sym = BasicSymbolRef();
1442 B.SymFlags = SymbolRef::SF_Global | SymbolRef::SF_Undefined;
1443 B.NType = MachO::N_EXT | MachO::N_UNDF;
1444 B.NSect = 0;
1445 B.NDesc = 0;
1446 MachO::SET_LIBRARY_ORDINAL(n_desc&: B.NDesc, ordinal: Entry.ordinal());
1447 B.Name = Entry.symbolName().str();
1448 SymbolList.push_back(x: B);
1449 BOS << Entry.symbolName();
1450 BOS << '\0';
1451 BindsAdded++;
1452 }
1453 }
1454 if (BErr)
1455 error(E: std::move(BErr), FileName: MachO.getFileName());
1456 // Set the symbol names and indirect names for the added symbols.
1457 if (BindsAdded) {
1458 const char *Q = BindsNameBuffer.c_str();
1459 for (unsigned K = 0; K < BindsAdded; K++) {
1460 SymbolList[I].Name = Q;
1461 Q += strlen(s: Q) + 1;
1462 if (SymbolList[I].TypeChar == 'I') {
1463 SymbolList[I].IndirectName = Q;
1464 Q += strlen(s: Q) + 1;
1465 }
1466 I++;
1467 }
1468 }
1469
1470 // Add the undefined symbols from the lazy bind entries.
1471 unsigned LazysAdded = 0;
1472 Error LErr = Error::success();
1473 LastSymbolName = StringRef();
1474 for (const llvm::object::MachOBindEntry &Entry :
1475 MachO.lazyBindTable(Err&: LErr)) {
1476 bool found = false;
1477 if (LastSymbolName == Entry.symbolName())
1478 found = true;
1479 else {
1480 // Here we must check to see it this symbol is already in the
1481 // SymbolList as it might have already have been added above via a
1482 // non-lazy (bind) entry.
1483 for (unsigned J = 0; J < SymbolList.size() && !found; ++J) {
1484 if (SymbolList[J].Name == Entry.symbolName())
1485 found = true;
1486 }
1487 }
1488 if (!found) {
1489 LastSymbolName = Entry.symbolName();
1490 NMSymbol L = {};
1491 L.Name = Entry.symbolName().str();
1492 L.Address = 0;
1493 L.Size = 0;
1494 L.TypeChar = 'U';
1495 // There is no symbol in the nlist symbol table for this so we set
1496 // Sym effectivly to null and the rest of code in here must test for
1497 // it and not do things like Sym.getFlags() for it.
1498 L.Sym = BasicSymbolRef();
1499 L.SymFlags = SymbolRef::SF_Global | SymbolRef::SF_Undefined;
1500 L.NType = MachO::N_EXT | MachO::N_UNDF;
1501 L.NSect = 0;
1502 // The REFERENCE_FLAG_UNDEFINED_LAZY is no longer used but here it
1503 // makes sence since we are creating this from a lazy bind entry.
1504 L.NDesc = MachO::REFERENCE_FLAG_UNDEFINED_LAZY;
1505 MachO::SET_LIBRARY_ORDINAL(n_desc&: L.NDesc, ordinal: Entry.ordinal());
1506 SymbolList.push_back(x: L);
1507 LOS << Entry.symbolName();
1508 LOS << '\0';
1509 LazysAdded++;
1510 }
1511 }
1512 if (LErr)
1513 error(E: std::move(LErr), FileName: MachO.getFileName());
1514 // Set the symbol names and indirect names for the added symbols.
1515 if (LazysAdded) {
1516 const char *Q = LazysNameBuffer.c_str();
1517 for (unsigned K = 0; K < LazysAdded; K++) {
1518 SymbolList[I].Name = Q;
1519 Q += strlen(s: Q) + 1;
1520 if (SymbolList[I].TypeChar == 'I') {
1521 SymbolList[I].IndirectName = Q;
1522 Q += strlen(s: Q) + 1;
1523 }
1524 I++;
1525 }
1526 }
1527
1528 // Add the undefineds symbol from the weak bind entries which are not
1529 // strong symbols.
1530 unsigned WeaksAdded = 0;
1531 Error WErr = Error::success();
1532 LastSymbolName = StringRef();
1533 for (const llvm::object::MachOBindEntry &Entry :
1534 MachO.weakBindTable(Err&: WErr)) {
1535 bool found = false;
1536 unsigned J = 0;
1537 if (LastSymbolName == Entry.symbolName() ||
1538 Entry.flags() & MachO::BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION) {
1539 found = true;
1540 } else {
1541 for (J = 0; J < SymbolList.size() && !found; ++J) {
1542 if (SymbolList[J].Name == Entry.symbolName()) {
1543 found = true;
1544 break;
1545 }
1546 }
1547 }
1548 if (!found) {
1549 LastSymbolName = Entry.symbolName();
1550 NMSymbol W = {};
1551 W.Name = Entry.symbolName().str();
1552 W.Address = 0;
1553 W.Size = 0;
1554 W.TypeChar = 'U';
1555 // There is no symbol in the nlist symbol table for this so we set
1556 // Sym effectivly to null and the rest of code in here must test for
1557 // it and not do things like Sym.getFlags() for it.
1558 W.Sym = BasicSymbolRef();
1559 W.SymFlags = SymbolRef::SF_Global | SymbolRef::SF_Undefined;
1560 W.NType = MachO::N_EXT | MachO::N_UNDF;
1561 W.NSect = 0;
1562 // Odd that we are using N_WEAK_DEF on an undefined symbol but that is
1563 // what is created in this case by the linker when there are real
1564 // symbols in the nlist structs.
1565 W.NDesc = MachO::N_WEAK_DEF;
1566 SymbolList.push_back(x: W);
1567 WOS << Entry.symbolName();
1568 WOS << '\0';
1569 WeaksAdded++;
1570 } else {
1571 // This is the case the symbol was previously been found and it could
1572 // have been added from a bind or lazy bind symbol. If so and not
1573 // a definition also mark it as weak.
1574 if (SymbolList[J].TypeChar == 'U')
1575 // See comment above about N_WEAK_DEF.
1576 SymbolList[J].NDesc |= MachO::N_WEAK_DEF;
1577 }
1578 }
1579 if (WErr)
1580 error(E: std::move(WErr), FileName: MachO.getFileName());
1581 // Set the symbol names and indirect names for the added symbols.
1582 if (WeaksAdded) {
1583 const char *Q = WeaksNameBuffer.c_str();
1584 for (unsigned K = 0; K < WeaksAdded; K++) {
1585 SymbolList[I].Name = Q;
1586 Q += strlen(s: Q) + 1;
1587 if (SymbolList[I].TypeChar == 'I') {
1588 SymbolList[I].IndirectName = Q;
1589 Q += strlen(s: Q) + 1;
1590 }
1591 I++;
1592 }
1593 }
1594
1595 // Trying adding symbol from the function starts table and LC_MAIN entry
1596 // point.
1597 SmallVector<uint64_t, 8> FoundFns;
1598 uint64_t lc_main_offset = UINT64_MAX;
1599 for (const auto &Command : MachO.load_commands()) {
1600 if (Command.C.cmd == MachO::LC_FUNCTION_STARTS) {
1601 // We found a function starts segment, parse the addresses for
1602 // consumption.
1603 MachO::linkedit_data_command LLC =
1604 MachO.getLinkeditDataLoadCommand(L: Command);
1605
1606 MachO.ReadULEB128s(Index: LLC.dataoff, Out&: FoundFns);
1607 } else if (Command.C.cmd == MachO::LC_MAIN) {
1608 MachO::entry_point_command LCmain = MachO.getEntryPointCommand(L: Command);
1609 lc_main_offset = LCmain.entryoff;
1610 }
1611 }
1612 // See if these addresses are already in the symbol table.
1613 unsigned FunctionStartsAdded = 0;
1614 // The addresses from FoundFns come from LC_FUNCTION_STARTS. Its contents
1615 // are delta encoded addresses from the start of __TEXT, ending when zero
1616 // is found. Because of this, the addresses should be unique, and even if
1617 // we create fake entries on SymbolList in the second loop, SymbolAddresses
1618 // should not need to be updated there.
1619 SmallSet<uint64_t, 32> SymbolAddresses;
1620 for (const auto &S : SymbolList)
1621 SymbolAddresses.insert(V: S.Address);
1622 for (uint64_t f = 0; f < FoundFns.size(); f++) {
1623 // See if this address is already in the symbol table, otherwise fake up
1624 // an nlist for it.
1625 if (!SymbolAddresses.contains(V: FoundFns[f] + BaseSegmentAddress)) {
1626 NMSymbol F = {};
1627 F.Name = "<redacted function X>";
1628 F.Address = FoundFns[f] + BaseSegmentAddress;
1629 F.Size = 0;
1630 // There is no symbol in the nlist symbol table for this so we set
1631 // Sym effectivly to null and the rest of code in here must test for
1632 // it and not do things like Sym.getFlags() for it.
1633 F.Sym = BasicSymbolRef();
1634 F.SymFlags = 0;
1635 F.NType = MachO::N_SECT;
1636 F.NSect = 0;
1637 StringRef SegmentName = StringRef();
1638 StringRef SectionName = StringRef();
1639 for (const SectionRef &Section : MachO.sections()) {
1640 if (Expected<StringRef> NameOrErr = Section.getName())
1641 SectionName = *NameOrErr;
1642 else
1643 consumeError(Err: NameOrErr.takeError());
1644
1645 SegmentName =
1646 MachO.getSectionFinalSegmentName(Sec: Section.getRawDataRefImpl());
1647 F.NSect++;
1648 if (F.Address >= Section.getAddress() &&
1649 F.Address < Section.getAddress() + Section.getSize()) {
1650 F.Section = Section;
1651 break;
1652 }
1653 }
1654 if (SegmentName == "__TEXT" && SectionName == "__text")
1655 F.TypeChar = 't';
1656 else if (SegmentName == "__DATA" && SectionName == "__data")
1657 F.TypeChar = 'd';
1658 else if (SegmentName == "__DATA" && SectionName == "__bss")
1659 F.TypeChar = 'b';
1660 else
1661 F.TypeChar = 's';
1662 F.NDesc = 0;
1663 SymbolList.push_back(x: F);
1664 if (FoundFns[f] == lc_main_offset)
1665 FOS << "<redacted LC_MAIN>";
1666 else
1667 FOS << "<redacted function " << f << ">";
1668 FOS << '\0';
1669 FunctionStartsAdded++;
1670 }
1671 }
1672 if (FunctionStartsAdded) {
1673 const char *Q = FunctionStartsNameBuffer.c_str();
1674 for (unsigned K = 0; K < FunctionStartsAdded; K++) {
1675 SymbolList[I].Name = Q;
1676 Q += strlen(s: Q) + 1;
1677 if (SymbolList[I].TypeChar == 'I') {
1678 SymbolList[I].IndirectName = Q;
1679 Q += strlen(s: Q) + 1;
1680 }
1681 I++;
1682 }
1683 }
1684 }
1685}
1686
1687static bool shouldDump(SymbolicFile &Obj) {
1688 // The -X option is currently only implemented for XCOFF, ELF, and IR object
1689 // files. The option isn't fundamentally impossible with other formats, just
1690 // isn't implemented.
1691 if (!isa<XCOFFObjectFile>(Val: Obj) && !isa<ELFObjectFileBase>(Val: Obj) &&
1692 !isa<IRObjectFile>(Val: Obj))
1693 return true;
1694
1695 return Obj.is64Bit() ? BitMode != BitModeTy::Bit32
1696 : BitMode != BitModeTy::Bit64;
1697}
1698
1699static void getXCOFFExports(XCOFFObjectFile *XCOFFObj,
1700 std::vector<NMSymbol> &SymbolList,
1701 StringRef ArchiveName) {
1702 // Skip Shared object file.
1703 if (XCOFFObj->getFlags() & XCOFF::F_SHROBJ)
1704 return;
1705
1706 for (SymbolRef Sym : XCOFFObj->symbols()) {
1707 // There is no visibility in old 32 bit XCOFF object file interpret.
1708 bool HasVisibilityAttr =
1709 XCOFFObj->is64Bit() || (XCOFFObj->auxiliaryHeader32() &&
1710 (XCOFFObj->auxiliaryHeader32()->getVersion() ==
1711 XCOFF::NEW_XCOFF_INTERPRET));
1712
1713 if (HasVisibilityAttr) {
1714 XCOFFSymbolRef XCOFFSym = XCOFFObj->toSymbolRef(Ref: Sym.getRawDataRefImpl());
1715 uint16_t SymType = XCOFFSym.getSymbolType();
1716 if ((SymType & XCOFF::VISIBILITY_MASK) == XCOFF::SYM_V_INTERNAL)
1717 continue;
1718 if ((SymType & XCOFF::VISIBILITY_MASK) == XCOFF::SYM_V_HIDDEN)
1719 continue;
1720 }
1721
1722 Expected<section_iterator> SymSecOrErr = Sym.getSection();
1723 if (!SymSecOrErr) {
1724 warn(Err: SymSecOrErr.takeError(), FileName: XCOFFObj->getFileName(),
1725 Context: "for symbol with index " +
1726 Twine(XCOFFObj->getSymbolIndex(SymEntPtr: Sym.getRawDataRefImpl().p)),
1727 Archive: ArchiveName);
1728 continue;
1729 }
1730 section_iterator SecIter = *SymSecOrErr;
1731 // If the symbol is not in a text or data section, it is not exported.
1732 if (SecIter == XCOFFObj->section_end())
1733 continue;
1734 if (!(SecIter->isText() || SecIter->isData() || SecIter->isBSS()))
1735 continue;
1736
1737 StringRef SymName = cantFail(ValOrErr: Sym.getName());
1738 if (SymName.empty())
1739 continue;
1740 if (SymName.starts_with(Prefix: "__sinit") || SymName.starts_with(Prefix: "__sterm") ||
1741 SymName.front() == '.' || SymName.front() == '(')
1742 continue;
1743
1744 // Check the SymName regex matching with "^__[0-9]+__".
1745 if (SymName.size() > 4 && SymName.starts_with(Prefix: "__") &&
1746 SymName.ends_with(Suffix: "__")) {
1747 if (std::all_of(first: SymName.begin() + 2, last: SymName.end() - 2, pred: isDigit))
1748 continue;
1749 }
1750
1751 if (SymName == "__rsrc" && NoRsrc)
1752 continue;
1753
1754 if (SymName.starts_with(Prefix: "__tf1"))
1755 SymName = SymName.substr(Start: 6);
1756 else if (SymName.starts_with(Prefix: "__tf9"))
1757 SymName = SymName.substr(Start: 14);
1758
1759 NMSymbol S = {};
1760 S.Name = SymName.str();
1761 S.Sym = Sym;
1762
1763 if (HasVisibilityAttr) {
1764 XCOFFSymbolRef XCOFFSym = XCOFFObj->toSymbolRef(Ref: Sym.getRawDataRefImpl());
1765 uint16_t SymType = XCOFFSym.getSymbolType();
1766 if ((SymType & XCOFF::VISIBILITY_MASK) == XCOFF::SYM_V_PROTECTED)
1767 S.Visibility = "protected";
1768 else if ((SymType & XCOFF::VISIBILITY_MASK) == XCOFF::SYM_V_EXPORTED)
1769 S.Visibility = "export";
1770 }
1771 if (S.initializeFlags(Obj: *XCOFFObj))
1772 SymbolList.push_back(x: S);
1773 }
1774}
1775
1776static Expected<SymbolicFile::basic_symbol_iterator_range>
1777getDynamicSyms(SymbolicFile &Obj) {
1778 const auto *E = dyn_cast<ELFObjectFileBase>(Val: &Obj);
1779 if (!E)
1780 return createError(Err: "File format has no dynamic symbol table");
1781 return E->getDynamicSymbolIterators();
1782}
1783
1784// Returns false if there is error found or true otherwise.
1785static bool getSymbolNamesFromObject(SymbolicFile &Obj,
1786 std::vector<NMSymbol> &SymbolList) {
1787 auto Symbols = Obj.symbols();
1788 std::vector<VersionEntry> SymbolVersions;
1789
1790 if (DynamicSyms) {
1791 Expected<SymbolicFile::basic_symbol_iterator_range> SymbolsOrErr =
1792 getDynamicSyms(Obj);
1793 if (!SymbolsOrErr) {
1794 error(E: SymbolsOrErr.takeError(), FileName: Obj.getFileName());
1795 return false;
1796 }
1797 Symbols = *SymbolsOrErr;
1798 if (const auto *E = dyn_cast<ELFObjectFileBase>(Val: &Obj)) {
1799 if (Expected<std::vector<VersionEntry>> VersionsOrErr =
1800 E->readDynsymVersions())
1801 SymbolVersions = std::move(*VersionsOrErr);
1802 else
1803 WithColor::warning(OS&: errs(), Prefix: ToolName)
1804 << "unable to read symbol versions: "
1805 << toString(E: VersionsOrErr.takeError()) << "\n";
1806 }
1807 }
1808 // If a "-s segname sectname" option was specified and this is a Mach-O
1809 // file get the section number for that section in this object file.
1810 unsigned int Nsect = 0;
1811 MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(Val: &Obj);
1812 if (!SegSect.empty() && MachO) {
1813 Nsect = getNsectForSegSect(Obj: MachO);
1814 // If this section is not in the object file no symbols are printed.
1815 if (Nsect == 0)
1816 return false;
1817 }
1818
1819 if (!(MachO && DyldInfoOnly)) {
1820 size_t I = -1;
1821 for (BasicSymbolRef Sym : Symbols) {
1822 ++I;
1823 Expected<uint32_t> SymFlagsOrErr = Sym.getFlags();
1824 if (!SymFlagsOrErr) {
1825 error(E: SymFlagsOrErr.takeError(), FileName: Obj.getFileName());
1826 return false;
1827 }
1828
1829 // Drop format-specific symbols (STT_FILE, STT_SECTION, etc.) but
1830 // retain mapping symbols (STT_NOTYPE such as $d, $x) on ARM, AArch64,
1831 // CSKY, and RISC-V targets to honor the --special-syms option.
1832 if (!DebugSyms && (*SymFlagsOrErr & SymbolRef::SF_FormatSpecific)) {
1833 auto *ELFObj = dyn_cast<ELFObjectFileBase>(Val: &Obj);
1834 bool IsMappingSymbol =
1835 ELFObj &&
1836 llvm::is_contained(
1837 Set: {ELF::EM_ARM, ELF::EM_AARCH64, ELF::EM_CSKY, ELF::EM_RISCV},
1838 Element: ELFObj->getEMachine()) &&
1839 ELFSymbolRef(Sym).getELFType() == ELF::STT_NOTYPE;
1840 if (!IsMappingSymbol)
1841 continue;
1842 }
1843 if (WithoutAliases && (*SymFlagsOrErr & SymbolRef::SF_Indirect))
1844 continue;
1845 // If a "-s segname sectname" option was specified and this is a Mach-O
1846 // file and this section appears in this file, Nsect will be non-zero then
1847 // see if this symbol is a symbol from that section and if not skip it.
1848 if (Nsect && Nsect != getNsectInMachO(Obj&: *MachO, Sym))
1849 continue;
1850 NMSymbol S = {};
1851 S.Size = 0;
1852 S.Address = 0;
1853 if (isa<ELFObjectFileBase>(Val: &Obj))
1854 S.Size = ELFSymbolRef(Sym).getSize();
1855
1856 if (const XCOFFObjectFile *XCOFFObj =
1857 dyn_cast<const XCOFFObjectFile>(Val: &Obj))
1858 S.Size = XCOFFObj->getSymbolSize(Symb: Sym.getRawDataRefImpl());
1859
1860 if (const WasmObjectFile *WasmObj = dyn_cast<WasmObjectFile>(Val: &Obj))
1861 S.Size = WasmObj->getSymbolSize(Sym);
1862
1863 if (PrintAddress && isa<ObjectFile>(Val: Obj)) {
1864 SymbolRef SymRef(Sym);
1865 Expected<uint64_t> AddressOrErr = SymRef.getAddress();
1866 if (!AddressOrErr) {
1867 consumeError(Err: AddressOrErr.takeError());
1868 break;
1869 }
1870 S.Address = *AddressOrErr;
1871 }
1872 S.TypeName = getNMTypeName(Obj, I: Sym);
1873 S.TypeChar = getNMSectionTagAndName(Obj, I: Sym, SecName&: S.SectionName);
1874
1875 raw_string_ostream OS(S.Name);
1876 if (Error E = Sym.printName(OS)) {
1877 if (MachO) {
1878 OS << "bad string index";
1879 consumeError(Err: std::move(E));
1880 } else
1881 error(E: std::move(E), FileName: Obj.getFileName());
1882 }
1883 if (!SymbolVersions.empty() && !SymbolVersions[I].Name.empty())
1884 S.Name +=
1885 (SymbolVersions[I].IsVerDef ? "@@" : "@") + SymbolVersions[I].Name;
1886
1887 S.Sym = Sym;
1888 if (S.initializeFlags(Obj))
1889 SymbolList.push_back(x: S);
1890 }
1891 }
1892
1893 // If this is a Mach-O file where the nlist symbol table is out of sync
1894 // with the dyld export trie then look through exports and fake up symbols
1895 // for the ones that are missing (also done with the -add-dyldinfo flag).
1896 // This is needed if strip(1) -T is run on a binary containing swift
1897 // language symbols for example. The option -only-dyldinfo will fake up
1898 // all symbols from the dyld export trie as well as the bind info.
1899 if (MachO && !NoDyldInfo)
1900 dumpSymbolsFromDLInfoMachO(MachO&: *MachO, SymbolList);
1901
1902 return true;
1903}
1904
1905static void printObjectLabel(bool PrintArchiveName, StringRef ArchiveName,
1906 StringRef ArchitectureName,
1907 StringRef ObjectFileName) {
1908 outs() << "\n";
1909 if (ArchiveName.empty() || !PrintArchiveName)
1910 outs() << ObjectFileName;
1911 else
1912 outs() << ArchiveName << "(" << ObjectFileName << ")";
1913 if (!ArchitectureName.empty())
1914 outs() << " (for architecture " << ArchitectureName << ")";
1915 outs() << ":\n";
1916}
1917
1918static Expected<bool> hasSymbols(SymbolicFile &Obj) {
1919 if (DynamicSyms) {
1920 Expected<SymbolicFile::basic_symbol_iterator_range> DynamicSymsOrErr =
1921 getDynamicSyms(Obj);
1922 if (!DynamicSymsOrErr)
1923 return DynamicSymsOrErr.takeError();
1924 return !DynamicSymsOrErr->empty();
1925 }
1926 return !Obj.symbols().empty();
1927}
1928
1929static void printSymbolNamesFromObject(
1930 SymbolicFile &Obj, std::vector<NMSymbol> &SymbolList,
1931 bool PrintSymbolObject, bool PrintObjectLabel, StringRef ArchiveName = {},
1932 StringRef ArchitectureName = {}, StringRef ObjectName = {},
1933 bool PrintArchiveName = true) {
1934
1935 if (PrintObjectLabel && !ExportSymbols)
1936 printObjectLabel(PrintArchiveName, ArchiveName, ArchitectureName,
1937 ObjectFileName: ObjectName.empty() ? Obj.getFileName() : ObjectName);
1938
1939 if (!getSymbolNamesFromObject(Obj, SymbolList) || ExportSymbols)
1940 return;
1941
1942 // If there is an error in hasSymbols(), the error should be encountered in
1943 // function getSymbolNamesFromObject first.
1944 if (!cantFail(ValOrErr: hasSymbols(Obj)) && SymbolList.empty() && !Quiet) {
1945 writeFileName(S&: errs(), ArchiveName, ArchitectureName);
1946 errs() << "no symbols\n";
1947 }
1948
1949 sortSymbolList(SymbolList);
1950 printSymbolList(Obj, SymbolList, printName: PrintSymbolObject, ArchiveName,
1951 ArchitectureName);
1952}
1953
1954static void dumpSymbolsNameFromMachOFilesetEntry(
1955 MachOObjectFile *Obj, std::vector<NMSymbol> &SymbolList,
1956 bool PrintSymbolObject, bool PrintObjectLabel) {
1957 auto Buf = Obj->getMemoryBufferRef();
1958 const auto *End = Obj->load_commands().end();
1959 for (const auto *It = Obj->load_commands().begin(); It != End; ++It) {
1960 const auto &Command = *It;
1961 if (Command.C.cmd != MachO::LC_FILESET_ENTRY)
1962 continue;
1963
1964 MachO::fileset_entry_command Entry =
1965 Obj->getFilesetEntryLoadCommand(L: Command);
1966 auto MaybeMachO =
1967 MachOObjectFile::createMachOObjectFile(Object: Buf, UniversalCputype: 0, UniversalIndex: 0, MachOFilesetEntryOffset: Entry.fileoff);
1968
1969 if (Error Err = MaybeMachO.takeError())
1970 report_fatal_error(Err: std::move(Err));
1971
1972 const char *EntryName = Command.Ptr + Entry.entry_id.offset;
1973 if (EntryName)
1974 outs() << "Symbols for " << EntryName << ": \n";
1975
1976 std::unique_ptr<MachOObjectFile> EntryMachO = std::move(MaybeMachO.get());
1977 printSymbolNamesFromObject(Obj&: *EntryMachO, SymbolList, PrintSymbolObject,
1978 PrintObjectLabel);
1979
1980 if (std::next(x: It) != End)
1981 outs() << "\n";
1982 }
1983}
1984
1985static void dumpSymbolNamesFromObject(
1986 SymbolicFile &Obj, std::vector<NMSymbol> &SymbolList,
1987 bool PrintSymbolObject, bool PrintObjectLabel, StringRef ArchiveName = {},
1988 StringRef ArchitectureName = {}, StringRef ObjectName = {},
1989 bool PrintArchiveName = true) {
1990 if (!shouldDump(Obj))
1991 return;
1992
1993 if (ExportSymbols && Obj.isXCOFF()) {
1994 XCOFFObjectFile *XCOFFObj = cast<XCOFFObjectFile>(Val: &Obj);
1995 getXCOFFExports(XCOFFObj, SymbolList, ArchiveName);
1996 return;
1997 }
1998
1999 CurrentFilename = Obj.getFileName();
2000
2001 // Are we handling a MachO of type MH_FILESET?
2002 if (Obj.isMachO() && Obj.is64Bit() &&
2003 cast<MachOObjectFile>(Val: &Obj)->getHeader64().filetype ==
2004 MachO::MH_FILESET) {
2005 dumpSymbolsNameFromMachOFilesetEntry(Obj: cast<MachOObjectFile>(Val: &Obj),
2006 SymbolList, PrintSymbolObject,
2007 PrintObjectLabel);
2008 return;
2009 }
2010
2011 printSymbolNamesFromObject(Obj, SymbolList, PrintSymbolObject,
2012 PrintObjectLabel, ArchiveName, ArchitectureName,
2013 ObjectName, PrintArchiveName);
2014}
2015
2016// checkMachOAndArchFlags() checks to see if the SymbolicFile is a Mach-O file
2017// and if it is and there is a list of architecture flags is specified then
2018// check to make sure this Mach-O file is one of those architectures or all
2019// architectures was specificed. If not then an error is generated and this
2020// routine returns false. Else it returns true.
2021static bool checkMachOAndArchFlags(SymbolicFile *O, StringRef Filename) {
2022 auto *MachO = dyn_cast<MachOObjectFile>(Val: O);
2023
2024 if (!MachO || ArchAll || ArchFlags.empty())
2025 return true;
2026
2027 MachO::mach_header H;
2028 MachO::mach_header_64 H_64;
2029 Triple T;
2030 const char *McpuDefault, *ArchFlag;
2031 if (MachO->is64Bit()) {
2032 H_64 = MachO->MachOObjectFile::getHeader64();
2033 T = MachOObjectFile::getArchTriple(CPUType: H_64.cputype, CPUSubType: H_64.cpusubtype,
2034 McpuDefault: &McpuDefault, ArchFlag: &ArchFlag);
2035 } else {
2036 H = MachO->MachOObjectFile::getHeader();
2037 T = MachOObjectFile::getArchTriple(CPUType: H.cputype, CPUSubType: H.cpusubtype,
2038 McpuDefault: &McpuDefault, ArchFlag: &ArchFlag);
2039 }
2040 const std::string ArchFlagName(ArchFlag);
2041 if (!llvm::is_contained(Range&: ArchFlags, Element: ArchFlagName)) {
2042 error(Message: "No architecture specified", Path: Filename);
2043 return false;
2044 }
2045 return true;
2046}
2047
2048static void printArchiveMap(iterator_range<Archive::symbol_iterator> &map,
2049 StringRef Filename) {
2050 for (auto I : map) {
2051 Expected<Archive::Child> C = I.getMember();
2052 if (!C) {
2053 error(E: C.takeError(), FileName: Filename);
2054 break;
2055 }
2056 Expected<StringRef> FileNameOrErr = C->getName();
2057 if (!FileNameOrErr) {
2058 error(E: FileNameOrErr.takeError(), FileName: Filename);
2059 break;
2060 }
2061 StringRef SymName = I.getName();
2062 outs() << SymName << " in " << FileNameOrErr.get() << "\n";
2063 }
2064
2065 outs() << "\n";
2066}
2067
2068static void dumpArchiveMap(Archive *A, StringRef Filename) {
2069 auto Map = A->symbols();
2070 if (!Map.empty()) {
2071 outs() << "Archive map\n";
2072 printArchiveMap(map&: Map, Filename);
2073 }
2074
2075 auto ECMap = A->ec_symbols();
2076 if (!ECMap) {
2077 warn(Err: ECMap.takeError(), FileName: Filename);
2078 } else if (!ECMap->empty()) {
2079 outs() << "Archive EC map\n";
2080 printArchiveMap(map&: *ECMap, Filename);
2081 }
2082}
2083
2084static void dumpArchive(Archive *A, std::vector<NMSymbol> &SymbolList,
2085 StringRef Filename, LLVMContext *ContextPtr) {
2086 if (ArchiveMap)
2087 dumpArchiveMap(A, Filename);
2088
2089 Error Err = Error::success();
2090 for (auto &C : A->children(Err)) {
2091 Expected<std::unique_ptr<Binary>> ChildOrErr = C.getAsBinary(Context: ContextPtr);
2092 if (!ChildOrErr) {
2093 if (auto E = isNotObjectErrorInvalidFileType(Err: ChildOrErr.takeError()))
2094 error(E: std::move(E), FileName: Filename, C);
2095 continue;
2096 }
2097 if (SymbolicFile *O = dyn_cast<SymbolicFile>(Val: &*ChildOrErr.get())) {
2098 if (!MachOPrintSizeWarning && PrintSize && isa<MachOObjectFile>(Val: O)) {
2099 WithColor::warning(OS&: errs(), Prefix: ToolName)
2100 << "sizes with -print-size for Mach-O files are always zero.\n";
2101 MachOPrintSizeWarning = true;
2102 }
2103 if (!checkMachOAndArchFlags(O, Filename))
2104 return;
2105 dumpSymbolNamesFromObject(Obj&: *O, SymbolList, /*PrintSymbolObject=*/false,
2106 PrintObjectLabel: !PrintFileName, ArchiveName: Filename,
2107 /*ArchitectureName=*/{}, ObjectName: O->getFileName(),
2108 /*PrintArchiveName=*/false);
2109 }
2110 }
2111 if (Err)
2112 error(E: std::move(Err), FileName: A->getFileName());
2113}
2114
2115static void dumpMachOUniversalBinaryMatchArchFlags(
2116 MachOUniversalBinary *UB, std::vector<NMSymbol> &SymbolList,
2117 StringRef Filename, LLVMContext *ContextPtr) {
2118 // Look for a slice in the universal binary that matches each ArchFlag.
2119 bool ArchFound;
2120 for (unsigned i = 0; i < ArchFlags.size(); ++i) {
2121 ArchFound = false;
2122 for (MachOUniversalBinary::object_iterator I = UB->begin_objects(),
2123 E = UB->end_objects();
2124 I != E; ++I) {
2125 if (ArchFlags[i] == I->getArchFlagName()) {
2126 ArchFound = true;
2127 Expected<std::unique_ptr<ObjectFile>> ObjOrErr = I->getAsObjectFile();
2128 std::string ArchiveName;
2129 std::string ArchitectureName;
2130 ArchiveName.clear();
2131 ArchitectureName.clear();
2132 if (ObjOrErr) {
2133 ObjectFile &Obj = *ObjOrErr.get();
2134 if (ArchFlags.size() > 1)
2135 ArchitectureName = I->getArchFlagName();
2136 dumpSymbolNamesFromObject(Obj, SymbolList,
2137 /*PrintSymbolObject=*/false,
2138 PrintObjectLabel: (ArchFlags.size() > 1) && !PrintFileName,
2139 ArchiveName, ArchitectureName);
2140 } else if (auto E =
2141 isNotObjectErrorInvalidFileType(Err: ObjOrErr.takeError())) {
2142 error(E: std::move(E), FileName: Filename,
2143 ArchitectureName: ArchFlags.size() > 1 ? StringRef(I->getArchFlagName())
2144 : StringRef());
2145 continue;
2146 } else if (Expected<std::unique_ptr<Archive>> AOrErr =
2147 I->getAsArchive()) {
2148 std::unique_ptr<Archive> &A = *AOrErr;
2149 Error Err = Error::success();
2150 for (auto &C : A->children(Err)) {
2151 Expected<std::unique_ptr<Binary>> ChildOrErr =
2152 C.getAsBinary(Context: ContextPtr);
2153 if (!ChildOrErr) {
2154 if (auto E =
2155 isNotObjectErrorInvalidFileType(Err: ChildOrErr.takeError())) {
2156 error(E: std::move(E), FileName: Filename, C,
2157 ArchitectureName: ArchFlags.size() > 1 ? StringRef(I->getArchFlagName())
2158 : StringRef());
2159 }
2160 continue;
2161 }
2162 if (SymbolicFile *O = dyn_cast<SymbolicFile>(Val: &*ChildOrErr.get())) {
2163 ArchiveName = std::string(A->getFileName());
2164 if (ArchFlags.size() > 1)
2165 ArchitectureName = I->getArchFlagName();
2166 dumpSymbolNamesFromObject(
2167 Obj&: *O, SymbolList, /*PrintSymbolObject=*/false, PrintObjectLabel: !PrintFileName,
2168 ArchiveName, ArchitectureName);
2169 }
2170 }
2171 if (Err)
2172 error(E: std::move(Err), FileName: A->getFileName());
2173 } else {
2174 consumeError(Err: AOrErr.takeError());
2175 error(Message: Filename + " for architecture " +
2176 StringRef(I->getArchFlagName()) +
2177 " is not a Mach-O file or an archive file",
2178 Path: "Mach-O universal file");
2179 }
2180 }
2181 }
2182 if (!ArchFound) {
2183 error(Message: ArchFlags[i],
2184 Path: "file: " + Filename + " does not contain architecture");
2185 return;
2186 }
2187 }
2188}
2189
2190// Returns true If the binary contains a slice that matches the host
2191// architecture, or false otherwise.
2192static bool dumpMachOUniversalBinaryMatchHost(MachOUniversalBinary *UB,
2193 std::vector<NMSymbol> &SymbolList,
2194 StringRef Filename,
2195 LLVMContext *ContextPtr) {
2196 Triple HostTriple = MachOObjectFile::getHostArch();
2197 StringRef HostArchName = HostTriple.getArchName();
2198 for (MachOUniversalBinary::object_iterator I = UB->begin_objects(),
2199 E = UB->end_objects();
2200 I != E; ++I) {
2201 if (HostArchName == I->getArchFlagName()) {
2202 Expected<std::unique_ptr<ObjectFile>> ObjOrErr = I->getAsObjectFile();
2203 std::string ArchiveName;
2204 if (ObjOrErr) {
2205 ObjectFile &Obj = *ObjOrErr.get();
2206 dumpSymbolNamesFromObject(Obj, SymbolList, /*PrintSymbolObject=*/false,
2207 /*PrintObjectLabel=*/false);
2208 } else if (auto E = isNotObjectErrorInvalidFileType(Err: ObjOrErr.takeError()))
2209 error(E: std::move(E), FileName: Filename);
2210 else if (Expected<std::unique_ptr<Archive>> AOrErr = I->getAsArchive()) {
2211 std::unique_ptr<Archive> &A = *AOrErr;
2212 Error Err = Error::success();
2213 for (auto &C : A->children(Err)) {
2214 Expected<std::unique_ptr<Binary>> ChildOrErr =
2215 C.getAsBinary(Context: ContextPtr);
2216 if (!ChildOrErr) {
2217 if (auto E =
2218 isNotObjectErrorInvalidFileType(Err: ChildOrErr.takeError()))
2219 error(E: std::move(E), FileName: Filename, C);
2220 continue;
2221 }
2222 if (SymbolicFile *O = dyn_cast<SymbolicFile>(Val: &*ChildOrErr.get())) {
2223 ArchiveName = std::string(A->getFileName());
2224 dumpSymbolNamesFromObject(Obj&: *O, SymbolList,
2225 /*PrintSymbolObject=*/false,
2226 PrintObjectLabel: !PrintFileName, ArchiveName);
2227 }
2228 }
2229 if (Err)
2230 error(E: std::move(Err), FileName: A->getFileName());
2231 } else {
2232 consumeError(Err: AOrErr.takeError());
2233 error(Message: Filename + " for architecture " +
2234 StringRef(I->getArchFlagName()) +
2235 " is not a Mach-O file or an archive file",
2236 Path: "Mach-O universal file");
2237 }
2238 return true;
2239 }
2240 }
2241 return false;
2242}
2243
2244static void dumpMachOUniversalBinaryArchAll(MachOUniversalBinary *UB,
2245 std::vector<NMSymbol> &SymbolList,
2246 StringRef Filename,
2247 LLVMContext *ContextPtr) {
2248 bool moreThanOneArch = UB->getNumberOfObjects() > 1;
2249 for (const MachOUniversalBinary::ObjectForArch &O : UB->objects()) {
2250 Expected<std::unique_ptr<ObjectFile>> ObjOrErr = O.getAsObjectFile();
2251 std::string ArchiveName;
2252 std::string ArchitectureName;
2253 ArchiveName.clear();
2254 ArchitectureName.clear();
2255 if (ObjOrErr) {
2256 ObjectFile &Obj = *ObjOrErr.get();
2257 if (isa<MachOObjectFile>(Val: Obj) && moreThanOneArch)
2258 ArchitectureName = O.getArchFlagName();
2259 dumpSymbolNamesFromObject(Obj, SymbolList, /*PrintSymbolObject=*/false,
2260 PrintObjectLabel: !PrintFileName, ArchiveName, ArchitectureName);
2261 } else if (auto E = isNotObjectErrorInvalidFileType(Err: ObjOrErr.takeError())) {
2262 error(E: std::move(E), FileName: Filename,
2263 ArchitectureName: moreThanOneArch ? StringRef(O.getArchFlagName()) : StringRef());
2264 continue;
2265 } else if (Expected<std::unique_ptr<Archive>> AOrErr = O.getAsArchive()) {
2266 std::unique_ptr<Archive> &A = *AOrErr;
2267 Error Err = Error::success();
2268 for (auto &C : A->children(Err)) {
2269 Expected<std::unique_ptr<Binary>> ChildOrErr =
2270 C.getAsBinary(Context: ContextPtr);
2271 if (!ChildOrErr) {
2272 if (auto E = isNotObjectErrorInvalidFileType(Err: ChildOrErr.takeError()))
2273 error(E: std::move(E), FileName: Filename, C,
2274 ArchitectureName: moreThanOneArch ? StringRef(ArchitectureName) : StringRef());
2275 continue;
2276 }
2277 if (SymbolicFile *F = dyn_cast<SymbolicFile>(Val: &*ChildOrErr.get())) {
2278 ArchiveName = std::string(A->getFileName());
2279 if (isa<MachOObjectFile>(Val: F) && moreThanOneArch)
2280 ArchitectureName = O.getArchFlagName();
2281 dumpSymbolNamesFromObject(Obj&: *F, SymbolList, /*PrintSymbolObject=*/false,
2282 PrintObjectLabel: !PrintFileName, ArchiveName,
2283 ArchitectureName);
2284 }
2285 }
2286 if (Err)
2287 error(E: std::move(Err), FileName: A->getFileName());
2288 } else {
2289 consumeError(Err: AOrErr.takeError());
2290 error(Message: Filename + " for architecture " + StringRef(O.getArchFlagName()) +
2291 " is not a Mach-O file or an archive file",
2292 Path: "Mach-O universal file");
2293 }
2294 }
2295}
2296
2297static void dumpMachOUniversalBinary(MachOUniversalBinary *UB,
2298 std::vector<NMSymbol> &SymbolList,
2299 StringRef Filename,
2300 LLVMContext *ContextPtr) {
2301 // If we have a list of architecture flags specified dump only those.
2302 if (!ArchAll && !ArchFlags.empty()) {
2303 dumpMachOUniversalBinaryMatchArchFlags(UB, SymbolList, Filename,
2304 ContextPtr);
2305 return;
2306 }
2307
2308 // No architecture flags were specified so if this contains a slice that
2309 // matches the host architecture dump only that.
2310 if (!ArchAll &&
2311 dumpMachOUniversalBinaryMatchHost(UB, SymbolList, Filename, ContextPtr))
2312 return;
2313
2314 // Either all architectures have been specified or none have been specified
2315 // and this does not contain the host architecture so dump all the slices.
2316 dumpMachOUniversalBinaryArchAll(UB, SymbolList, Filename, ContextPtr);
2317}
2318
2319static void dumpTapiUniversal(TapiUniversal *TU,
2320 std::vector<NMSymbol> &SymbolList,
2321 StringRef Filename) {
2322 for (const TapiUniversal::ObjectForArch &I : TU->objects()) {
2323 StringRef ArchName = I.getArchFlagName();
2324 const bool ShowArch =
2325 ArchFlags.empty() || llvm::is_contained(Range&: ArchFlags, Element: ArchName);
2326 if (!ShowArch)
2327 continue;
2328 if (!AddInlinedInfo && !I.isTopLevelLib())
2329 continue;
2330 if (auto ObjOrErr = I.getAsObjectFile())
2331 dumpSymbolNamesFromObject(
2332 Obj&: *ObjOrErr.get(), SymbolList, /*PrintSymbolObject=*/false,
2333 /*PrintObjectLabel=*/true,
2334 /*ArchiveName=*/{}, ArchitectureName: ArchName, ObjectName: I.getInstallName());
2335 else if (Error E = isNotObjectErrorInvalidFileType(Err: ObjOrErr.takeError())) {
2336 error(E: std::move(E), FileName: Filename, ArchitectureName: ArchName);
2337 }
2338 }
2339}
2340
2341static void dumpSymbolicFile(SymbolicFile *O, std::vector<NMSymbol> &SymbolList,
2342 StringRef Filename) {
2343 if (!MachOPrintSizeWarning && PrintSize && isa<MachOObjectFile>(Val: O)) {
2344 WithColor::warning(OS&: errs(), Prefix: ToolName)
2345 << "sizes with --print-size for Mach-O files are always zero.\n";
2346 MachOPrintSizeWarning = true;
2347 }
2348 if (!checkMachOAndArchFlags(O, Filename))
2349 return;
2350 dumpSymbolNamesFromObject(Obj&: *O, SymbolList, /*PrintSymbolObject=*/true,
2351 /*PrintObjectLabel=*/false);
2352}
2353
2354static std::vector<NMSymbol> dumpSymbolNamesFromFile(StringRef Filename) {
2355 std::vector<NMSymbol> SymbolList;
2356 ErrorOr<std::unique_ptr<MemoryBuffer>> BufferOrErr =
2357 MemoryBuffer::getFileOrSTDIN(Filename);
2358 if (error(EC: BufferOrErr.getError(), Path: Filename))
2359 return SymbolList;
2360
2361 // Ignore AIX linker import files (these files start with "#!"), when
2362 // exporting symbols.
2363 const char *BuffStart = (*BufferOrErr)->getBufferStart();
2364 size_t BufferSize = (*BufferOrErr)->getBufferSize();
2365 if (ExportSymbols && BufferSize >= 2 && BuffStart[0] == '#' &&
2366 BuffStart[1] == '!')
2367 return SymbolList;
2368
2369 LLVMContext Context;
2370 LLVMContext *ContextPtr = NoLLVMBitcode ? nullptr : &Context;
2371 Expected<std::unique_ptr<Binary>> BinaryOrErr =
2372 createBinary(Source: BufferOrErr.get()->getMemBufferRef(), Context: ContextPtr);
2373 if (!BinaryOrErr) {
2374 error(E: BinaryOrErr.takeError(), FileName: Filename);
2375 return SymbolList;
2376 }
2377 Binary &Bin = *BinaryOrErr.get();
2378 if (Archive *A = dyn_cast<Archive>(Val: &Bin))
2379 dumpArchive(A, SymbolList, Filename, ContextPtr);
2380 else if (MachOUniversalBinary *UB = dyn_cast<MachOUniversalBinary>(Val: &Bin))
2381 dumpMachOUniversalBinary(UB, SymbolList, Filename, ContextPtr);
2382 else if (TapiUniversal *TU = dyn_cast<TapiUniversal>(Val: &Bin))
2383 dumpTapiUniversal(TU, SymbolList, Filename);
2384 else if (SymbolicFile *O = dyn_cast<SymbolicFile>(Val: &Bin))
2385 dumpSymbolicFile(O, SymbolList, Filename);
2386 return SymbolList;
2387}
2388
2389static void
2390exportSymbolNamesFromFiles(const std::vector<std::string> &InputFilenames) {
2391 std::vector<NMSymbol> SymbolList;
2392 for (const auto &FileName : InputFilenames) {
2393 std::vector<NMSymbol> FileSymList = dumpSymbolNamesFromFile(Filename: FileName);
2394 llvm::append_range(C&: SymbolList, R&: FileSymList);
2395 }
2396
2397 // Delete symbols which should not be printed from SymolList.
2398 llvm::erase_if(C&: SymbolList,
2399 P: [](const NMSymbol &s) { return !s.shouldPrint(); });
2400 sortSymbolList(SymbolList);
2401 SymbolList.erase(first: llvm::unique(R&: SymbolList), last: SymbolList.end());
2402 printExportSymbolList(SymbolList);
2403}
2404
2405int llvm_nm_main(int argc, char **argv, const llvm::ToolContext &) {
2406 BumpPtrAllocator A;
2407 StringSaver Saver(A);
2408 NmOptTable Tbl;
2409 ToolName = argv[0];
2410 opt::InputArgList Args =
2411 Tbl.parseArgs(Argc: argc, Argv: argv, Unknown: OPT_UNKNOWN, Saver, ErrorFn: [&](StringRef Msg) {
2412 error(Message: Msg);
2413 exit(status: 1);
2414 });
2415 if (Args.hasArg(Ids: OPT_help)) {
2416 Tbl.printHelp(
2417 OS&: outs(),
2418 Usage: (Twine(ToolName) + " [options] <input object files>").str().c_str(),
2419 Title: "LLVM symbol table dumper");
2420 // TODO Replace this with OptTable API once it adds extrahelp support.
2421 outs() << "\nPass @FILE as argument to read options from FILE.\n";
2422 return 0;
2423 }
2424 if (Args.hasArg(Ids: OPT_version)) {
2425 // This needs to contain the word "GNU", libtool looks for that string.
2426 outs() << "llvm-nm, compatible with GNU nm" << '\n';
2427 cl::PrintVersionMessage();
2428 return 0;
2429 }
2430
2431 DebugSyms = Args.hasArg(Ids: OPT_debug_syms);
2432 DefinedOnly = Args.hasArg(Ids: OPT_defined_only);
2433 Demangle = Args.hasFlag(Pos: OPT_demangle, Neg: OPT_no_demangle, Default: false);
2434 DynamicSyms = Args.hasArg(Ids: OPT_dynamic);
2435 ExternalOnly = Args.hasArg(Ids: OPT_extern_only);
2436 StringRef V = Args.getLastArgValue(Id: OPT_format_EQ, Default: "bsd");
2437 if (V == "bsd")
2438 OutputFormat = bsd;
2439 else if (V == "posix")
2440 OutputFormat = posix;
2441 else if (V == "sysv")
2442 OutputFormat = sysv;
2443 else if (V == "darwin")
2444 OutputFormat = darwin;
2445 else if (V == "just-symbols")
2446 OutputFormat = just_symbols;
2447 else
2448 error(Message: "--format value should be one of: bsd, posix, sysv, darwin, "
2449 "just-symbols");
2450 LineNumbers = Args.hasArg(Ids: OPT_line_numbers);
2451 NoLLVMBitcode = Args.hasArg(Ids: OPT_no_llvm_bc);
2452 NoSort = Args.hasArg(Ids: OPT_no_sort);
2453 NoWeakSymbols = Args.hasArg(Ids: OPT_no_weak);
2454 NumericSort = Args.hasArg(Ids: OPT_numeric_sort);
2455 ArchiveMap = Args.hasArg(Ids: OPT_print_armap);
2456 PrintFileName = Args.hasArg(Ids: OPT_print_file_name);
2457 PrintSize = Args.hasArg(Ids: OPT_print_size);
2458 ReverseSort = Args.hasArg(Ids: OPT_reverse_sort);
2459 ExportSymbols = Args.hasArg(Ids: OPT_export_symbols);
2460 if (ExportSymbols) {
2461 ExternalOnly = true;
2462 DefinedOnly = true;
2463 }
2464
2465 Quiet = Args.hasArg(Ids: OPT_quiet);
2466 V = Args.getLastArgValue(Id: OPT_radix_EQ, Default: "x");
2467 if (V == "o")
2468 AddressRadix = Radix::o;
2469 else if (V == "d")
2470 AddressRadix = Radix::d;
2471 else if (V == "x")
2472 AddressRadix = Radix::x;
2473 else
2474 error(Message: "--radix value should be one of: 'o' (octal), 'd' (decimal), 'x' "
2475 "(hexadecimal)");
2476 SizeSort = Args.hasArg(Ids: OPT_size_sort);
2477 SpecialSyms = Args.hasArg(Ids: OPT_special_syms);
2478 UndefinedOnly = Args.hasArg(Ids: OPT_undefined_only);
2479 WithoutAliases = Args.hasArg(Ids: OPT_without_aliases);
2480
2481 // Get BitMode from enviornment variable "OBJECT_MODE" for AIX OS, if
2482 // specified.
2483 Triple HostTriple(sys::getProcessTriple());
2484 if (HostTriple.isOSAIX()) {
2485 BitMode = StringSwitch<BitModeTy>(getenv(name: "OBJECT_MODE"))
2486 .Case(S: "32", Value: BitModeTy::Bit32)
2487 .Case(S: "64", Value: BitModeTy::Bit64)
2488 .Case(S: "32_64", Value: BitModeTy::Bit32_64)
2489 .Case(S: "any", Value: BitModeTy::Any)
2490 .Default(Value: BitModeTy::Bit32);
2491 } else
2492 BitMode = BitModeTy::Any;
2493
2494 if (Arg *A = Args.getLastArg(Ids: OPT_X)) {
2495 StringRef Mode = A->getValue();
2496 if (Mode == "32")
2497 BitMode = BitModeTy::Bit32;
2498 else if (Mode == "64")
2499 BitMode = BitModeTy::Bit64;
2500 else if (Mode == "32_64")
2501 BitMode = BitModeTy::Bit32_64;
2502 else if (Mode == "any")
2503 BitMode = BitModeTy::Any;
2504 else
2505 error(Message: "-X value should be one of: 32, 64, 32_64, (default) any");
2506 }
2507
2508 // Mach-O specific options.
2509 FormatMachOasHex = Args.hasArg(Ids: OPT_x);
2510 AddDyldInfo = Args.hasArg(Ids: OPT_add_dyldinfo);
2511 AddInlinedInfo = Args.hasArg(Ids: OPT_add_inlinedinfo);
2512 DyldInfoOnly = Args.hasArg(Ids: OPT_dyldinfo_only);
2513 NoDyldInfo = Args.hasArg(Ids: OPT_no_dyldinfo);
2514
2515 // XCOFF specific options.
2516 NoRsrc = Args.hasArg(Ids: OPT_no_rsrc);
2517
2518 // llvm-nm only reads binary files.
2519 if (error(EC: sys::ChangeStdinToBinary()))
2520 return 1;
2521
2522 // These calls are needed so that we can read bitcode correctly.
2523 llvm::InitializeAllTargetInfos();
2524 llvm::InitializeAllTargetMCs();
2525 llvm::InitializeAllAsmParsers();
2526
2527 // The relative order of these is important. If you pass --size-sort it should
2528 // only print out the size. However, if you pass -S --size-sort, it should
2529 // print out both the size and address.
2530 if (SizeSort && !PrintSize)
2531 PrintAddress = false;
2532 if (OutputFormat == sysv || SizeSort)
2533 PrintSize = true;
2534
2535 for (const auto *A : Args.filtered(Ids: OPT_arch_EQ)) {
2536 SmallVector<StringRef, 2> Values;
2537 llvm::SplitString(Source: A->getValue(), OutFragments&: Values, Delimiters: ",");
2538 for (StringRef V : Values) {
2539 if (V == "all")
2540 ArchAll = true;
2541 else if (MachOObjectFile::isValidArch(ArchFlag: V))
2542 ArchFlags.push_back(x: V);
2543 else
2544 error(Message: "Unknown architecture named '" + V + "'",
2545 Path: "for the --arch option");
2546 }
2547 }
2548
2549 // Mach-O takes -s to accept two arguments. We emulate this by iterating over
2550 // both OPT_s and OPT_INPUT.
2551 std::vector<std::string> InputFilenames;
2552 int SegSectArgs = 0;
2553 for (opt::Arg *A : Args.filtered(Ids: OPT_s, Ids: OPT_INPUT)) {
2554 if (SegSectArgs > 0) {
2555 --SegSectArgs;
2556 SegSect.push_back(x: A->getValue());
2557 } else if (A->getOption().matches(ID: OPT_s)) {
2558 SegSectArgs = 2;
2559 } else {
2560 InputFilenames.push_back(x: A->getValue());
2561 }
2562 }
2563 if (!SegSect.empty() && SegSect.size() != 2)
2564 error(Message: "bad number of arguments (must be two arguments)",
2565 Path: "for the -s option");
2566
2567 if (InputFilenames.empty())
2568 InputFilenames.push_back(x: "a.out");
2569 if (InputFilenames.size() > 1)
2570 MultipleFiles = true;
2571
2572 if (NoDyldInfo && (AddDyldInfo || DyldInfoOnly))
2573 error(Message: "--no-dyldinfo can't be used with --add-dyldinfo or --dyldinfo-only");
2574
2575 if (ExportSymbols)
2576 exportSymbolNamesFromFiles(InputFilenames);
2577 else
2578 llvm::for_each(Range&: InputFilenames, F: dumpSymbolNamesFromFile);
2579
2580 if (HadError)
2581 return 1;
2582 return 0;
2583}
2584