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