Bug Summary

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