Bug Summary

File:llvm/tools/llvm-nm/llvm-nm.cpp
Warning:line 324, 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-store=region -analyzer-opt-analyze-nested-blocks -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-14~++20220119111520+da61cb019eb2/build-llvm -resource-dir /usr/lib/llvm-14/lib/clang/14.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-14~++20220119111520+da61cb019eb2/llvm/tools/llvm-nm -I include -I /build/llvm-toolchain-snapshot-14~++20220119111520+da61cb019eb2/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-14/lib/clang/14.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-14~++20220119111520+da61cb019eb2/build-llvm=build-llvm -fmacro-prefix-map=/build/llvm-toolchain-snapshot-14~++20220119111520+da61cb019eb2/= -fcoverage-prefix-map=/build/llvm-toolchain-snapshot-14~++20220119111520+da61cb019eb2/build-llvm=build-llvm -fcoverage-prefix-map=/build/llvm-toolchain-snapshot-14~++20220119111520+da61cb019eb2/= -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 -std=c++14 -fdeprecated-macro -fdebug-compilation-dir=/build/llvm-toolchain-snapshot-14~++20220119111520+da61cb019eb2/build-llvm -fdebug-prefix-map=/build/llvm-toolchain-snapshot-14~++20220119111520+da61cb019eb2/build-llvm=build-llvm -fdebug-prefix-map=/build/llvm-toolchain-snapshot-14~++20220119111520+da61cb019eb2/= -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-01-19-134126-35450-1 -x c++ /build/llvm-toolchain-snapshot-14~++20220119111520+da61cb019eb2/llvm/tools/llvm-nm/llvm-nm.cpp

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

/build/llvm-toolchain-snapshot-14~++20220119111520+da61cb019eb2/llvm/include/llvm/Object/Binary.h

1//===- Binary.h - A generic binary file -------------------------*- C++ -*-===//
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 file declares the Binary class.
10//
11//===----------------------------------------------------------------------===//
12
13#ifndef LLVM_OBJECT_BINARY_H
14#define LLVM_OBJECT_BINARY_H
15
16#include "llvm-c/Types.h"
17#include "llvm/ADT/Triple.h"
18#include "llvm/Object/Error.h"
19#include "llvm/Support/Error.h"
20#include "llvm/Support/MemoryBuffer.h"
21#include <algorithm>
22#include <memory>
23#include <utility>
24
25namespace llvm {
26
27class LLVMContext;
28class StringRef;
29
30namespace object {
31
32class Binary {
33private:
34 unsigned int TypeID;
35
36protected:
37 MemoryBufferRef Data;
38
39 Binary(unsigned int Type, MemoryBufferRef Source);
40
41 enum {
42 ID_Archive,
43 ID_MachOUniversalBinary,
44 ID_COFFImportFile,
45 ID_IR, // LLVM IR
46 ID_TapiUniversal, // Text-based Dynamic Library Stub file.
47 ID_TapiFile, // Text-based Dynamic Library Stub file.
48
49 ID_Minidump,
50
51 ID_WinRes, // Windows resource (.res) file.
52
53 // Object and children.
54 ID_StartObjects,
55 ID_COFF,
56
57 ID_XCOFF32, // AIX XCOFF 32-bit
58 ID_XCOFF64, // AIX XCOFF 64-bit
59
60 ID_ELF32L, // ELF 32-bit, little endian
61 ID_ELF32B, // ELF 32-bit, big endian
62 ID_ELF64L, // ELF 64-bit, little endian
63 ID_ELF64B, // ELF 64-bit, big endian
64
65 ID_MachO32L, // MachO 32-bit, little endian
66 ID_MachO32B, // MachO 32-bit, big endian
67 ID_MachO64L, // MachO 64-bit, little endian
68 ID_MachO64B, // MachO 64-bit, big endian
69
70 ID_Wasm,
71
72 ID_EndObjects
73 };
74
75 static inline unsigned int getELFType(bool isLE, bool is64Bits) {
76 if (isLE)
77 return is64Bits ? ID_ELF64L : ID_ELF32L;
78 else
79 return is64Bits ? ID_ELF64B : ID_ELF32B;
80 }
81
82 static unsigned int getMachOType(bool isLE, bool is64Bits) {
83 if (isLE)
84 return is64Bits ? ID_MachO64L : ID_MachO32L;
85 else
86 return is64Bits ? ID_MachO64B : ID_MachO32B;
87 }
88
89public:
90 Binary() = delete;
91 Binary(const Binary &other) = delete;
92 virtual ~Binary();
93
94 virtual Error initContent() { return Error::success(); };
95
96 StringRef getData() const;
97 StringRef getFileName() const;
98 MemoryBufferRef getMemoryBufferRef() const;
99
100 // Cast methods.
101 unsigned int getType() const { return TypeID; }
102
103 // Convenience methods
104 bool isObject() const {
105 return TypeID > ID_StartObjects && TypeID < ID_EndObjects;
106 }
107
108 bool isSymbolic() const {
109 return isIR() || isObject() || isCOFFImportFile() || isTapiFile();
110 }
111
112 bool isArchive() const { return TypeID == ID_Archive; }
113
114 bool isMachOUniversalBinary() const {
115 return TypeID == ID_MachOUniversalBinary;
116 }
117
118 bool isTapiUniversal() const { return TypeID == ID_TapiUniversal; }
119
120 bool isELF() const {
121 return TypeID >= ID_ELF32L && TypeID <= ID_ELF64B;
122 }
123
124 bool isMachO() const {
125 return TypeID >= ID_MachO32L && TypeID <= ID_MachO64B;
126 }
127
128 bool isCOFF() const {
129 return TypeID == ID_COFF;
130 }
131
132 bool isXCOFF() const { return TypeID == ID_XCOFF32 || TypeID == ID_XCOFF64; }
133
134 bool isWasm() const { return TypeID == ID_Wasm; }
135
136 bool isCOFFImportFile() const {
137 return TypeID == ID_COFFImportFile;
138 }
139
140 bool isIR() const {
141 return TypeID == ID_IR;
4
Assuming field 'TypeID' is not equal to ID_IR
5
Returning zero, which participates in a condition later
142 }
143
144 bool isMinidump() const { return TypeID == ID_Minidump; }
145
146 bool isTapiFile() const { return TypeID == ID_TapiFile; }
147
148 bool isLittleEndian() const {
149 return !(TypeID == ID_ELF32B || TypeID == ID_ELF64B ||
150 TypeID == ID_MachO32B || TypeID == ID_MachO64B ||
151 TypeID == ID_XCOFF32 || TypeID == ID_XCOFF64);
152 }
153
154 bool isWinRes() const { return TypeID == ID_WinRes; }
155
156 Triple::ObjectFormatType getTripleObjectFormat() const {
157 if (isCOFF())
158 return Triple::COFF;
159 if (isMachO())
160 return Triple::MachO;
161 if (isELF())
162 return Triple::ELF;
163 return Triple::UnknownObjectFormat;
164 }
165
166 static Error checkOffset(MemoryBufferRef M, uintptr_t Addr,
167 const uint64_t Size) {
168 if (Addr + Size < Addr || Addr + Size < Size ||
169 Addr + Size > reinterpret_cast<uintptr_t>(M.getBufferEnd()) ||
170 Addr < reinterpret_cast<uintptr_t>(M.getBufferStart())) {
171 return errorCodeToError(object_error::unexpected_eof);
172 }
173 return Error::success();
174 }
175};
176
177// Create wrappers for C Binding types (see CBindingWrapping.h).
178DEFINE_ISA_CONVERSION_FUNCTIONS(Binary, LLVMBinaryRef)inline Binary *unwrap(LLVMBinaryRef P) { return reinterpret_cast
<Binary*>(P); } inline LLVMBinaryRef wrap(const Binary *
P) { return reinterpret_cast<LLVMBinaryRef>(const_cast<
Binary*>(P)); } template<typename T> inline T *unwrap
(LLVMBinaryRef P) { return cast<T>(unwrap(P)); }
179
180/// Create a Binary from Source, autodetecting the file type.
181///
182/// @param Source The data to create the Binary from.
183Expected<std::unique_ptr<Binary>> createBinary(MemoryBufferRef Source,
184 LLVMContext *Context = nullptr,
185 bool InitContent = true);
186
187template <typename T> class OwningBinary {
188 std::unique_ptr<T> Bin;
189 std::unique_ptr<MemoryBuffer> Buf;
190
191public:
192 OwningBinary();
193 OwningBinary(std::unique_ptr<T> Bin, std::unique_ptr<MemoryBuffer> Buf);
194 OwningBinary(OwningBinary<T>&& Other);
195 OwningBinary<T> &operator=(OwningBinary<T> &&Other);
196
197 std::pair<std::unique_ptr<T>, std::unique_ptr<MemoryBuffer>> takeBinary();
198
199 T* getBinary();
200 const T* getBinary() const;
201};
202
203template <typename T>
204OwningBinary<T>::OwningBinary(std::unique_ptr<T> Bin,
205 std::unique_ptr<MemoryBuffer> Buf)
206 : Bin(std::move(Bin)), Buf(std::move(Buf)) {}
207
208template <typename T> OwningBinary<T>::OwningBinary() = default;
209
210template <typename T>
211OwningBinary<T>::OwningBinary(OwningBinary &&Other)
212 : Bin(std::move(Other.Bin)), Buf(std::move(Other.Buf)) {}
213
214template <typename T>
215OwningBinary<T> &OwningBinary<T>::operator=(OwningBinary &&Other) {
216 Bin = std::move(Other.Bin);
217 Buf = std::move(Other.Buf);
218 return *this;
219}
220
221template <typename T>
222std::pair<std::unique_ptr<T>, std::unique_ptr<MemoryBuffer>>
223OwningBinary<T>::takeBinary() {
224 return std::make_pair(std::move(Bin), std::move(Buf));
225}
226
227template <typename T> T* OwningBinary<T>::getBinary() {
228 return Bin.get();
229}
230
231template <typename T> const T* OwningBinary<T>::getBinary() const {
232 return Bin.get();
233}
234
235Expected<OwningBinary<Binary>> createBinary(StringRef Path,
236 LLVMContext *Context = nullptr,
237 bool InitContent = true);
238
239} // end namespace object
240
241} // end namespace llvm
242
243#endif // LLVM_OBJECT_BINARY_H