Bug Summary

File:build/source/llvm/tools/llvm-nm/llvm-nm.cpp
Warning:line 344, column 9
Called C++ object pointer is null

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name llvm-nm.cpp -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -analyzer-config-compatibility-mode=true -mrelocation-model pic -pic-level 2 -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -ffunction-sections -fdata-sections -fcoverage-compilation-dir=/build/source/build-llvm/tools/clang/stage2-bins -resource-dir /usr/lib/llvm-17/lib/clang/17 -D _DEBUG -D _GLIBCXX_ASSERTIONS -D _GNU_SOURCE -D _LIBCPP_ENABLE_ASSERTIONS -D __STDC_CONSTANT_MACROS -D __STDC_FORMAT_MACROS -D __STDC_LIMIT_MACROS -I tools/llvm-nm -I /build/source/llvm/tools/llvm-nm -I include -I /build/source/llvm/include -D _FORTIFY_SOURCE=2 -D NDEBUG -U NDEBUG -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/x86_64-linux-gnu/c++/10 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/backward -internal-isystem /usr/lib/llvm-17/lib/clang/17/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/10/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -fmacro-prefix-map=/build/source/build-llvm/tools/clang/stage2-bins=build-llvm/tools/clang/stage2-bins -fmacro-prefix-map=/build/source/= -fcoverage-prefix-map=/build/source/build-llvm/tools/clang/stage2-bins=build-llvm/tools/clang/stage2-bins -fcoverage-prefix-map=/build/source/= -source-date-epoch 1683717183 -O2 -Wno-unused-command-line-argument -Wno-unused-parameter -Wwrite-strings -Wno-missing-field-initializers -Wno-long-long -Wno-maybe-uninitialized -Wno-class-memaccess -Wno-redundant-move -Wno-pessimizing-move -Wno-noexcept-type -Wno-comment -Wno-misleading-indentation -std=c++17 -fdeprecated-macro -fdebug-compilation-dir=/build/source/build-llvm/tools/clang/stage2-bins -fdebug-prefix-map=/build/source/build-llvm/tools/clang/stage2-bins=build-llvm/tools/clang/stage2-bins -fdebug-prefix-map=/build/source/= -ferror-limit 19 -fvisibility-inlines-hidden -stack-protector 2 -fgnuc-version=4.2.1 -fcolor-diagnostics -vectorize-loops -vectorize-slp -analyzer-output=html -analyzer-config stable-report-filename=true -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /tmp/scan-build-2023-05-10-133810-16478-1 -x c++ /build/source/llvm/tools/llvm-nm/llvm-nm.cpp
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/LLVMDriver.h"
44#include "llvm/Support/MemoryBuffer.h"
45#include "llvm/Support/Program.h"
46#include "llvm/Support/Signals.h"
47#include "llvm/Support/TargetSelect.h"
48#include "llvm/Support/WithColor.h"
49#include "llvm/Support/raw_ostream.h"
50#include "llvm/TargetParser/Host.h"
51#include "llvm/TargetParser/Triple.h"
52#include <vector>
53
54using namespace llvm;
55using namespace object;
56
57namespace {
58using namespace llvm::opt; // for HelpHidden in Opts.inc
59enum ID {
60 OPT_INVALID = 0, // This is not an option ID.
61#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \
62 HELPTEXT, METAVAR, VALUES) \
63 OPT_##ID,
64#include "Opts.inc"
65#undef OPTION
66};
67
68#define PREFIX(NAME, VALUE) \
69 static constexpr StringLiteral NAME##_init[] = VALUE; \
70 static constexpr ArrayRef<StringLiteral> NAME(NAME##_init, \
71 std::size(NAME##_init) - 1);
72#include "Opts.inc"
73#undef PREFIX
74
75static constexpr opt::OptTable::Info InfoTable[] = {
76#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \
77 HELPTEXT, METAVAR, VALUES) \
78 { \
79 PREFIX, NAME, HELPTEXT, \
80 METAVAR, OPT_##ID, opt::Option::KIND##Class, \
81 PARAM, FLAGS, OPT_##GROUP, \
82 OPT_##ALIAS, ALIASARGS, VALUES},
83#include "Opts.inc"
84#undef OPTION
85};
86
87class NmOptTable : public opt::GenericOptTable {
88public:
89 NmOptTable() : opt::GenericOptTable(InfoTable) {
90 setGroupedShortOptions(true);
91 }
92};
93
94enum OutputFormatTy { bsd, sysv, posix, darwin, just_symbols };
95enum class BitModeTy { Bit32, Bit64, Bit32_64, Any };
96} // namespace
97
98static bool ArchiveMap;
99static BitModeTy BitMode;
100static bool DebugSyms;
101static bool DefinedOnly;
102static bool Demangle;
103static bool DynamicSyms;
104static bool ExportSymbols;
105static bool ExternalOnly;
106static OutputFormatTy OutputFormat;
107static bool NoLLVMBitcode;
108static bool NoSort;
109static bool NoWeakSymbols;
110static bool NumericSort;
111static bool PrintFileName;
112static bool PrintSize;
113static bool Quiet;
114static bool ReverseSort;
115static bool SpecialSyms;
116static bool SizeSort;
117static bool UndefinedOnly;
118static bool WithoutAliases;
119
120// XCOFF-specific options.
121static bool NoRsrc;
122
123namespace {
124enum Radix { d, o, x };
125} // namespace
126static Radix AddressRadix;
127
128// Mach-O specific options.
129static bool ArchAll = false;
130static std::vector<StringRef> ArchFlags;
131static bool AddDyldInfo;
132static bool AddInlinedInfo;
133static bool DyldInfoOnly;
134static bool FormatMachOasHex;
135static bool NoDyldInfo;
136static std::vector<StringRef> SegSect;
137static bool MachOPrintSizeWarning = false;
138
139// Miscellaneous states.
140static bool PrintAddress = true;
141static bool MultipleFiles = false;
142static bool HadError = false;
143
144static StringRef ToolName;
145
146static void warn(Error Err, Twine FileName, Twine Context = Twine(),
147 Twine Archive = Twine()) {
148 assert(Err)(static_cast <bool> (Err) ? void (0) : __assert_fail ("Err"
, "llvm/tools/llvm-nm/llvm-nm.cpp", 148, __extension__ __PRETTY_FUNCTION__
))
;
149
150 // Flush the standard output so that the warning isn't interleaved with other
151 // output if stdout and stderr are writing to the same place.
152 outs().flush();
153
154 handleAllErrors(std::move(Err), [&](const ErrorInfoBase &EI) {
155 WithColor::warning(errs(), ToolName)
156 << (Archive.str().empty() ? FileName : Archive + "(" + FileName + ")")
157 << ": " << (Context.str().empty() ? "" : Context + ": ") << EI.message()
158 << "\n";
159 });
160}
161
162static void error(Twine Message, Twine Path = Twine()) {
163 HadError = true;
164 WithColor::error(errs(), ToolName) << Path << ": " << Message << "\n";
165}
166
167static bool error(std::error_code EC, Twine Path = Twine()) {
168 if (EC) {
169 error(EC.message(), Path);
170 return true;
171 }
172 return false;
173}
174
175// This version of error() prints the archive name and member name, for example:
176// "libx.a(foo.o)" after the ToolName before the error message. It sets
177// HadError but returns allowing the code to move on to other archive members.
178static void error(llvm::Error E, StringRef FileName, const Archive::Child &C,
179 StringRef ArchitectureName = StringRef()) {
180 HadError = true;
181 WithColor::error(errs(), ToolName) << FileName;
182
183 Expected<StringRef> NameOrErr = C.getName();
184 // TODO: if we have a error getting the name then it would be nice to print
185 // the index of which archive member this is and or its offset in the
186 // archive instead of "???" as the name.
187 if (!NameOrErr) {
188 consumeError(NameOrErr.takeError());
189 errs() << "(" << "???" << ")";
190 } else
191 errs() << "(" << NameOrErr.get() << ")";
192
193 if (!ArchitectureName.empty())
194 errs() << " (for architecture " << ArchitectureName << ")";
195
196 std::string Buf;
197 raw_string_ostream OS(Buf);
198 logAllUnhandledErrors(std::move(E), OS);
199 OS.flush();
200 errs() << ": " << Buf << "\n";
201}
202
203// This version of error() prints the file name and which architecture slice it
204// is from, for example: "foo.o (for architecture i386)" after the ToolName
205// before the error message. It sets HadError but returns allowing the code to
206// move on to other architecture slices.
207static void error(llvm::Error E, StringRef FileName,
208 StringRef ArchitectureName = StringRef()) {
209 HadError = true;
210 WithColor::error(errs(), ToolName) << FileName;
211
212 if (!ArchitectureName.empty())
213 errs() << " (for architecture " << ArchitectureName << ")";
214
215 std::string Buf;
216 raw_string_ostream OS(Buf);
217 logAllUnhandledErrors(std::move(E), OS);
218 OS.flush();
219 errs() << ": " << Buf << "\n";
220}
221
222namespace {
223struct NMSymbol {
224 uint64_t Address;
225 uint64_t Size;
226 char TypeChar;
227 std::string Name;
228 StringRef SectionName;
229 StringRef TypeName;
230 BasicSymbolRef Sym;
231 StringRef Visibility;
232
233 // The Sym field above points to the native symbol in the object file,
234 // for Mach-O when we are creating symbols from the dyld info the above
235 // pointer is null as there is no native symbol. In these cases the fields
236 // below are filled in to represent what would have been a Mach-O nlist
237 // native symbol.
238 uint32_t SymFlags;
239 SectionRef Section;
240 uint8_t NType;
241 uint8_t NSect;
242 uint16_t NDesc;
243 std::string IndirectName;
244
245 bool isDefined() const {
246 if (Sym.getRawDataRefImpl().p) {
247 uint32_t Flags = cantFail(Sym.getFlags());
248 return !(Flags & SymbolRef::SF_Undefined);
249 }
250 return TypeChar != 'U';
251 }
252
253 bool initializeFlags(const SymbolicFile &Obj) {
254 Expected<uint32_t> SymFlagsOrErr = Sym.getFlags();
255 if (!SymFlagsOrErr) {
256 // TODO: Test this error.
257 error(SymFlagsOrErr.takeError(), Obj.getFileName());
258 return false;
259 }
260 SymFlags = *SymFlagsOrErr;
261 return true;
262 }
263
264 bool shouldPrint() const {
265 bool Undefined = SymFlags & SymbolRef::SF_Undefined;
266 bool Global = SymFlags & SymbolRef::SF_Global;
267 bool Weak = SymFlags & SymbolRef::SF_Weak;
268 bool FormatSpecific = SymFlags & SymbolRef::SF_FormatSpecific;
269 if ((!Undefined && UndefinedOnly) || (Undefined && DefinedOnly) ||
270 (!Global && ExternalOnly) || (Weak && NoWeakSymbols) ||
271 (FormatSpecific && !(SpecialSyms || DebugSyms)))
272 return false;
273 return true;
274 }
275};
276
277bool operator<(const NMSymbol &A, const NMSymbol &B) {
278 if (NumericSort)
279 return std::make_tuple(A.isDefined(), A.Address, A.Name, A.Size) <
280 std::make_tuple(B.isDefined(), B.Address, B.Name, B.Size);
281 if (SizeSort)
282 return std::make_tuple(A.Size, A.Name, A.Address) <
283 std::make_tuple(B.Size, B.Name, B.Address);
284 if (ExportSymbols)
285 return std::make_tuple(A.Name, A.Visibility) <
286 std::make_tuple(B.Name, B.Visibility);
287 return std::make_tuple(A.Name, A.Size, A.Address) <
288 std::make_tuple(B.Name, B.Size, B.Address);
289}
290
291bool operator>(const NMSymbol &A, const NMSymbol &B) { return B < A; }
292bool operator==(const NMSymbol &A, const NMSymbol &B) {
293 return !(A < B) && !(B < A);
294}
295} // anonymous namespace
296
297static StringRef CurrentFilename;
298
299static char getSymbolNMTypeChar(IRObjectFile &Obj, basic_symbol_iterator I);
300
301// darwinPrintSymbol() is used to print a symbol from a Mach-O file when the
302// the OutputFormat is darwin or we are printing Mach-O symbols in hex. For
303// the darwin format it produces the same output as darwin's nm(1) -m output
304// and when printing Mach-O symbols in hex it produces the same output as
305// darwin's nm(1) -x format.
306static void darwinPrintSymbol(SymbolicFile &Obj, const NMSymbol &S,
307 char *SymbolAddrStr, const char *printBlanks,
308 const char *printDashes,
309 const char *printFormat) {
310 MachO::mach_header H;
311 MachO::mach_header_64 H_64;
312 uint32_t Filetype = MachO::MH_OBJECT;
313 uint32_t Flags = 0;
314 uint8_t NType = 0;
315 uint8_t NSect = 0;
316 uint16_t NDesc = 0;
317 uint32_t NStrx = 0;
318 uint64_t NValue = 0;
319 MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(&Obj);
1
Assuming the object is not a 'CastReturnType'
2
'MachO' initialized to a null pointer value
320 if (Obj.isIR()) {
3
Taking false branch
321 uint32_t SymFlags = cantFail(S.Sym.getFlags());
322 if (SymFlags & SymbolRef::SF_Global)
323 NType |= MachO::N_EXT;
324 if (SymFlags & SymbolRef::SF_Hidden)
325 NType |= MachO::N_PEXT;
326 if (SymFlags & SymbolRef::SF_Undefined)
327 NType |= MachO::N_EXT | MachO::N_UNDF;
328 else {
329 // Here we have a symbol definition. So to fake out a section name we
330 // use 1, 2 and 3 for section numbers. See below where they are used to
331 // print out fake section names.
332 NType |= MachO::N_SECT;
333 if (SymFlags & SymbolRef::SF_Const)
334 NSect = 3;
335 else if (SymFlags & SymbolRef::SF_Executable)
336 NSect = 1;
337 else
338 NSect = 2;
339 }
340 if (SymFlags & SymbolRef::SF_Weak)
341 NDesc |= MachO::N_WEAK_DEF;
342 } else {
343 DataRefImpl SymDRI = S.Sym.getRawDataRefImpl();
344 if (MachO->is64Bit()) {
4
Called C++ object pointer is null
345 H_64 = MachO->MachOObjectFile::getHeader64();
346 Filetype = H_64.filetype;
347 Flags = H_64.flags;
348 if (SymDRI.p){
349 MachO::nlist_64 STE_64 = MachO->getSymbol64TableEntry(SymDRI);
350 NType = STE_64.n_type;
351 NSect = STE_64.n_sect;
352 NDesc = STE_64.n_desc;
353 NStrx = STE_64.n_strx;
354 NValue = STE_64.n_value;
355 } else {
356 NType = S.NType;
357 NSect = S.NSect;
358 NDesc = S.NDesc;
359 NStrx = 0;
360 NValue = S.Address;
361 }
362 } else {
363 H = MachO->MachOObjectFile::getHeader();
364 Filetype = H.filetype;
365 Flags = H.flags;
366 if (SymDRI.p){
367 MachO::nlist STE = MachO->getSymbolTableEntry(SymDRI);
368 NType = STE.n_type;
369 NSect = STE.n_sect;
370 NDesc = STE.n_desc;
371 NStrx = STE.n_strx;
372 NValue = STE.n_value;
373 } else {
374 NType = S.NType;
375 NSect = S.NSect;
376 NDesc = S.NDesc;
377 NStrx = 0;
378 NValue = S.Address;
379 }
380 }
381 }
382
383 // If we are printing Mach-O symbols in hex do that and return.
384 if (FormatMachOasHex) {
385 outs() << format(printFormat, NValue) << ' '
386 << format("%02x %02x %04x %08x", NType, NSect, NDesc, NStrx) << ' '
387 << S.Name;
388 if ((NType & MachO::N_TYPE) == MachO::N_INDR) {
389 outs() << " (indirect for ";
390 outs() << format(printFormat, NValue) << ' ';
391 StringRef IndirectName;
392 if (S.Sym.getRawDataRefImpl().p) {
393 if (MachO->getIndirectName(S.Sym.getRawDataRefImpl(), IndirectName))
394 outs() << "?)";
395 else
396 outs() << IndirectName << ")";
397 } else
398 outs() << S.IndirectName << ")";
399 }
400 outs() << "\n";
401 return;
402 }
403
404 if (PrintAddress) {
405 if ((NType & MachO::N_TYPE) == MachO::N_INDR)
406 strcpy(SymbolAddrStr, printBlanks);
407 if (Obj.isIR() && (NType & MachO::N_TYPE) == MachO::N_TYPE)
408 strcpy(SymbolAddrStr, printDashes);
409 outs() << SymbolAddrStr << ' ';
410 }
411
412 switch (NType & MachO::N_TYPE) {
413 case MachO::N_UNDF:
414 if (NValue != 0) {
415 outs() << "(common) ";
416 if (MachO::GET_COMM_ALIGN(NDesc) != 0)
417 outs() << "(alignment 2^" << (int)MachO::GET_COMM_ALIGN(NDesc) << ") ";
418 } else {
419 if ((NType & MachO::N_TYPE) == MachO::N_PBUD)
420 outs() << "(prebound ";
421 else
422 outs() << "(";
423 if ((NDesc & MachO::REFERENCE_TYPE) ==
424 MachO::REFERENCE_FLAG_UNDEFINED_LAZY)
425 outs() << "undefined [lazy bound]) ";
426 else if ((NDesc & MachO::REFERENCE_TYPE) ==
427 MachO::REFERENCE_FLAG_PRIVATE_UNDEFINED_LAZY)
428 outs() << "undefined [private lazy bound]) ";
429 else if ((NDesc & MachO::REFERENCE_TYPE) ==
430 MachO::REFERENCE_FLAG_PRIVATE_UNDEFINED_NON_LAZY)
431 outs() << "undefined [private]) ";
432 else
433 outs() << "undefined) ";
434 }
435 break;
436 case MachO::N_ABS:
437 outs() << "(absolute) ";
438 break;
439 case MachO::N_INDR:
440 outs() << "(indirect) ";
441 break;
442 case MachO::N_SECT: {
443 if (Obj.isIR()) {
444 // For llvm bitcode files print out a fake section name using the values
445 // use 1, 2 and 3 for section numbers as set above.
446 if (NSect == 1)
447 outs() << "(LTO,CODE) ";
448 else if (NSect == 2)
449 outs() << "(LTO,DATA) ";
450 else if (NSect == 3)
451 outs() << "(LTO,RODATA) ";
452 else
453 outs() << "(?,?) ";
454 break;
455 }
456 section_iterator Sec = SectionRef();
457 if (S.Sym.getRawDataRefImpl().p) {
458 Expected<section_iterator> SecOrErr =
459 MachO->getSymbolSection(S.Sym.getRawDataRefImpl());
460 if (!SecOrErr) {
461 consumeError(SecOrErr.takeError());
462 outs() << "(?,?) ";
463 break;
464 }
465 Sec = *SecOrErr;
466 if (Sec == MachO->section_end()) {
467 outs() << "(?,?) ";
468 break;
469 }
470 } else {
471 Sec = S.Section;
472 }
473 DataRefImpl Ref = Sec->getRawDataRefImpl();
474 StringRef SectionName;
475 if (Expected<StringRef> NameOrErr = MachO->getSectionName(Ref))
476 SectionName = *NameOrErr;
477 StringRef SegmentName = MachO->getSectionFinalSegmentName(Ref);
478 outs() << "(" << SegmentName << "," << SectionName << ") ";
479 break;
480 }
481 default:
482 outs() << "(?) ";
483 break;
484 }
485
486 if (NType & MachO::N_EXT) {
487 if (NDesc & MachO::REFERENCED_DYNAMICALLY)
488 outs() << "[referenced dynamically] ";
489 if (NType & MachO::N_PEXT) {
490 if ((NDesc & MachO::N_WEAK_DEF) == MachO::N_WEAK_DEF)
491 outs() << "weak private external ";
492 else
493 outs() << "private external ";
494 } else {
495 if ((NDesc & MachO::N_WEAK_REF) == MachO::N_WEAK_REF ||
496 (NDesc & MachO::N_WEAK_DEF) == MachO::N_WEAK_DEF) {
497 if ((NDesc & (MachO::N_WEAK_REF | MachO::N_WEAK_DEF)) ==
498 (MachO::N_WEAK_REF | MachO::N_WEAK_DEF))
499 outs() << "weak external automatically hidden ";
500 else
501 outs() << "weak external ";
502 } else
503 outs() << "external ";
504 }
505 } else {
506 if (NType & MachO::N_PEXT)
507 outs() << "non-external (was a private external) ";
508 else
509 outs() << "non-external ";
510 }
511
512 if (Filetype == MachO::MH_OBJECT) {
513 if (NDesc & MachO::N_NO_DEAD_STRIP)
514 outs() << "[no dead strip] ";
515 if ((NType & MachO::N_TYPE) != MachO::N_UNDF &&
516 NDesc & MachO::N_SYMBOL_RESOLVER)
517 outs() << "[symbol resolver] ";
518 if ((NType & MachO::N_TYPE) != MachO::N_UNDF && NDesc & MachO::N_ALT_ENTRY)
519 outs() << "[alt entry] ";
520 if ((NType & MachO::N_TYPE) != MachO::N_UNDF && NDesc & MachO::N_COLD_FUNC)
521 outs() << "[cold func] ";
522 }
523
524 if ((NDesc & MachO::N_ARM_THUMB_DEF) == MachO::N_ARM_THUMB_DEF)
525 outs() << "[Thumb] ";
526
527 if ((NType & MachO::N_TYPE) == MachO::N_INDR) {
528 outs() << S.Name << " (for ";
529 StringRef IndirectName;
530 if (MachO) {
531 if (S.Sym.getRawDataRefImpl().p) {
532 if (MachO->getIndirectName(S.Sym.getRawDataRefImpl(), IndirectName))
533 outs() << "?)";
534 else
535 outs() << IndirectName << ")";
536 } else
537 outs() << S.IndirectName << ")";
538 } else
539 outs() << "?)";
540 } else
541 outs() << S.Name;
542
543 if ((Flags & MachO::MH_TWOLEVEL) == MachO::MH_TWOLEVEL &&
544 (((NType & MachO::N_TYPE) == MachO::N_UNDF && NValue == 0) ||
545 (NType & MachO::N_TYPE) == MachO::N_PBUD)) {
546 uint32_t LibraryOrdinal = MachO::GET_LIBRARY_ORDINAL(NDesc);
547 if (LibraryOrdinal != 0) {
548 if (LibraryOrdinal == MachO::EXECUTABLE_ORDINAL)
549 outs() << " (from executable)";
550 else if (LibraryOrdinal == MachO::DYNAMIC_LOOKUP_ORDINAL)
551 outs() << " (dynamically looked up)";
552 else {
553 StringRef LibraryName;
554 if (!MachO ||
555 MachO->getLibraryShortNameByIndex(LibraryOrdinal - 1, LibraryName))
556 outs() << " (from bad library ordinal " << LibraryOrdinal << ")";
557 else
558 outs() << " (from " << LibraryName << ")";
559 }
560 }
561 }
562
563 outs() << "\n";
564}
565
566// Table that maps Darwin's Mach-O stab constants to strings to allow printing.
567struct DarwinStabName {
568 uint8_t NType;
569 const char *Name;
570};
571const struct DarwinStabName DarwinStabNames[] = {
572 {MachO::N_GSYM, "GSYM"},
573 {MachO::N_FNAME, "FNAME"},
574 {MachO::N_FUN, "FUN"},
575 {MachO::N_STSYM, "STSYM"},
576 {MachO::N_LCSYM, "LCSYM"},
577 {MachO::N_BNSYM, "BNSYM"},
578 {MachO::N_PC, "PC"},
579 {MachO::N_AST, "AST"},
580 {MachO::N_OPT, "OPT"},
581 {MachO::N_RSYM, "RSYM"},
582 {MachO::N_SLINE, "SLINE"},
583 {MachO::N_ENSYM, "ENSYM"},
584 {MachO::N_SSYM, "SSYM"},
585 {MachO::N_SO, "SO"},
586 {MachO::N_OSO, "OSO"},
587 {MachO::N_LSYM, "LSYM"},
588 {MachO::N_BINCL, "BINCL"},
589 {MachO::N_SOL, "SOL"},
590 {MachO::N_PARAMS, "PARAM"},
591 {MachO::N_VERSION, "VERS"},
592 {MachO::N_OLEVEL, "OLEV"},
593 {MachO::N_PSYM, "PSYM"},
594 {MachO::N_EINCL, "EINCL"},
595 {MachO::N_ENTRY, "ENTRY"},
596 {MachO::N_LBRAC, "LBRAC"},
597 {MachO::N_EXCL, "EXCL"},
598 {MachO::N_RBRAC, "RBRAC"},
599 {MachO::N_BCOMM, "BCOMM"},
600 {MachO::N_ECOMM, "ECOMM"},
601 {MachO::N_ECOML, "ECOML"},
602 {MachO::N_LENG, "LENG"},
603};
604
605static const char *getDarwinStabString(uint8_t NType) {
606 for (auto I : ArrayRef(DarwinStabNames))
607 if (I.NType == NType)
608 return I.Name;
609 return nullptr;
610}
611
612// darwinPrintStab() prints the n_sect, n_desc along with a symbolic name of
613// a stab n_type value in a Mach-O file.
614static void darwinPrintStab(MachOObjectFile *MachO, const NMSymbol &S) {
615 MachO::nlist_64 STE_64;
616 MachO::nlist STE;
617 uint8_t NType;
618 uint8_t NSect;
619 uint16_t NDesc;
620 DataRefImpl SymDRI = S.Sym.getRawDataRefImpl();
621 if (MachO->is64Bit()) {
622 STE_64 = MachO->getSymbol64TableEntry(SymDRI);
623 NType = STE_64.n_type;
624 NSect = STE_64.n_sect;
625 NDesc = STE_64.n_desc;
626 } else {
627 STE = MachO->getSymbolTableEntry(SymDRI);
628 NType = STE.n_type;
629 NSect = STE.n_sect;
630 NDesc = STE.n_desc;
631 }
632
633 outs() << format(" %02x %04x ", NSect, NDesc);
634 if (const char *stabString = getDarwinStabString(NType))
635 outs() << format("%5.5s", stabString);
636 else
637 outs() << format(" %02x", NType);
638}
639
640static std::optional<std::string> demangle(StringRef Name) {
641 std::string Demangled;
642 if (nonMicrosoftDemangle(Name.str().c_str(), Demangled))
643 return Demangled;
644 return std::nullopt;
645}
646
647static std::optional<std::string> demangleXCOFF(StringRef Name) {
648 if (Name.empty() || Name[0] != '.')
649 return demangle(Name);
650
651 Name = Name.drop_front();
652 std::optional<std::string> DemangledName = demangle(Name);
653 if (DemangledName)
654 return "." + *DemangledName;
655 return std::nullopt;
656}
657
658static std::optional<std::string> demangleMachO(StringRef Name) {
659 if (!Name.empty() && Name[0] == '_')
660 Name = Name.drop_front();
661 return demangle(Name);
662}
663
664static bool symbolIsDefined(const NMSymbol &Sym) {
665 return Sym.TypeChar != 'U' && Sym.TypeChar != 'w' && Sym.TypeChar != 'v';
666}
667
668static void writeFileName(raw_ostream &S, StringRef ArchiveName,
669 StringRef ArchitectureName) {
670 if (!ArchitectureName.empty())
671 S << "(for architecture " << ArchitectureName << "):";
672 if (OutputFormat == posix && !ArchiveName.empty())
673 S << ArchiveName << "[" << CurrentFilename << "]: ";
674 else {
675 if (!ArchiveName.empty())
676 S << ArchiveName << ":";
677 S << CurrentFilename << ": ";
678 }
679}
680
681static void sortSymbolList(std::vector<NMSymbol> &SymbolList) {
682 if (NoSort)
683 return;
684
685 if (ReverseSort)
686 llvm::sort(SymbolList, std::greater<>());
687 else
688 llvm::sort(SymbolList);
689}
690
691static void printExportSymbolList(const std::vector<NMSymbol> &SymbolList) {
692 for (const NMSymbol &Sym : SymbolList) {
693 outs() << Sym.Name;
694 if (!Sym.Visibility.empty())
695 outs() << ' ' << Sym.Visibility;
696 outs() << '\n';
697 }
698}
699
700static void printSymbolList(SymbolicFile &Obj,
701 std::vector<NMSymbol> &SymbolList, bool printName,
702 StringRef ArchiveName, StringRef ArchitectureName) {
703 if (!PrintFileName) {
704 if ((OutputFormat == bsd || OutputFormat == posix ||
705 OutputFormat == just_symbols) &&
706 MultipleFiles && printName) {
707 outs() << '\n' << CurrentFilename << ":\n";
708 } else if (OutputFormat == sysv) {
709 outs() << "\n\nSymbols from " << CurrentFilename << ":\n\n";
710 if (Obj.is64Bit())
711 outs() << "Name Value Class Type"
712 << " Size Line Section\n";
713 else
714 outs() << "Name Value Class Type"
715 << " Size Line Section\n";
716 }
717 }
718
719 const char *printBlanks, *printDashes, *printFormat;
720 if (Obj.is64Bit()) {
721 printBlanks = " ";
722 printDashes = "----------------";
723 switch (AddressRadix) {
724 case Radix::o:
725 printFormat = OutputFormat == posix ? "%" PRIo64"l" "o" : "%016" PRIo64"l" "o";
726 break;
727 case Radix::x:
728 printFormat = OutputFormat == posix ? "%" PRIx64"l" "x" : "%016" PRIx64"l" "x";
729 break;
730 default:
731 printFormat = OutputFormat == posix ? "%" PRId64"l" "d" : "%016" PRId64"l" "d";
732 }
733 } else {
734 printBlanks = " ";
735 printDashes = "--------";
736 switch (AddressRadix) {
737 case Radix::o:
738 printFormat = OutputFormat == posix ? "%" PRIo64"l" "o" : "%08" PRIo64"l" "o";
739 break;
740 case Radix::x:
741 printFormat = OutputFormat == posix ? "%" PRIx64"l" "x" : "%08" PRIx64"l" "x";
742 break;
743 default:
744 printFormat = OutputFormat == posix ? "%" PRId64"l" "d" : "%08" PRId64"l" "d";
745 }
746 }
747
748 for (const NMSymbol &S : SymbolList) {
749 if (!S.shouldPrint())
750 continue;
751
752 std::string Name = S.Name;
753 MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(&Obj);
754 if (Demangle) {
755 function_ref<std::optional<std::string>(StringRef)> Fn = ::demangle;
756 if (Obj.isXCOFF())
757 Fn = demangleXCOFF;
758 if (Obj.isMachO())
759 Fn = demangleMachO;
760 if (std::optional<std::string> Opt = Fn(S.Name))
761 Name = *Opt;
762 }
763
764 if (PrintFileName)
765 writeFileName(outs(), ArchiveName, ArchitectureName);
766 if ((OutputFormat == just_symbols ||
767 (UndefinedOnly && MachO && OutputFormat != darwin)) &&
768 OutputFormat != posix) {
769 outs() << Name << "\n";
770 continue;
771 }
772
773 char SymbolAddrStr[23], SymbolSizeStr[23];
774
775 // If the format is SysV or the symbol isn't defined, then print spaces.
776 if (OutputFormat == sysv || !symbolIsDefined(S)) {
777 if (OutputFormat == posix) {
778 format(printFormat, S.Address)
779 .print(SymbolAddrStr, sizeof(SymbolAddrStr));
780 format(printFormat, S.Size).print(SymbolSizeStr, sizeof(SymbolSizeStr));
781 } else {
782 strcpy(SymbolAddrStr, printBlanks);
783 strcpy(SymbolSizeStr, printBlanks);
784 }
785 }
786
787 if (symbolIsDefined(S)) {
788 // Otherwise, print the symbol address and size.
789 if (Obj.isIR())
790 strcpy(SymbolAddrStr, printDashes);
791 else if (MachO && S.TypeChar == 'I')
792 strcpy(SymbolAddrStr, printBlanks);
793 else
794 format(printFormat, S.Address)
795 .print(SymbolAddrStr, sizeof(SymbolAddrStr));
796 format(printFormat, S.Size).print(SymbolSizeStr, sizeof(SymbolSizeStr));
797 }
798
799 // If OutputFormat is darwin or we are printing Mach-O symbols in hex and
800 // we have a MachOObjectFile, call darwinPrintSymbol to print as darwin's
801 // nm(1) -m output or hex, else if OutputFormat is darwin or we are
802 // printing Mach-O symbols in hex and not a Mach-O object fall back to
803 // OutputFormat bsd (see below).
804 if ((OutputFormat == darwin || FormatMachOasHex) && (MachO || Obj.isIR())) {
805 darwinPrintSymbol(Obj, S, SymbolAddrStr, printBlanks, printDashes,
806 printFormat);
807 } else if (OutputFormat == posix) {
808 outs() << Name << " " << S.TypeChar << " " << SymbolAddrStr << " "
809 << (MachO ? "0" : SymbolSizeStr) << "\n";
810 } else if (OutputFormat == bsd || (OutputFormat == darwin && !MachO)) {
811 if (PrintAddress)
812 outs() << SymbolAddrStr << ' ';
813 if (PrintSize)
814 outs() << SymbolSizeStr << ' ';
815 outs() << S.TypeChar;
816 if (S.TypeChar == '-' && MachO)
817 darwinPrintStab(MachO, S);
818 outs() << " " << Name;
819 if (S.TypeChar == 'I' && MachO) {
820 outs() << " (indirect for ";
821 if (S.Sym.getRawDataRefImpl().p) {
822 StringRef IndirectName;
823 if (MachO->getIndirectName(S.Sym.getRawDataRefImpl(), IndirectName))
824 outs() << "?)";
825 else
826 outs() << IndirectName << ")";
827 } else
828 outs() << S.IndirectName << ")";
829 }
830 outs() << "\n";
831 } else if (OutputFormat == sysv) {
832 outs() << left_justify(Name, 20) << "|" << SymbolAddrStr << "| "
833 << S.TypeChar << " |" << right_justify(S.TypeName, 18) << "|"
834 << SymbolSizeStr << "| |" << S.SectionName << "\n";
835 }
836 }
837
838 SymbolList.clear();
839}
840
841static char getSymbolNMTypeChar(ELFObjectFileBase &Obj,
842 basic_symbol_iterator I) {
843 // OK, this is ELF
844 elf_symbol_iterator SymI(I);
845
846 Expected<elf_section_iterator> SecIOrErr = SymI->getSection();
847 if (!SecIOrErr) {
848 consumeError(SecIOrErr.takeError());
849 return '?';
850 }
851
852 uint8_t Binding = SymI->getBinding();
853 if (Binding == ELF::STB_GNU_UNIQUE)
854 return 'u';
855
856 assert(Binding != ELF::STB_WEAK && "STB_WEAK not tested in calling function")(static_cast <bool> (Binding != ELF::STB_WEAK &&
"STB_WEAK not tested in calling function") ? void (0) : __assert_fail
("Binding != ELF::STB_WEAK && \"STB_WEAK not tested in calling function\""
, "llvm/tools/llvm-nm/llvm-nm.cpp", 856, __extension__ __PRETTY_FUNCTION__
))
;
857 if (Binding != ELF::STB_GLOBAL && Binding != ELF::STB_LOCAL)
858 return '?';
859
860 elf_section_iterator SecI = *SecIOrErr;
861 if (SecI != Obj.section_end()) {
862 uint32_t Type = SecI->getType();
863 uint64_t Flags = SecI->getFlags();
864 if (Flags & ELF::SHF_EXECINSTR)
865 return 't';
866 if (Type == ELF::SHT_NOBITS)
867 return 'b';
868 if (Flags & ELF::SHF_ALLOC)
869 return Flags & ELF::SHF_WRITE ? 'd' : 'r';
870
871 auto NameOrErr = SecI->getName();
872 if (!NameOrErr) {
873 consumeError(NameOrErr.takeError());
874 return '?';
875 }
876 if ((*NameOrErr).startswith(".debug"))
877 return 'N';
878 if (!(Flags & ELF::SHF_WRITE))
879 return 'n';
880 }
881
882 return '?';
883}
884
885static char getSymbolNMTypeChar(COFFObjectFile &Obj, symbol_iterator I) {
886 COFFSymbolRef Symb = Obj.getCOFFSymbol(*I);
887 // OK, this is COFF.
888 symbol_iterator SymI(I);
889
890 Expected<StringRef> Name = SymI->getName();
891 if (!Name) {
892 consumeError(Name.takeError());
893 return '?';
894 }
895
896 char Ret = StringSwitch<char>(*Name)
897 .StartsWith(".debug", 'N')
898 .StartsWith(".sxdata", 'N')
899 .Default('?');
900
901 if (Ret != '?')
902 return Ret;
903
904 uint32_t Characteristics = 0;
905 if (!COFF::isReservedSectionNumber(Symb.getSectionNumber())) {
906 Expected<section_iterator> SecIOrErr = SymI->getSection();
907 if (!SecIOrErr) {
908 consumeError(SecIOrErr.takeError());
909 return '?';
910 }
911 section_iterator SecI = *SecIOrErr;
912 const coff_section *Section = Obj.getCOFFSection(*SecI);
913 Characteristics = Section->Characteristics;
914 if (Expected<StringRef> NameOrErr = Obj.getSectionName(Section))
915 if (NameOrErr->startswith(".idata"))
916 return 'i';
917 }
918
919 switch (Symb.getSectionNumber()) {
920 case COFF::IMAGE_SYM_DEBUG:
921 return 'n';
922 default:
923 // Check section type.
924 if (Characteristics & COFF::IMAGE_SCN_CNT_CODE)
925 return 't';
926 if (Characteristics & COFF::IMAGE_SCN_CNT_INITIALIZED_DATA)
927 return Characteristics & COFF::IMAGE_SCN_MEM_WRITE ? 'd' : 'r';
928 if (Characteristics & COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA)
929 return 'b';
930 if (Characteristics & COFF::IMAGE_SCN_LNK_INFO)
931 return 'i';
932 // Check for section symbol.
933 if (Symb.isSectionDefinition())
934 return 's';
935 }
936
937 return '?';
938}
939
940static char getSymbolNMTypeChar(XCOFFObjectFile &Obj, symbol_iterator I) {
941 Expected<uint32_t> TypeOrErr = I->getType();
942 if (!TypeOrErr) {
943 warn(TypeOrErr.takeError(), Obj.getFileName(),
944 "for symbol with index " +
945 Twine(Obj.getSymbolIndex(I->getRawDataRefImpl().p)));
946 return '?';
947 }
948
949 uint32_t SymType = *TypeOrErr;
950
951 if (SymType == SymbolRef::ST_File)
952 return 'f';
953
954 // If the I->getSection() call would return an error, the earlier I->getType()
955 // call will already have returned the same error first.
956 section_iterator SecIter = cantFail(I->getSection());
957
958 if (SecIter == Obj.section_end())
959 return '?';
960
961 if (Obj.isDebugSection(SecIter->getRawDataRefImpl()))
962 return 'N';
963
964 if (SecIter->isText())
965 return 't';
966
967 if (SecIter->isData())
968 return 'd';
969
970 if (SecIter->isBSS())
971 return 'b';
972
973 return '?';
974}
975
976static char getSymbolNMTypeChar(COFFImportFile &Obj) {
977 switch (Obj.getCOFFImportHeader()->getType()) {
978 case COFF::IMPORT_CODE:
979 return 't';
980 case COFF::IMPORT_DATA:
981 return 'd';
982 case COFF::IMPORT_CONST:
983 return 'r';
984 }
985 return '?';
986}
987
988static char getSymbolNMTypeChar(MachOObjectFile &Obj, basic_symbol_iterator I) {
989 DataRefImpl Symb = I->getRawDataRefImpl();
990 uint8_t NType = Obj.is64Bit() ? Obj.getSymbol64TableEntry(Symb).n_type
991 : Obj.getSymbolTableEntry(Symb).n_type;
992
993 if (NType & MachO::N_STAB)
994 return '-';
995
996 switch (NType & MachO::N_TYPE) {
997 case MachO::N_ABS:
998 return 's';
999 case MachO::N_INDR:
1000 return 'i';
1001 case MachO::N_SECT: {
1002 Expected<section_iterator> SecOrErr = Obj.getSymbolSection(Symb);
1003 if (!SecOrErr) {
1004 consumeError(SecOrErr.takeError());
1005 return 's';
1006 }
1007 section_iterator Sec = *SecOrErr;
1008 if (Sec == Obj.section_end())
1009 return 's';
1010 DataRefImpl Ref = Sec->getRawDataRefImpl();
1011 StringRef SectionName;
1012 if (Expected<StringRef> NameOrErr = Obj.getSectionName(Ref))
1013 SectionName = *NameOrErr;
1014 StringRef SegmentName = Obj.getSectionFinalSegmentName(Ref);
1015 if (Obj.is64Bit() && Obj.getHeader64().filetype == MachO::MH_KEXT_BUNDLE &&
1016 SegmentName == "__TEXT_EXEC" && SectionName == "__text")
1017 return 't';
1018 if (SegmentName == "__TEXT" && SectionName == "__text")
1019 return 't';
1020 if (SegmentName == "__DATA" && SectionName == "__data")
1021 return 'd';
1022 if (SegmentName == "__DATA" && SectionName == "__bss")
1023 return 'b';
1024 return 's';
1025 }
1026 }
1027
1028 return '?';
1029}
1030
1031static char getSymbolNMTypeChar(TapiFile &Obj, basic_symbol_iterator I) {
1032 auto Type = cantFail(Obj.getSymbolType(I->getRawDataRefImpl()));
1033 switch (Type) {
1034 case SymbolRef::ST_Data:
1035 return 'd';
1036 case SymbolRef::ST_Function:
1037 return 't';
1038 default:
1039 return 's';
1040 }
1041}
1042
1043static 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
1050static 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
1063static 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.
1070static 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.
1080static 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")::llvm::llvm_unreachable_internal("unknown binary format", "llvm/tools/llvm-nm/llvm-nm.cpp"
, 1147)
;
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.
1161static 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.
1181static 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
1191static 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(18446744073709551615UL);
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
1659static 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 Obj.is64Bit() ? BitMode != BitModeTy::Bit32
1668 : BitMode != BitModeTy::Bit64;
1669}
1670
1671static 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
1748static Expected<SymbolicFile::basic_symbol_iterator_range>
1749getDynamicSyms(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.
1757static 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
1868static 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
1881static 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
1892static 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.
1930static 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
1957static void printArchiveMap(iterator_range<Archive::symbol_iterator> &map,
1958 StringRef Filename) {
1959 for (auto I : map) {
1960 Expected<Archive::Child> C = I.getMember();
1961 if (!C) {
1962 error(C.takeError(), Filename);
1963 break;
1964 }
1965 Expected<StringRef> FileNameOrErr = C->getName();
1966 if (!FileNameOrErr) {
1967 error(FileNameOrErr.takeError(), Filename);
1968 break;
1969 }
1970 StringRef SymName = I.getName();
1971 outs() << SymName << " in " << FileNameOrErr.get() << "\n";
1972 }
1973
1974 outs() << "\n";
1975}
1976
1977static void dumpArchiveMap(Archive *A, StringRef Filename) {
1978 auto Map = A->symbols();
1979 if (!Map.empty()) {
1980 outs() << "Archive map\n";
1981 printArchiveMap(Map, Filename);
1982 }
1983
1984 auto ECMap = A->ec_symbols();
1985 if (!ECMap) {
1986 warn(ECMap.takeError(), Filename);
1987 } else if (!ECMap->empty()) {
1988 outs() << "Archive EC map\n";
1989 printArchiveMap(*ECMap, Filename);
1990 }
1991}
1992
1993static void dumpArchive(Archive *A, std::vector<NMSymbol> &SymbolList,
1994 StringRef Filename, LLVMContext *ContextPtr) {
1995 if (ArchiveMap)
1996 dumpArchiveMap(A, Filename);
1997
1998 Error Err = Error::success();
1999 for (auto &C : A->children(Err)) {
2000 Expected<std::unique_ptr<Binary>> ChildOrErr = C.getAsBinary(ContextPtr);
2001 if (!ChildOrErr) {
2002 if (auto E = isNotObjectErrorInvalidFileType(ChildOrErr.takeError()))
2003 error(std::move(E), Filename, C);
2004 continue;
2005 }
2006 if (SymbolicFile *O = dyn_cast<SymbolicFile>(&*ChildOrErr.get())) {
2007 if (!MachOPrintSizeWarning && PrintSize && isa<MachOObjectFile>(O)) {
2008 WithColor::warning(errs(), ToolName)
2009 << "sizes with -print-size for Mach-O files are always zero.\n";
2010 MachOPrintSizeWarning = true;
2011 }
2012 if (!checkMachOAndArchFlags(O, Filename))
2013 return;
2014 dumpSymbolNamesFromObject(*O, SymbolList, /*PrintSymbolObject=*/false,
2015 !PrintFileName, Filename,
2016 /*ArchitectureName=*/{}, O->getFileName(),
2017 /*PrintArchiveName=*/false);
2018 }
2019 }
2020 if (Err)
2021 error(std::move(Err), A->getFileName());
2022}
2023
2024static void dumpMachOUniversalBinaryMatchArchFlags(
2025 MachOUniversalBinary *UB, std::vector<NMSymbol> &SymbolList,
2026 StringRef Filename, LLVMContext *ContextPtr) {
2027 // Look for a slice in the universal binary that matches each ArchFlag.
2028 bool ArchFound;
2029 for (unsigned i = 0; i < ArchFlags.size(); ++i) {
2030 ArchFound = false;
2031 for (MachOUniversalBinary::object_iterator I = UB->begin_objects(),
2032 E = UB->end_objects();
2033 I != E; ++I) {
2034 if (ArchFlags[i] == I->getArchFlagName()) {
2035 ArchFound = true;
2036 Expected<std::unique_ptr<ObjectFile>> ObjOrErr = I->getAsObjectFile();
2037 std::string ArchiveName;
2038 std::string ArchitectureName;
2039 ArchiveName.clear();
2040 ArchitectureName.clear();
2041 if (ObjOrErr) {
2042 ObjectFile &Obj = *ObjOrErr.get();
2043 if (ArchFlags.size() > 1)
2044 ArchitectureName = I->getArchFlagName();
2045 dumpSymbolNamesFromObject(Obj, SymbolList,
2046 /*PrintSymbolObject=*/false,
2047 (ArchFlags.size() > 1) && !PrintFileName,
2048 ArchiveName, ArchitectureName);
2049 } else if (auto E =
2050 isNotObjectErrorInvalidFileType(ObjOrErr.takeError())) {
2051 error(std::move(E), Filename,
2052 ArchFlags.size() > 1 ? StringRef(I->getArchFlagName())
2053 : StringRef());
2054 continue;
2055 } else if (Expected<std::unique_ptr<Archive>> AOrErr =
2056 I->getAsArchive()) {
2057 std::unique_ptr<Archive> &A = *AOrErr;
2058 Error Err = Error::success();
2059 for (auto &C : A->children(Err)) {
2060 Expected<std::unique_ptr<Binary>> ChildOrErr =
2061 C.getAsBinary(ContextPtr);
2062 if (!ChildOrErr) {
2063 if (auto E =
2064 isNotObjectErrorInvalidFileType(ChildOrErr.takeError())) {
2065 error(std::move(E), Filename, C,
2066 ArchFlags.size() > 1 ? StringRef(I->getArchFlagName())
2067 : StringRef());
2068 }
2069 continue;
2070 }
2071 if (SymbolicFile *O = dyn_cast<SymbolicFile>(&*ChildOrErr.get())) {
2072 ArchiveName = std::string(A->getFileName());
2073 if (ArchFlags.size() > 1)
2074 ArchitectureName = I->getArchFlagName();
2075 dumpSymbolNamesFromObject(
2076 *O, SymbolList, /*PrintSymbolObject=*/false, !PrintFileName,
2077 ArchiveName, ArchitectureName);
2078 }
2079 }
2080 if (Err)
2081 error(std::move(Err), A->getFileName());
2082 } else {
2083 consumeError(AOrErr.takeError());
2084 error(Filename + " for architecture " +
2085 StringRef(I->getArchFlagName()) +
2086 " is not a Mach-O file or an archive file",
2087 "Mach-O universal file");
2088 }
2089 }
2090 }
2091 if (!ArchFound) {
2092 error(ArchFlags[i],
2093 "file: " + Filename + " does not contain architecture");
2094 return;
2095 }
2096 }
2097}
2098
2099// Returns true If the binary contains a slice that matches the host
2100// architecture, or false otherwise.
2101static bool dumpMachOUniversalBinaryMatchHost(MachOUniversalBinary *UB,
2102 std::vector<NMSymbol> &SymbolList,
2103 StringRef Filename,
2104 LLVMContext *ContextPtr) {
2105 Triple HostTriple = MachOObjectFile::getHostArch();
2106 StringRef HostArchName = HostTriple.getArchName();
2107 for (MachOUniversalBinary::object_iterator I = UB->begin_objects(),
2108 E = UB->end_objects();
2109 I != E; ++I) {
2110 if (HostArchName == I->getArchFlagName()) {
2111 Expected<std::unique_ptr<ObjectFile>> ObjOrErr = I->getAsObjectFile();
2112 std::string ArchiveName;
2113 if (ObjOrErr) {
2114 ObjectFile &Obj = *ObjOrErr.get();
2115 dumpSymbolNamesFromObject(Obj, SymbolList, /*PrintSymbolObject=*/false,
2116 /*PrintObjectLabel=*/false);
2117 } else if (auto E = isNotObjectErrorInvalidFileType(ObjOrErr.takeError()))
2118 error(std::move(E), Filename);
2119 else if (Expected<std::unique_ptr<Archive>> AOrErr = I->getAsArchive()) {
2120 std::unique_ptr<Archive> &A = *AOrErr;
2121 Error Err = Error::success();
2122 for (auto &C : A->children(Err)) {
2123 Expected<std::unique_ptr<Binary>> ChildOrErr =
2124 C.getAsBinary(ContextPtr);
2125 if (!ChildOrErr) {
2126 if (auto E =
2127 isNotObjectErrorInvalidFileType(ChildOrErr.takeError()))
2128 error(std::move(E), Filename, C);
2129 continue;
2130 }
2131 if (SymbolicFile *O = dyn_cast<SymbolicFile>(&*ChildOrErr.get())) {
2132 ArchiveName = std::string(A->getFileName());
2133 dumpSymbolNamesFromObject(*O, SymbolList,
2134 /*PrintSymbolObject=*/false,
2135 !PrintFileName, ArchiveName);
2136 }
2137 }
2138 if (Err)
2139 error(std::move(Err), A->getFileName());
2140 } else {
2141 consumeError(AOrErr.takeError());
2142 error(Filename + " for architecture " +
2143 StringRef(I->getArchFlagName()) +
2144 " is not a Mach-O file or an archive file",
2145 "Mach-O universal file");
2146 }
2147 return true;
2148 }
2149 }
2150 return false;
2151}
2152
2153static void dumpMachOUniversalBinaryArchAll(MachOUniversalBinary *UB,
2154 std::vector<NMSymbol> &SymbolList,
2155 StringRef Filename,
2156 LLVMContext *ContextPtr) {
2157 bool moreThanOneArch = UB->getNumberOfObjects() > 1;
2158 for (const MachOUniversalBinary::ObjectForArch &O : UB->objects()) {
2159 Expected<std::unique_ptr<ObjectFile>> ObjOrErr = O.getAsObjectFile();
2160 std::string ArchiveName;
2161 std::string ArchitectureName;
2162 ArchiveName.clear();
2163 ArchitectureName.clear();
2164 if (ObjOrErr) {
2165 ObjectFile &Obj = *ObjOrErr.get();
2166 if (isa<MachOObjectFile>(Obj) && moreThanOneArch)
2167 ArchitectureName = O.getArchFlagName();
2168 dumpSymbolNamesFromObject(Obj, SymbolList, /*PrintSymbolObject=*/false,
2169 !PrintFileName, ArchiveName, ArchitectureName);
2170 } else if (auto E = isNotObjectErrorInvalidFileType(ObjOrErr.takeError())) {
2171 error(std::move(E), Filename,
2172 moreThanOneArch ? StringRef(O.getArchFlagName()) : StringRef());
2173 continue;
2174 } else if (Expected<std::unique_ptr<Archive>> AOrErr = O.getAsArchive()) {
2175 std::unique_ptr<Archive> &A = *AOrErr;
2176 Error Err = Error::success();
2177 for (auto &C : A->children(Err)) {
2178 Expected<std::unique_ptr<Binary>> ChildOrErr =
2179 C.getAsBinary(ContextPtr);
2180 if (!ChildOrErr) {
2181 if (auto E = isNotObjectErrorInvalidFileType(ChildOrErr.takeError()))
2182 error(std::move(E), Filename, C,
2183 moreThanOneArch ? StringRef(ArchitectureName) : StringRef());
2184 continue;
2185 }
2186 if (SymbolicFile *F = dyn_cast<SymbolicFile>(&*ChildOrErr.get())) {
2187 ArchiveName = std::string(A->getFileName());
2188 if (isa<MachOObjectFile>(F) && moreThanOneArch)
2189 ArchitectureName = O.getArchFlagName();
2190 dumpSymbolNamesFromObject(*F, SymbolList, /*PrintSymbolObject=*/false,
2191 !PrintFileName, ArchiveName,
2192 ArchitectureName);
2193 }
2194 }
2195 if (Err)
2196 error(std::move(Err), A->getFileName());
2197 } else {
2198 consumeError(AOrErr.takeError());
2199 error(Filename + " for architecture " + StringRef(O.getArchFlagName()) +
2200 " is not a Mach-O file or an archive file",
2201 "Mach-O universal file");
2202 }
2203 }
2204}
2205
2206static void dumpMachOUniversalBinary(MachOUniversalBinary *UB,
2207 std::vector<NMSymbol> &SymbolList,
2208 StringRef Filename,
2209 LLVMContext *ContextPtr) {
2210 // If we have a list of architecture flags specified dump only those.
2211 if (!ArchAll && !ArchFlags.empty()) {
2212 dumpMachOUniversalBinaryMatchArchFlags(UB, SymbolList, Filename,
2213 ContextPtr);
2214 return;
2215 }
2216
2217 // No architecture flags were specified so if this contains a slice that
2218 // matches the host architecture dump only that.
2219 if (!ArchAll &&
2220 dumpMachOUniversalBinaryMatchHost(UB, SymbolList, Filename, ContextPtr))
2221 return;
2222
2223 // Either all architectures have been specified or none have been specified
2224 // and this does not contain the host architecture so dump all the slices.
2225 dumpMachOUniversalBinaryArchAll(UB, SymbolList, Filename, ContextPtr);
2226}
2227
2228static void dumpTapiUniversal(TapiUniversal *TU,
2229 std::vector<NMSymbol> &SymbolList,
2230 StringRef Filename) {
2231 for (const TapiUniversal::ObjectForArch &I : TU->objects()) {
2232 StringRef ArchName = I.getArchFlagName();
2233 const bool ShowArch =
2234 ArchFlags.empty() || llvm::is_contained(ArchFlags, ArchName);
2235 if (!ShowArch)
2236 continue;
2237 if (!AddInlinedInfo && !I.isTopLevelLib())
2238 continue;
2239 if (auto ObjOrErr = I.getAsObjectFile())
2240 dumpSymbolNamesFromObject(
2241 *ObjOrErr.get(), SymbolList, /*PrintSymbolObject=*/false,
2242 /*PrintObjectLabel=*/true,
2243 /*ArchiveName=*/{}, ArchName, I.getInstallName());
2244 else if (Error E = isNotObjectErrorInvalidFileType(ObjOrErr.takeError())) {
2245 error(std::move(E), Filename, ArchName);
2246 }
2247 }
2248}
2249
2250static void dumpSymbolicFile(SymbolicFile *O, std::vector<NMSymbol> &SymbolList,
2251 StringRef Filename) {
2252 if (!MachOPrintSizeWarning && PrintSize && isa<MachOObjectFile>(O)) {
2253 WithColor::warning(errs(), ToolName)
2254 << "sizes with --print-size for Mach-O files are always zero.\n";
2255 MachOPrintSizeWarning = true;
2256 }
2257 if (!checkMachOAndArchFlags(O, Filename))
2258 return;
2259 dumpSymbolNamesFromObject(*O, SymbolList, /*PrintSymbolObject=*/true,
2260 /*PrintObjectLabel=*/false);
2261}
2262
2263static std::vector<NMSymbol> dumpSymbolNamesFromFile(StringRef Filename) {
2264 std::vector<NMSymbol> SymbolList;
2265 ErrorOr<std::unique_ptr<MemoryBuffer>> BufferOrErr =
2266 MemoryBuffer::getFileOrSTDIN(Filename);
2267 if (error(BufferOrErr.getError(), Filename))
2268 return SymbolList;
2269
2270 // Always enable opaque pointers, to handle archives with mixed typed and
2271 // opaque pointer bitcode files gracefully. As we're only reading symbols,
2272 // the used pointer types don't matter.
2273 LLVMContext Context;
2274 Context.setOpaquePointers(true);
2275 LLVMContext *ContextPtr = NoLLVMBitcode ? nullptr : &Context;
2276 Expected<std::unique_ptr<Binary>> BinaryOrErr =
2277 createBinary(BufferOrErr.get()->getMemBufferRef(), ContextPtr);
2278 if (!BinaryOrErr) {
2279 error(BinaryOrErr.takeError(), Filename);
2280 return SymbolList;
2281 }
2282 Binary &Bin = *BinaryOrErr.get();
2283 if (Archive *A = dyn_cast<Archive>(&Bin))
2284 dumpArchive(A, SymbolList, Filename, ContextPtr);
2285 else if (MachOUniversalBinary *UB = dyn_cast<MachOUniversalBinary>(&Bin))
2286 dumpMachOUniversalBinary(UB, SymbolList, Filename, ContextPtr);
2287 else if (TapiUniversal *TU = dyn_cast<TapiUniversal>(&Bin))
2288 dumpTapiUniversal(TU, SymbolList, Filename);
2289 else if (SymbolicFile *O = dyn_cast<SymbolicFile>(&Bin))
2290 dumpSymbolicFile(O, SymbolList, Filename);
2291 return SymbolList;
2292}
2293
2294static void
2295exportSymbolNamesFromFiles(const std::vector<std::string> &InputFilenames) {
2296 std::vector<NMSymbol> SymbolList;
2297 for (const auto &FileName : InputFilenames) {
2298 std::vector<NMSymbol> FileSymList = dumpSymbolNamesFromFile(FileName);
2299 SymbolList.insert(SymbolList.end(), FileSymList.begin(), FileSymList.end());
2300 }
2301
2302 // Delete symbols which should not be printed from SymolList.
2303 llvm::erase_if(SymbolList,
2304 [](const NMSymbol &s) { return !s.shouldPrint(); });
2305 sortSymbolList(SymbolList);
2306 SymbolList.erase(std::unique(SymbolList.begin(), SymbolList.end()),
2307 SymbolList.end());
2308 printExportSymbolList(SymbolList);
2309}
2310
2311int llvm_nm_main(int argc, char **argv, const llvm::ToolContext &) {
2312 InitLLVM X(argc, argv);
2313 BumpPtrAllocator A;
2314 StringSaver Saver(A);
2315 NmOptTable Tbl;
2316 ToolName = argv[0];
2317 opt::InputArgList Args =
2318 Tbl.parseArgs(argc, argv, OPT_UNKNOWN, Saver, [&](StringRef Msg) {
2319 error(Msg);
2320 exit(1);
2321 });
2322 if (Args.hasArg(OPT_help)) {
2323 Tbl.printHelp(
2324 outs(),
2325 (Twine(ToolName) + " [options] <input object files>").str().c_str(),
2326 "LLVM symbol table dumper");
2327 // TODO Replace this with OptTable API once it adds extrahelp support.
2328 outs() << "\nPass @FILE as argument to read options from FILE.\n";
2329 return 0;
2330 }
2331 if (Args.hasArg(OPT_version)) {
2332 // This needs to contain the word "GNU", libtool looks for that string.
2333 outs() << "llvm-nm, compatible with GNU nm" << '\n';
2334 cl::PrintVersionMessage();
2335 return 0;
2336 }
2337
2338 DebugSyms = Args.hasArg(OPT_debug_syms);
2339 DefinedOnly = Args.hasArg(OPT_defined_only);
2340 Demangle = Args.hasFlag(OPT_demangle, OPT_no_demangle, false);
2341 DynamicSyms = Args.hasArg(OPT_dynamic);
2342 ExternalOnly = Args.hasArg(OPT_extern_only);
2343 StringRef V = Args.getLastArgValue(OPT_format_EQ, "bsd");
2344 if (V == "bsd")
2345 OutputFormat = bsd;
2346 else if (V == "posix")
2347 OutputFormat = posix;
2348 else if (V == "sysv")
2349 OutputFormat = sysv;
2350 else if (V == "darwin")
2351 OutputFormat = darwin;
2352 else if (V == "just-symbols")
2353 OutputFormat = just_symbols;
2354 else
2355 error("--format value should be one of: bsd, posix, sysv, darwin, "
2356 "just-symbols");
2357 NoLLVMBitcode = Args.hasArg(OPT_no_llvm_bc);
2358 NoSort = Args.hasArg(OPT_no_sort);
2359 NoWeakSymbols = Args.hasArg(OPT_no_weak);
2360 NumericSort = Args.hasArg(OPT_numeric_sort);
2361 ArchiveMap = Args.hasArg(OPT_print_armap);
2362 PrintFileName = Args.hasArg(OPT_print_file_name);
2363 PrintSize = Args.hasArg(OPT_print_size);
2364 ReverseSort = Args.hasArg(OPT_reverse_sort);
2365 ExportSymbols = Args.hasArg(OPT_export_symbols);
2366 if (ExportSymbols) {
2367 ExternalOnly = true;
2368 DefinedOnly = true;
2369 }
2370
2371 Quiet = Args.hasArg(OPT_quiet);
2372 V = Args.getLastArgValue(OPT_radix_EQ, "x");
2373 if (V == "o")
2374 AddressRadix = Radix::o;
2375 else if (V == "d")
2376 AddressRadix = Radix::d;
2377 else if (V == "x")
2378 AddressRadix = Radix::x;
2379 else
2380 error("--radix value should be one of: 'o' (octal), 'd' (decimal), 'x' "
2381 "(hexadecimal)");
2382 SizeSort = Args.hasArg(OPT_size_sort);
2383 SpecialSyms = Args.hasArg(OPT_special_syms);
2384 UndefinedOnly = Args.hasArg(OPT_undefined_only);
2385 WithoutAliases = Args.hasArg(OPT_without_aliases);
2386
2387 // Get BitMode from enviornment variable "OBJECT_MODE" for AIX OS, if
2388 // specified.
2389 Triple HostTriple(sys::getProcessTriple());
2390 if (HostTriple.isOSAIX()) {
2391 BitMode = StringSwitch<BitModeTy>(getenv("OBJECT_MODE"))
2392 .Case("32", BitModeTy::Bit32)
2393 .Case("64", BitModeTy::Bit64)
2394 .Case("32_64", BitModeTy::Bit32_64)
2395 .Case("any", BitModeTy::Any)
2396 .Default(BitModeTy::Bit32);
2397 } else
2398 BitMode = BitModeTy::Any;
2399
2400 if (Arg *A = Args.getLastArg(OPT_X)) {
2401 StringRef Mode = A->getValue();
2402 if (Mode == "32")
2403 BitMode = BitModeTy::Bit32;
2404 else if (Mode == "64")
2405 BitMode = BitModeTy::Bit64;
2406 else if (Mode == "32_64")
2407 BitMode = BitModeTy::Bit32_64;
2408 else if (Mode == "any")
2409 BitMode = BitModeTy::Any;
2410 else
2411 error("-X value should be one of: 32, 64, 32_64, (default) any");
2412 }
2413
2414 // Mach-O specific options.
2415 FormatMachOasHex = Args.hasArg(OPT_x);
2416 AddDyldInfo = Args.hasArg(OPT_add_dyldinfo);
2417 AddInlinedInfo = Args.hasArg(OPT_add_inlinedinfo);
2418 DyldInfoOnly = Args.hasArg(OPT_dyldinfo_only);
2419 NoDyldInfo = Args.hasArg(OPT_no_dyldinfo);
2420
2421 // XCOFF specific options.
2422 NoRsrc = Args.hasArg(OPT_no_rsrc);
2423
2424 // llvm-nm only reads binary files.
2425 if (error(sys::ChangeStdinToBinary()))
2426 return 1;
2427
2428 // These calls are needed so that we can read bitcode correctly.
2429 llvm::InitializeAllTargetInfos();
2430 llvm::InitializeAllTargetMCs();
2431 llvm::InitializeAllAsmParsers();
2432
2433 // The relative order of these is important. If you pass --size-sort it should
2434 // only print out the size. However, if you pass -S --size-sort, it should
2435 // print out both the size and address.
2436 if (SizeSort && !PrintSize)
2437 PrintAddress = false;
2438 if (OutputFormat == sysv || SizeSort)
2439 PrintSize = true;
2440
2441 for (const auto *A : Args.filtered(OPT_arch_EQ)) {
2442 SmallVector<StringRef, 2> Values;
2443 llvm::SplitString(A->getValue(), Values, ",");
2444 for (StringRef V : Values) {
2445 if (V == "all")
2446 ArchAll = true;
2447 else if (MachOObjectFile::isValidArch(V))
2448 ArchFlags.push_back(V);
2449 else
2450 error("Unknown architecture named '" + V + "'",
2451 "for the --arch option");
2452 }
2453 }
2454
2455 // Mach-O takes -s to accept two arguments. We emulate this by iterating over
2456 // both OPT_s and OPT_INPUT.
2457 std::vector<std::string> InputFilenames;
2458 int SegSectArgs = 0;
2459 for (opt::Arg *A : Args.filtered(OPT_s, OPT_INPUT)) {
2460 if (SegSectArgs > 0) {
2461 --SegSectArgs;
2462 SegSect.push_back(A->getValue());
2463 } else if (A->getOption().matches(OPT_s)) {
2464 SegSectArgs = 2;
2465 } else {
2466 InputFilenames.push_back(A->getValue());
2467 }
2468 }
2469 if (!SegSect.empty() && SegSect.size() != 2)
2470 error("bad number of arguments (must be two arguments)",
2471 "for the -s option");
2472
2473 if (InputFilenames.empty())
2474 InputFilenames.push_back("a.out");
2475 if (InputFilenames.size() > 1)
2476 MultipleFiles = true;
2477
2478 if (NoDyldInfo && (AddDyldInfo || DyldInfoOnly))
2479 error("--no-dyldinfo can't be used with --add-dyldinfo or --dyldinfo-only");
2480
2481 if (ExportSymbols)
2482 exportSymbolNamesFromFiles(InputFilenames);
2483 else
2484 llvm::for_each(InputFilenames, dumpSymbolNamesFromFile);
2485
2486 if (HadError)
2487 return 1;
2488 return 0;
2489}