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