brintos

brintos / llvm-project-archived public Read only

0
0
Text · 88.4 KiB · dcfc0f9 Raw
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