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