Path: blob/main/contrib/llvm-project/llvm/tools/llvm-nm/llvm-nm.cpp
35259 views
//===-- llvm-nm.cpp - Symbol table dumping utility for llvm ---------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// This program is a utility that works like traditional Unix "nm", that is, it9// prints out the names of symbols in a bitcode or object file, along with some10// information about each symbol.11//12// This "nm" supports many of the features of GNU "nm", including its different13// output formats.14//15//===----------------------------------------------------------------------===//1617#include "llvm/ADT/StringSwitch.h"18#include "llvm/BinaryFormat/COFF.h"19#include "llvm/BinaryFormat/MachO.h"20#include "llvm/BinaryFormat/XCOFF.h"21#include "llvm/DebugInfo/Symbolize/Symbolize.h"22#include "llvm/Demangle/Demangle.h"23#include "llvm/IR/Function.h"24#include "llvm/IR/LLVMContext.h"25#include "llvm/Object/Archive.h"26#include "llvm/Object/COFF.h"27#include "llvm/Object/COFFImportFile.h"28#include "llvm/Object/ELFObjectFile.h"29#include "llvm/Object/IRObjectFile.h"30#include "llvm/Object/MachO.h"31#include "llvm/Object/MachOUniversal.h"32#include "llvm/Object/ObjectFile.h"33#include "llvm/Object/SymbolicFile.h"34#include "llvm/Object/TapiFile.h"35#include "llvm/Object/TapiUniversal.h"36#include "llvm/Object/Wasm.h"37#include "llvm/Object/XCOFFObjectFile.h"38#include "llvm/Option/Arg.h"39#include "llvm/Option/ArgList.h"40#include "llvm/Option/Option.h"41#include "llvm/Support/CommandLine.h"42#include "llvm/Support/FileSystem.h"43#include "llvm/Support/Format.h"44#include "llvm/Support/LLVMDriver.h"45#include "llvm/Support/MemoryBuffer.h"46#include "llvm/Support/Program.h"47#include "llvm/Support/Signals.h"48#include "llvm/Support/TargetSelect.h"49#include "llvm/Support/WithColor.h"50#include "llvm/Support/raw_ostream.h"51#include "llvm/TargetParser/Host.h"52#include "llvm/TargetParser/Triple.h"53#include <vector>5455using namespace llvm;56using namespace object;5758namespace {59using namespace llvm::opt; // for HelpHidden in Opts.inc60enum ID {61OPT_INVALID = 0, // This is not an option ID.62#define OPTION(...) LLVM_MAKE_OPT_ID(__VA_ARGS__),63#include "Opts.inc"64#undef OPTION65};6667#define PREFIX(NAME, VALUE) \68static constexpr StringLiteral NAME##_init[] = VALUE; \69static constexpr ArrayRef<StringLiteral> NAME(NAME##_init, \70std::size(NAME##_init) - 1);71#include "Opts.inc"72#undef PREFIX7374static constexpr opt::OptTable::Info InfoTable[] = {75#define OPTION(...) LLVM_CONSTRUCT_OPT_INFO(__VA_ARGS__),76#include "Opts.inc"77#undef OPTION78};7980class NmOptTable : public opt::GenericOptTable {81public:82NmOptTable() : opt::GenericOptTable(InfoTable) {83setGroupedShortOptions(true);84}85};8687enum OutputFormatTy { bsd, sysv, posix, darwin, just_symbols };88enum class BitModeTy { Bit32, Bit64, Bit32_64, Any };89} // namespace9091static bool ArchiveMap;92static BitModeTy BitMode;93static bool DebugSyms;94static bool DefinedOnly;95static bool Demangle;96static bool DynamicSyms;97static bool ExportSymbols;98static bool ExternalOnly;99static bool LineNumbers;100static OutputFormatTy OutputFormat;101static bool NoLLVMBitcode;102static bool NoSort;103static bool NoWeakSymbols;104static bool NumericSort;105static bool PrintFileName;106static bool PrintSize;107static bool Quiet;108static bool ReverseSort;109static bool SpecialSyms;110static bool SizeSort;111static bool UndefinedOnly;112static bool WithoutAliases;113114// XCOFF-specific options.115static bool NoRsrc;116117namespace {118enum Radix { d, o, x };119} // namespace120static Radix AddressRadix;121122// Mach-O specific options.123static bool ArchAll = false;124static std::vector<StringRef> ArchFlags;125static bool AddDyldInfo;126static bool AddInlinedInfo;127static bool DyldInfoOnly;128static bool FormatMachOasHex;129static bool NoDyldInfo;130static std::vector<StringRef> SegSect;131static bool MachOPrintSizeWarning = false;132133// Miscellaneous states.134static bool PrintAddress = true;135static bool MultipleFiles = false;136static bool HadError = false;137138static StringRef ToolName;139140static void warn(Error Err, Twine FileName, Twine Context = Twine(),141Twine Archive = Twine()) {142assert(Err);143144// Flush the standard output so that the warning isn't interleaved with other145// output if stdout and stderr are writing to the same place.146outs().flush();147148handleAllErrors(std::move(Err), [&](const ErrorInfoBase &EI) {149WithColor::warning(errs(), ToolName)150<< (Archive.str().empty() ? FileName : Archive + "(" + FileName + ")")151<< ": " << (Context.str().empty() ? "" : Context + ": ") << EI.message()152<< "\n";153});154}155156static void error(Twine Message, Twine Path = Twine()) {157HadError = true;158WithColor::error(errs(), ToolName) << Path << ": " << Message << "\n";159}160161static bool error(std::error_code EC, Twine Path = Twine()) {162if (EC) {163error(EC.message(), Path);164return true;165}166return false;167}168169// This version of error() prints the archive name and member name, for example:170// "libx.a(foo.o)" after the ToolName before the error message. It sets171// HadError but returns allowing the code to move on to other archive members.172static void error(llvm::Error E, StringRef FileName, const Archive::Child &C,173StringRef ArchitectureName = StringRef()) {174HadError = true;175WithColor::error(errs(), ToolName) << FileName;176177Expected<StringRef> NameOrErr = C.getName();178// TODO: if we have a error getting the name then it would be nice to print179// the index of which archive member this is and or its offset in the180// archive instead of "???" as the name.181if (!NameOrErr) {182consumeError(NameOrErr.takeError());183errs() << "(" << "???" << ")";184} else185errs() << "(" << NameOrErr.get() << ")";186187if (!ArchitectureName.empty())188errs() << " (for architecture " << ArchitectureName << ")";189190std::string Buf;191raw_string_ostream OS(Buf);192logAllUnhandledErrors(std::move(E), OS);193OS.flush();194errs() << ": " << Buf << "\n";195}196197// This version of error() prints the file name and which architecture slice it198// is from, for example: "foo.o (for architecture i386)" after the ToolName199// before the error message. It sets HadError but returns allowing the code to200// move on to other architecture slices.201static void error(llvm::Error E, StringRef FileName,202StringRef ArchitectureName = StringRef()) {203HadError = true;204WithColor::error(errs(), ToolName) << FileName;205206if (!ArchitectureName.empty())207errs() << " (for architecture " << ArchitectureName << ")";208209std::string Buf;210raw_string_ostream OS(Buf);211logAllUnhandledErrors(std::move(E), OS);212OS.flush();213errs() << ": " << Buf << "\n";214}215216namespace {217struct NMSymbol {218uint64_t Address;219uint64_t Size;220char TypeChar;221std::string Name;222StringRef SectionName;223StringRef TypeName;224BasicSymbolRef Sym;225StringRef Visibility;226227// The Sym field above points to the native symbol in the object file,228// for Mach-O when we are creating symbols from the dyld info the above229// pointer is null as there is no native symbol. In these cases the fields230// below are filled in to represent what would have been a Mach-O nlist231// native symbol.232uint32_t SymFlags;233SectionRef Section;234uint8_t NType;235uint8_t NSect;236uint16_t NDesc;237std::string IndirectName;238239bool isDefined() const {240if (Sym.getRawDataRefImpl().p)241return !(SymFlags & SymbolRef::SF_Undefined);242return TypeChar != 'U';243}244245bool initializeFlags(const SymbolicFile &Obj) {246Expected<uint32_t> SymFlagsOrErr = Sym.getFlags();247if (!SymFlagsOrErr) {248// TODO: Test this error.249error(SymFlagsOrErr.takeError(), Obj.getFileName());250return false;251}252SymFlags = *SymFlagsOrErr;253return true;254}255256bool shouldPrint() const {257bool Undefined = SymFlags & SymbolRef::SF_Undefined;258bool Global = SymFlags & SymbolRef::SF_Global;259bool Weak = SymFlags & SymbolRef::SF_Weak;260bool FormatSpecific = SymFlags & SymbolRef::SF_FormatSpecific;261if ((!Undefined && UndefinedOnly) || (Undefined && DefinedOnly) ||262(!Global && ExternalOnly) || (Weak && NoWeakSymbols) ||263(FormatSpecific && !(SpecialSyms || DebugSyms)))264return false;265return true;266}267};268269bool operator<(const NMSymbol &A, const NMSymbol &B) {270if (NumericSort)271return std::make_tuple(A.isDefined(), A.Address, A.Name, A.Size) <272std::make_tuple(B.isDefined(), B.Address, B.Name, B.Size);273if (SizeSort)274return std::make_tuple(A.Size, A.Name, A.Address) <275std::make_tuple(B.Size, B.Name, B.Address);276if (ExportSymbols)277return std::make_tuple(A.Name, A.Visibility) <278std::make_tuple(B.Name, B.Visibility);279return std::make_tuple(A.Name, A.Size, A.Address) <280std::make_tuple(B.Name, B.Size, B.Address);281}282283bool operator>(const NMSymbol &A, const NMSymbol &B) { return B < A; }284bool operator==(const NMSymbol &A, const NMSymbol &B) {285return !(A < B) && !(B < A);286}287} // anonymous namespace288289static StringRef CurrentFilename;290291static char getSymbolNMTypeChar(IRObjectFile &Obj, basic_symbol_iterator I);292293// darwinPrintSymbol() is used to print a symbol from a Mach-O file when the294// the OutputFormat is darwin or we are printing Mach-O symbols in hex. For295// the darwin format it produces the same output as darwin's nm(1) -m output296// and when printing Mach-O symbols in hex it produces the same output as297// darwin's nm(1) -x format.298static void darwinPrintSymbol(SymbolicFile &Obj, const NMSymbol &S,299char *SymbolAddrStr, const char *printBlanks,300const char *printDashes,301const char *printFormat) {302MachO::mach_header H;303MachO::mach_header_64 H_64;304uint32_t Filetype = MachO::MH_OBJECT;305uint32_t Flags = 0;306uint8_t NType = 0;307uint8_t NSect = 0;308uint16_t NDesc = 0;309uint32_t NStrx = 0;310uint64_t NValue = 0;311MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(&Obj);312if (Obj.isIR()) {313uint32_t SymFlags = cantFail(S.Sym.getFlags());314if (SymFlags & SymbolRef::SF_Global)315NType |= MachO::N_EXT;316if (SymFlags & SymbolRef::SF_Hidden)317NType |= MachO::N_PEXT;318if (SymFlags & SymbolRef::SF_Undefined)319NType |= MachO::N_EXT | MachO::N_UNDF;320else {321// Here we have a symbol definition. So to fake out a section name we322// use 1, 2 and 3 for section numbers. See below where they are used to323// print out fake section names.324NType |= MachO::N_SECT;325if (SymFlags & SymbolRef::SF_Const)326NSect = 3;327else if (SymFlags & SymbolRef::SF_Executable)328NSect = 1;329else330NSect = 2;331}332if (SymFlags & SymbolRef::SF_Weak)333NDesc |= MachO::N_WEAK_DEF;334} else {335DataRefImpl SymDRI = S.Sym.getRawDataRefImpl();336if (MachO->is64Bit()) {337H_64 = MachO->MachOObjectFile::getHeader64();338Filetype = H_64.filetype;339Flags = H_64.flags;340if (SymDRI.p){341MachO::nlist_64 STE_64 = MachO->getSymbol64TableEntry(SymDRI);342NType = STE_64.n_type;343NSect = STE_64.n_sect;344NDesc = STE_64.n_desc;345NStrx = STE_64.n_strx;346NValue = STE_64.n_value;347} else {348NType = S.NType;349NSect = S.NSect;350NDesc = S.NDesc;351NStrx = 0;352NValue = S.Address;353}354} else {355H = MachO->MachOObjectFile::getHeader();356Filetype = H.filetype;357Flags = H.flags;358if (SymDRI.p){359MachO::nlist STE = MachO->getSymbolTableEntry(SymDRI);360NType = STE.n_type;361NSect = STE.n_sect;362NDesc = STE.n_desc;363NStrx = STE.n_strx;364NValue = STE.n_value;365} else {366NType = S.NType;367NSect = S.NSect;368NDesc = S.NDesc;369NStrx = 0;370NValue = S.Address;371}372}373}374375// If we are printing Mach-O symbols in hex do that and return.376if (FormatMachOasHex) {377outs() << format(printFormat, NValue) << ' '378<< format("%02x %02x %04x %08x", NType, NSect, NDesc, NStrx) << ' '379<< S.Name;380if ((NType & MachO::N_TYPE) == MachO::N_INDR) {381outs() << " (indirect for ";382outs() << format(printFormat, NValue) << ' ';383StringRef IndirectName;384if (S.Sym.getRawDataRefImpl().p) {385if (MachO->getIndirectName(S.Sym.getRawDataRefImpl(), IndirectName))386outs() << "?)";387else388outs() << IndirectName << ")";389} else390outs() << S.IndirectName << ")";391}392outs() << "\n";393return;394}395396if (PrintAddress) {397if ((NType & MachO::N_TYPE) == MachO::N_INDR)398strcpy(SymbolAddrStr, printBlanks);399if (Obj.isIR() && (NType & MachO::N_TYPE) == MachO::N_TYPE)400strcpy(SymbolAddrStr, printDashes);401outs() << SymbolAddrStr << ' ';402}403404switch (NType & MachO::N_TYPE) {405case MachO::N_UNDF:406if (NValue != 0) {407outs() << "(common) ";408if (MachO::GET_COMM_ALIGN(NDesc) != 0)409outs() << "(alignment 2^" << (int)MachO::GET_COMM_ALIGN(NDesc) << ") ";410} else {411if ((NType & MachO::N_TYPE) == MachO::N_PBUD)412outs() << "(prebound ";413else414outs() << "(";415if ((NDesc & MachO::REFERENCE_TYPE) ==416MachO::REFERENCE_FLAG_UNDEFINED_LAZY)417outs() << "undefined [lazy bound]) ";418else if ((NDesc & MachO::REFERENCE_TYPE) ==419MachO::REFERENCE_FLAG_PRIVATE_UNDEFINED_LAZY)420outs() << "undefined [private lazy bound]) ";421else if ((NDesc & MachO::REFERENCE_TYPE) ==422MachO::REFERENCE_FLAG_PRIVATE_UNDEFINED_NON_LAZY)423outs() << "undefined [private]) ";424else425outs() << "undefined) ";426}427break;428case MachO::N_ABS:429outs() << "(absolute) ";430break;431case MachO::N_INDR:432outs() << "(indirect) ";433break;434case MachO::N_SECT: {435if (Obj.isIR()) {436// For llvm bitcode files print out a fake section name using the values437// use 1, 2 and 3 for section numbers as set above.438if (NSect == 1)439outs() << "(LTO,CODE) ";440else if (NSect == 2)441outs() << "(LTO,DATA) ";442else if (NSect == 3)443outs() << "(LTO,RODATA) ";444else445outs() << "(?,?) ";446break;447}448section_iterator Sec = SectionRef();449if (S.Sym.getRawDataRefImpl().p) {450Expected<section_iterator> SecOrErr =451MachO->getSymbolSection(S.Sym.getRawDataRefImpl());452if (!SecOrErr) {453consumeError(SecOrErr.takeError());454outs() << "(?,?) ";455break;456}457Sec = *SecOrErr;458if (Sec == MachO->section_end()) {459outs() << "(?,?) ";460break;461}462} else {463Sec = S.Section;464}465DataRefImpl Ref = Sec->getRawDataRefImpl();466StringRef SectionName;467if (Expected<StringRef> NameOrErr = MachO->getSectionName(Ref))468SectionName = *NameOrErr;469StringRef SegmentName = MachO->getSectionFinalSegmentName(Ref);470outs() << "(" << SegmentName << "," << SectionName << ") ";471break;472}473default:474outs() << "(?) ";475break;476}477478if (NType & MachO::N_EXT) {479if (NDesc & MachO::REFERENCED_DYNAMICALLY)480outs() << "[referenced dynamically] ";481if (NType & MachO::N_PEXT) {482if ((NDesc & MachO::N_WEAK_DEF) == MachO::N_WEAK_DEF)483outs() << "weak private external ";484else485outs() << "private external ";486} else {487if ((NDesc & MachO::N_WEAK_REF) == MachO::N_WEAK_REF ||488(NDesc & MachO::N_WEAK_DEF) == MachO::N_WEAK_DEF) {489if ((NDesc & (MachO::N_WEAK_REF | MachO::N_WEAK_DEF)) ==490(MachO::N_WEAK_REF | MachO::N_WEAK_DEF))491outs() << "weak external automatically hidden ";492else493outs() << "weak external ";494} else495outs() << "external ";496}497} else {498if (NType & MachO::N_PEXT)499outs() << "non-external (was a private external) ";500else501outs() << "non-external ";502}503504if (Filetype == MachO::MH_OBJECT) {505if (NDesc & MachO::N_NO_DEAD_STRIP)506outs() << "[no dead strip] ";507if ((NType & MachO::N_TYPE) != MachO::N_UNDF &&508NDesc & MachO::N_SYMBOL_RESOLVER)509outs() << "[symbol resolver] ";510if ((NType & MachO::N_TYPE) != MachO::N_UNDF && NDesc & MachO::N_ALT_ENTRY)511outs() << "[alt entry] ";512if ((NType & MachO::N_TYPE) != MachO::N_UNDF && NDesc & MachO::N_COLD_FUNC)513outs() << "[cold func] ";514}515516if ((NDesc & MachO::N_ARM_THUMB_DEF) == MachO::N_ARM_THUMB_DEF)517outs() << "[Thumb] ";518519if ((NType & MachO::N_TYPE) == MachO::N_INDR) {520outs() << S.Name << " (for ";521StringRef IndirectName;522if (MachO) {523if (S.Sym.getRawDataRefImpl().p) {524if (MachO->getIndirectName(S.Sym.getRawDataRefImpl(), IndirectName))525outs() << "?)";526else527outs() << IndirectName << ")";528} else529outs() << S.IndirectName << ")";530} else531outs() << "?)";532} else533outs() << S.Name;534535if ((Flags & MachO::MH_TWOLEVEL) == MachO::MH_TWOLEVEL &&536(((NType & MachO::N_TYPE) == MachO::N_UNDF && NValue == 0) ||537(NType & MachO::N_TYPE) == MachO::N_PBUD)) {538uint32_t LibraryOrdinal = MachO::GET_LIBRARY_ORDINAL(NDesc);539if (LibraryOrdinal != 0) {540if (LibraryOrdinal == MachO::EXECUTABLE_ORDINAL)541outs() << " (from executable)";542else if (LibraryOrdinal == MachO::DYNAMIC_LOOKUP_ORDINAL)543outs() << " (dynamically looked up)";544else {545StringRef LibraryName;546if (!MachO ||547MachO->getLibraryShortNameByIndex(LibraryOrdinal - 1, LibraryName))548outs() << " (from bad library ordinal " << LibraryOrdinal << ")";549else550outs() << " (from " << LibraryName << ")";551}552}553}554}555556// Table that maps Darwin's Mach-O stab constants to strings to allow printing.557struct DarwinStabName {558uint8_t NType;559const char *Name;560};561const struct DarwinStabName DarwinStabNames[] = {562{MachO::N_GSYM, "GSYM"}, {MachO::N_FNAME, "FNAME"},563{MachO::N_FUN, "FUN"}, {MachO::N_STSYM, "STSYM"},564{MachO::N_LCSYM, "LCSYM"}, {MachO::N_BNSYM, "BNSYM"},565{MachO::N_PC, "PC"}, {MachO::N_AST, "AST"},566{MachO::N_OPT, "OPT"}, {MachO::N_RSYM, "RSYM"},567{MachO::N_SLINE, "SLINE"}, {MachO::N_ENSYM, "ENSYM"},568{MachO::N_SSYM, "SSYM"}, {MachO::N_SO, "SO"},569{MachO::N_OSO, "OSO"}, {MachO::N_LIB, "LIB"},570{MachO::N_LSYM, "LSYM"}, {MachO::N_BINCL, "BINCL"},571{MachO::N_SOL, "SOL"}, {MachO::N_PARAMS, "PARAM"},572{MachO::N_VERSION, "VERS"}, {MachO::N_OLEVEL, "OLEV"},573{MachO::N_PSYM, "PSYM"}, {MachO::N_EINCL, "EINCL"},574{MachO::N_ENTRY, "ENTRY"}, {MachO::N_LBRAC, "LBRAC"},575{MachO::N_EXCL, "EXCL"}, {MachO::N_RBRAC, "RBRAC"},576{MachO::N_BCOMM, "BCOMM"}, {MachO::N_ECOMM, "ECOMM"},577{MachO::N_ECOML, "ECOML"}, {MachO::N_LENG, "LENG"},578};579580static const char *getDarwinStabString(uint8_t NType) {581for (auto I : ArrayRef(DarwinStabNames))582if (I.NType == NType)583return I.Name;584return nullptr;585}586587// darwinPrintStab() prints the n_sect, n_desc along with a symbolic name of588// a stab n_type value in a Mach-O file.589static void darwinPrintStab(MachOObjectFile *MachO, const NMSymbol &S) {590MachO::nlist_64 STE_64;591MachO::nlist STE;592uint8_t NType;593uint8_t NSect;594uint16_t NDesc;595DataRefImpl SymDRI = S.Sym.getRawDataRefImpl();596if (MachO->is64Bit()) {597STE_64 = MachO->getSymbol64TableEntry(SymDRI);598NType = STE_64.n_type;599NSect = STE_64.n_sect;600NDesc = STE_64.n_desc;601} else {602STE = MachO->getSymbolTableEntry(SymDRI);603NType = STE.n_type;604NSect = STE.n_sect;605NDesc = STE.n_desc;606}607608outs() << format(" %02x %04x ", NSect, NDesc);609if (const char *stabString = getDarwinStabString(NType))610outs() << format("%5.5s", stabString);611else612outs() << format(" %02x", NType);613}614615static bool symbolIsDefined(const NMSymbol &Sym) {616return Sym.TypeChar != 'U' && Sym.TypeChar != 'w' && Sym.TypeChar != 'v';617}618619static void writeFileName(raw_ostream &S, StringRef ArchiveName,620StringRef ArchitectureName) {621if (!ArchitectureName.empty())622S << "(for architecture " << ArchitectureName << "):";623if (OutputFormat == posix && !ArchiveName.empty())624S << ArchiveName << "[" << CurrentFilename << "]: ";625else {626if (!ArchiveName.empty())627S << ArchiveName << ":";628S << CurrentFilename << ": ";629}630}631632static void sortSymbolList(std::vector<NMSymbol> &SymbolList) {633if (NoSort)634return;635636if (ReverseSort)637llvm::sort(SymbolList, std::greater<>());638else639llvm::sort(SymbolList);640}641642static void printExportSymbolList(const std::vector<NMSymbol> &SymbolList) {643for (const NMSymbol &Sym : SymbolList) {644outs() << Sym.Name;645if (!Sym.Visibility.empty())646outs() << ' ' << Sym.Visibility;647outs() << '\n';648}649}650651static void printLineNumbers(symbolize::LLVMSymbolizer &Symbolizer,652const NMSymbol &S) {653const auto *Obj = dyn_cast<ObjectFile>(S.Sym.getObject());654if (!Obj)655return;656const SymbolRef Sym(S.Sym);657uint64_t SectionIndex = object::SectionedAddress::UndefSection;658section_iterator Sec = cantFail(Sym.getSection());659if (Sec != Obj->section_end())660SectionIndex = Sec->getIndex();661object::SectionedAddress Address = {cantFail(Sym.getAddress()), SectionIndex};662663std::string FileName;664uint32_t Line;665switch (S.TypeChar) {666// For undefined symbols, find the first relocation for that symbol with a667// line number.668case 'U': {669for (const SectionRef RelocsSec : Obj->sections()) {670if (RelocsSec.relocations().empty())671continue;672SectionRef TextSec = *cantFail(RelocsSec.getRelocatedSection());673if (!TextSec.isText())674continue;675for (const RelocationRef R : RelocsSec.relocations()) {676if (R.getSymbol() != Sym)677continue;678Expected<DILineInfo> ResOrErr = Symbolizer.symbolizeCode(679*Obj, {TextSec.getAddress() + R.getOffset(), SectionIndex});680if (!ResOrErr) {681error(ResOrErr.takeError(), Obj->getFileName());682return;683}684if (ResOrErr->FileName == DILineInfo::BadString)685return;686FileName = std::move(ResOrErr->FileName);687Line = ResOrErr->Line;688break;689}690if (!FileName.empty())691break;692}693if (FileName.empty())694return;695break;696}697case 't':698case 'T': {699Expected<DILineInfo> ResOrErr = Symbolizer.symbolizeCode(*Obj, Address);700if (!ResOrErr) {701error(ResOrErr.takeError(), Obj->getFileName());702return;703}704if (ResOrErr->FileName == DILineInfo::BadString)705return;706FileName = std::move(ResOrErr->FileName);707Line = ResOrErr->Line;708break;709}710default: {711Expected<DIGlobal> ResOrErr = Symbolizer.symbolizeData(*Obj, Address);712if (!ResOrErr) {713error(ResOrErr.takeError(), Obj->getFileName());714return;715}716if (ResOrErr->DeclFile.empty())717return;718FileName = std::move(ResOrErr->DeclFile);719Line = ResOrErr->DeclLine;720break;721}722}723outs() << '\t' << FileName << ':' << Line;724}725726static void printSymbolList(SymbolicFile &Obj,727std::vector<NMSymbol> &SymbolList, bool printName,728StringRef ArchiveName, StringRef ArchitectureName) {729std::optional<symbolize::LLVMSymbolizer> Symbolizer;730if (LineNumbers)731Symbolizer.emplace();732733if (!PrintFileName) {734if ((OutputFormat == bsd || OutputFormat == posix ||735OutputFormat == just_symbols) &&736MultipleFiles && printName) {737outs() << '\n' << CurrentFilename << ":\n";738} else if (OutputFormat == sysv) {739outs() << "\n\nSymbols from " << CurrentFilename << ":\n\n";740if (Obj.is64Bit())741outs() << "Name Value Class Type"742<< " Size Line Section\n";743else744outs() << "Name Value Class Type"745<< " Size Line Section\n";746}747}748749const char *printBlanks, *printDashes, *printFormat;750if (Obj.is64Bit()) {751printBlanks = " ";752printDashes = "----------------";753switch (AddressRadix) {754case Radix::o:755printFormat = OutputFormat == posix ? "%" PRIo64 : "%016" PRIo64;756break;757case Radix::x:758printFormat = OutputFormat == posix ? "%" PRIx64 : "%016" PRIx64;759break;760default:761printFormat = OutputFormat == posix ? "%" PRId64 : "%016" PRId64;762}763} else {764printBlanks = " ";765printDashes = "--------";766switch (AddressRadix) {767case Radix::o:768printFormat = OutputFormat == posix ? "%" PRIo64 : "%08" PRIo64;769break;770case Radix::x:771printFormat = OutputFormat == posix ? "%" PRIx64 : "%08" PRIx64;772break;773default:774printFormat = OutputFormat == posix ? "%" PRId64 : "%08" PRId64;775}776}777778for (const NMSymbol &S : SymbolList) {779if (!S.shouldPrint())780continue;781782std::string Name = S.Name;783MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(&Obj);784if (Demangle)785Name = demangle(Name);786787if (PrintFileName)788writeFileName(outs(), ArchiveName, ArchitectureName);789if ((OutputFormat == just_symbols ||790(UndefinedOnly && MachO && OutputFormat != darwin)) &&791OutputFormat != posix) {792outs() << Name << "\n";793continue;794}795796char SymbolAddrStr[23], SymbolSizeStr[23];797798// If the format is SysV or the symbol isn't defined, then print spaces.799if (OutputFormat == sysv || !symbolIsDefined(S)) {800if (OutputFormat == posix) {801format(printFormat, S.Address)802.print(SymbolAddrStr, sizeof(SymbolAddrStr));803format(printFormat, S.Size).print(SymbolSizeStr, sizeof(SymbolSizeStr));804} else {805strcpy(SymbolAddrStr, printBlanks);806strcpy(SymbolSizeStr, printBlanks);807}808}809810if (symbolIsDefined(S)) {811// Otherwise, print the symbol address and size.812if (Obj.isIR())813strcpy(SymbolAddrStr, printDashes);814else if (MachO && S.TypeChar == 'I')815strcpy(SymbolAddrStr, printBlanks);816else817format(printFormat, S.Address)818.print(SymbolAddrStr, sizeof(SymbolAddrStr));819format(printFormat, S.Size).print(SymbolSizeStr, sizeof(SymbolSizeStr));820}821822// If OutputFormat is darwin or we are printing Mach-O symbols in hex and823// we have a MachOObjectFile, call darwinPrintSymbol to print as darwin's824// nm(1) -m output or hex, else if OutputFormat is darwin or we are825// printing Mach-O symbols in hex and not a Mach-O object fall back to826// OutputFormat bsd (see below).827if ((OutputFormat == darwin || FormatMachOasHex) && (MachO || Obj.isIR())) {828darwinPrintSymbol(Obj, S, SymbolAddrStr, printBlanks, printDashes,829printFormat);830} else if (OutputFormat == posix) {831outs() << Name << " " << S.TypeChar << " " << SymbolAddrStr << " "832<< (MachO ? "0" : SymbolSizeStr);833} else if (OutputFormat == bsd || (OutputFormat == darwin && !MachO)) {834if (PrintAddress)835outs() << SymbolAddrStr << ' ';836if (PrintSize)837outs() << SymbolSizeStr << ' ';838outs() << S.TypeChar;839if (S.TypeChar == '-' && MachO)840darwinPrintStab(MachO, S);841outs() << " " << Name;842if (S.TypeChar == 'I' && MachO) {843outs() << " (indirect for ";844if (S.Sym.getRawDataRefImpl().p) {845StringRef IndirectName;846if (MachO->getIndirectName(S.Sym.getRawDataRefImpl(), IndirectName))847outs() << "?)";848else849outs() << IndirectName << ")";850} else851outs() << S.IndirectName << ")";852}853} else if (OutputFormat == sysv) {854outs() << left_justify(Name, 20) << "|" << SymbolAddrStr << "| "855<< S.TypeChar << " |" << right_justify(S.TypeName, 18) << "|"856<< SymbolSizeStr << "| |" << S.SectionName;857}858if (LineNumbers)859printLineNumbers(*Symbolizer, S);860outs() << '\n';861}862863SymbolList.clear();864}865866static char getSymbolNMTypeChar(ELFObjectFileBase &Obj,867basic_symbol_iterator I) {868// OK, this is ELF869elf_symbol_iterator SymI(I);870871Expected<elf_section_iterator> SecIOrErr = SymI->getSection();872if (!SecIOrErr) {873consumeError(SecIOrErr.takeError());874return '?';875}876877uint8_t Binding = SymI->getBinding();878if (Binding == ELF::STB_GNU_UNIQUE)879return 'u';880881assert(Binding != ELF::STB_WEAK && "STB_WEAK not tested in calling function");882if (Binding != ELF::STB_GLOBAL && Binding != ELF::STB_LOCAL)883return '?';884885elf_section_iterator SecI = *SecIOrErr;886if (SecI != Obj.section_end()) {887uint32_t Type = SecI->getType();888uint64_t Flags = SecI->getFlags();889if (Flags & ELF::SHF_EXECINSTR)890return 't';891if (Type == ELF::SHT_NOBITS)892return 'b';893if (Flags & ELF::SHF_ALLOC)894return Flags & ELF::SHF_WRITE ? 'd' : 'r';895896auto NameOrErr = SecI->getName();897if (!NameOrErr) {898consumeError(NameOrErr.takeError());899return '?';900}901if ((*NameOrErr).starts_with(".debug"))902return 'N';903if (!(Flags & ELF::SHF_WRITE))904return 'n';905}906907return '?';908}909910static char getSymbolNMTypeChar(COFFObjectFile &Obj, symbol_iterator I) {911COFFSymbolRef Symb = Obj.getCOFFSymbol(*I);912// OK, this is COFF.913symbol_iterator SymI(I);914915Expected<StringRef> Name = SymI->getName();916if (!Name) {917consumeError(Name.takeError());918return '?';919}920921char Ret = StringSwitch<char>(*Name)922.StartsWith(".debug", 'N')923.StartsWith(".sxdata", 'N')924.Default('?');925926if (Ret != '?')927return Ret;928929uint32_t Characteristics = 0;930if (!COFF::isReservedSectionNumber(Symb.getSectionNumber())) {931Expected<section_iterator> SecIOrErr = SymI->getSection();932if (!SecIOrErr) {933consumeError(SecIOrErr.takeError());934return '?';935}936section_iterator SecI = *SecIOrErr;937const coff_section *Section = Obj.getCOFFSection(*SecI);938Characteristics = Section->Characteristics;939if (Expected<StringRef> NameOrErr = Obj.getSectionName(Section))940if (NameOrErr->starts_with(".idata"))941return 'i';942}943944switch (Symb.getSectionNumber()) {945case COFF::IMAGE_SYM_DEBUG:946return 'n';947default:948// Check section type.949if (Characteristics & COFF::IMAGE_SCN_CNT_CODE)950return 't';951if (Characteristics & COFF::IMAGE_SCN_CNT_INITIALIZED_DATA)952return Characteristics & COFF::IMAGE_SCN_MEM_WRITE ? 'd' : 'r';953if (Characteristics & COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA)954return 'b';955if (Characteristics & COFF::IMAGE_SCN_LNK_INFO)956return 'i';957// Check for section symbol.958if (Symb.isSectionDefinition())959return 's';960}961962return '?';963}964965static char getSymbolNMTypeChar(XCOFFObjectFile &Obj, symbol_iterator I) {966Expected<uint32_t> TypeOrErr = I->getType();967if (!TypeOrErr) {968warn(TypeOrErr.takeError(), Obj.getFileName(),969"for symbol with index " +970Twine(Obj.getSymbolIndex(I->getRawDataRefImpl().p)));971return '?';972}973974uint32_t SymType = *TypeOrErr;975976if (SymType == SymbolRef::ST_File)977return 'f';978979// If the I->getSection() call would return an error, the earlier I->getType()980// call will already have returned the same error first.981section_iterator SecIter = cantFail(I->getSection());982983if (SecIter == Obj.section_end())984return '?';985986if (Obj.isDebugSection(SecIter->getRawDataRefImpl()))987return 'N';988989if (SecIter->isText())990return 't';991992if (SecIter->isData())993return 'd';994995if (SecIter->isBSS())996return 'b';997998return '?';999}10001001static char getSymbolNMTypeChar(COFFImportFile &Obj) {1002switch (Obj.getCOFFImportHeader()->getType()) {1003case COFF::IMPORT_CODE:1004return 't';1005case COFF::IMPORT_DATA:1006return 'd';1007case COFF::IMPORT_CONST:1008return 'r';1009}1010return '?';1011}10121013static char getSymbolNMTypeChar(MachOObjectFile &Obj, basic_symbol_iterator I) {1014DataRefImpl Symb = I->getRawDataRefImpl();1015uint8_t NType = Obj.is64Bit() ? Obj.getSymbol64TableEntry(Symb).n_type1016: Obj.getSymbolTableEntry(Symb).n_type;10171018if (NType & MachO::N_STAB)1019return '-';10201021switch (NType & MachO::N_TYPE) {1022case MachO::N_ABS:1023return 's';1024case MachO::N_INDR:1025return 'i';1026case MachO::N_SECT: {1027Expected<section_iterator> SecOrErr = Obj.getSymbolSection(Symb);1028if (!SecOrErr) {1029consumeError(SecOrErr.takeError());1030return 's';1031}1032section_iterator Sec = *SecOrErr;1033if (Sec == Obj.section_end())1034return 's';1035DataRefImpl Ref = Sec->getRawDataRefImpl();1036StringRef SectionName;1037if (Expected<StringRef> NameOrErr = Obj.getSectionName(Ref))1038SectionName = *NameOrErr;1039StringRef SegmentName = Obj.getSectionFinalSegmentName(Ref);1040if (Obj.is64Bit() && Obj.getHeader64().filetype == MachO::MH_KEXT_BUNDLE &&1041SegmentName == "__TEXT_EXEC" && SectionName == "__text")1042return 't';1043if (SegmentName == "__TEXT" && SectionName == "__text")1044return 't';1045if (SegmentName == "__DATA" && SectionName == "__data")1046return 'd';1047if (SegmentName == "__DATA" && SectionName == "__bss")1048return 'b';1049return 's';1050}1051}10521053return '?';1054}10551056static char getSymbolNMTypeChar(TapiFile &Obj, basic_symbol_iterator I) {1057auto Type = cantFail(Obj.getSymbolType(I->getRawDataRefImpl()));1058switch (Type) {1059case SymbolRef::ST_Function:1060return 't';1061case SymbolRef::ST_Data:1062if (Obj.hasSegmentInfo())1063return 'd';1064[[fallthrough]];1065default:1066return 's';1067}1068}10691070static char getSymbolNMTypeChar(WasmObjectFile &Obj, basic_symbol_iterator I) {1071uint32_t Flags = cantFail(I->getFlags());1072if (Flags & SymbolRef::SF_Executable)1073return 't';1074return 'd';1075}10761077static char getSymbolNMTypeChar(IRObjectFile &Obj, basic_symbol_iterator I) {1078uint32_t Flags = cantFail(I->getFlags());1079// FIXME: should we print 'b'? At the IR level we cannot be sure if this1080// will be in bss or not, but we could approximate.1081if (Flags & SymbolRef::SF_Executable)1082return 't';1083else if (Triple(Obj.getTargetTriple()).isOSDarwin() &&1084(Flags & SymbolRef::SF_Const))1085return 's';1086else1087return 'd';1088}10891090static bool isObject(SymbolicFile &Obj, basic_symbol_iterator I) {1091return isa<ELFObjectFileBase>(&Obj) &&1092elf_symbol_iterator(I)->getELFType() == ELF::STT_OBJECT;1093}10941095// For ELF object files, Set TypeName to the symbol typename, to be printed1096// in the 'Type' column of the SYSV format output.1097static StringRef getNMTypeName(SymbolicFile &Obj, basic_symbol_iterator I) {1098if (isa<ELFObjectFileBase>(&Obj)) {1099elf_symbol_iterator SymI(I);1100return SymI->getELFTypeName();1101}1102return "";1103}11041105// Return Posix nm class type tag (single letter), but also set SecName and1106// section and name, to be used in format=sysv output.1107static char getNMSectionTagAndName(SymbolicFile &Obj, basic_symbol_iterator I,1108StringRef &SecName) {1109// Symbol Flags have been checked in the caller.1110uint32_t Symflags = cantFail(I->getFlags());1111if (ELFObjectFileBase *ELFObj = dyn_cast<ELFObjectFileBase>(&Obj)) {1112if (Symflags & object::SymbolRef::SF_Absolute)1113SecName = "*ABS*";1114else if (Symflags & object::SymbolRef::SF_Common)1115SecName = "*COM*";1116else if (Symflags & object::SymbolRef::SF_Undefined)1117SecName = "*UND*";1118else {1119elf_symbol_iterator SymI(I);1120Expected<elf_section_iterator> SecIOrErr = SymI->getSection();1121if (!SecIOrErr) {1122consumeError(SecIOrErr.takeError());1123return '?';1124}11251126if (*SecIOrErr == ELFObj->section_end())1127return '?';11281129Expected<StringRef> NameOrErr = (*SecIOrErr)->getName();1130if (!NameOrErr) {1131consumeError(NameOrErr.takeError());1132return '?';1133}1134SecName = *NameOrErr;1135}1136}11371138if (Symflags & object::SymbolRef::SF_Undefined) {1139if (isa<MachOObjectFile>(Obj) || !(Symflags & object::SymbolRef::SF_Weak))1140return 'U';1141return isObject(Obj, I) ? 'v' : 'w';1142}1143if (isa<ELFObjectFileBase>(&Obj))1144if (ELFSymbolRef(*I).getELFType() == ELF::STT_GNU_IFUNC)1145return 'i';1146if (!isa<MachOObjectFile>(Obj) && (Symflags & object::SymbolRef::SF_Weak))1147return isObject(Obj, I) ? 'V' : 'W';11481149if (Symflags & object::SymbolRef::SF_Common)1150return 'C';11511152char Ret = '?';1153if (Symflags & object::SymbolRef::SF_Absolute)1154Ret = 'a';1155else if (IRObjectFile *IR = dyn_cast<IRObjectFile>(&Obj))1156Ret = getSymbolNMTypeChar(*IR, I);1157else if (COFFObjectFile *COFF = dyn_cast<COFFObjectFile>(&Obj))1158Ret = getSymbolNMTypeChar(*COFF, I);1159else if (XCOFFObjectFile *XCOFF = dyn_cast<XCOFFObjectFile>(&Obj))1160Ret = getSymbolNMTypeChar(*XCOFF, I);1161else if (COFFImportFile *COFFImport = dyn_cast<COFFImportFile>(&Obj))1162Ret = getSymbolNMTypeChar(*COFFImport);1163else if (MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(&Obj))1164Ret = getSymbolNMTypeChar(*MachO, I);1165else if (WasmObjectFile *Wasm = dyn_cast<WasmObjectFile>(&Obj))1166Ret = getSymbolNMTypeChar(*Wasm, I);1167else if (TapiFile *Tapi = dyn_cast<TapiFile>(&Obj))1168Ret = getSymbolNMTypeChar(*Tapi, I);1169else if (ELFObjectFileBase *ELF = dyn_cast<ELFObjectFileBase>(&Obj)) {1170Ret = getSymbolNMTypeChar(*ELF, I);1171if (ELFSymbolRef(*I).getBinding() == ELF::STB_GNU_UNIQUE)1172return Ret;1173} else1174llvm_unreachable("unknown binary format");11751176if (!(Symflags & object::SymbolRef::SF_Global))1177return Ret;11781179return toupper(Ret);1180}11811182// getNsectForSegSect() is used to implement the Mach-O "-s segname sectname"1183// option to dump only those symbols from that section in a Mach-O file.1184// It is called once for each Mach-O file from getSymbolNamesFromObject()1185// to get the section number for that named section from the command line1186// arguments. It returns the section number for that section in the Mach-O1187// file or zero it is not present.1188static unsigned getNsectForSegSect(MachOObjectFile *Obj) {1189unsigned Nsect = 1;1190for (auto &S : Obj->sections()) {1191DataRefImpl Ref = S.getRawDataRefImpl();1192StringRef SectionName;1193if (Expected<StringRef> NameOrErr = Obj->getSectionName(Ref))1194SectionName = *NameOrErr;1195StringRef SegmentName = Obj->getSectionFinalSegmentName(Ref);1196if (SegmentName == SegSect[0] && SectionName == SegSect[1])1197return Nsect;1198Nsect++;1199}1200return 0;1201}12021203// getNsectInMachO() is used to implement the Mach-O "-s segname sectname"1204// option to dump only those symbols from that section in a Mach-O file.1205// It is called once for each symbol in a Mach-O file from1206// getSymbolNamesFromObject() and returns the section number for that symbol1207// if it is in a section, else it returns 0.1208static unsigned getNsectInMachO(MachOObjectFile &Obj, BasicSymbolRef Sym) {1209DataRefImpl Symb = Sym.getRawDataRefImpl();1210if (Obj.is64Bit()) {1211MachO::nlist_64 STE = Obj.getSymbol64TableEntry(Symb);1212return (STE.n_type & MachO::N_TYPE) == MachO::N_SECT ? STE.n_sect : 0;1213}1214MachO::nlist STE = Obj.getSymbolTableEntry(Symb);1215return (STE.n_type & MachO::N_TYPE) == MachO::N_SECT ? STE.n_sect : 0;1216}12171218static void dumpSymbolsFromDLInfoMachO(MachOObjectFile &MachO,1219std::vector<NMSymbol> &SymbolList) {1220size_t I = SymbolList.size();1221std::string ExportsNameBuffer;1222raw_string_ostream EOS(ExportsNameBuffer);1223std::string BindsNameBuffer;1224raw_string_ostream BOS(BindsNameBuffer);1225std::string LazysNameBuffer;1226raw_string_ostream LOS(LazysNameBuffer);1227std::string WeaksNameBuffer;1228raw_string_ostream WOS(WeaksNameBuffer);1229std::string FunctionStartsNameBuffer;1230raw_string_ostream FOS(FunctionStartsNameBuffer);12311232MachO::mach_header H;1233MachO::mach_header_64 H_64;1234uint32_t HFlags = 0;1235if (MachO.is64Bit()) {1236H_64 = MachO.MachOObjectFile::getHeader64();1237HFlags = H_64.flags;1238} else {1239H = MachO.MachOObjectFile::getHeader();1240HFlags = H.flags;1241}1242uint64_t BaseSegmentAddress = 0;1243for (const auto &Command : MachO.load_commands()) {1244if (Command.C.cmd == MachO::LC_SEGMENT) {1245MachO::segment_command Seg = MachO.getSegmentLoadCommand(Command);1246if (Seg.fileoff == 0 && Seg.filesize != 0) {1247BaseSegmentAddress = Seg.vmaddr;1248break;1249}1250} else if (Command.C.cmd == MachO::LC_SEGMENT_64) {1251MachO::segment_command_64 Seg = MachO.getSegment64LoadCommand(Command);1252if (Seg.fileoff == 0 && Seg.filesize != 0) {1253BaseSegmentAddress = Seg.vmaddr;1254break;1255}1256}1257}1258if (DyldInfoOnly || AddDyldInfo ||1259HFlags & MachO::MH_NLIST_OUTOFSYNC_WITH_DYLDINFO) {1260unsigned ExportsAdded = 0;1261Error Err = Error::success();1262for (const llvm::object::ExportEntry &Entry : MachO.exports(Err)) {1263bool found = false;1264bool ReExport = false;1265if (!DyldInfoOnly) {1266for (const NMSymbol &S : SymbolList)1267if (S.Address == Entry.address() + BaseSegmentAddress &&1268S.Name == Entry.name()) {1269found = true;1270break;1271}1272}1273if (!found) {1274NMSymbol S = {};1275S.Address = Entry.address() + BaseSegmentAddress;1276S.Size = 0;1277S.TypeChar = '\0';1278S.Name = Entry.name().str();1279// There is no symbol in the nlist symbol table for this so we set1280// Sym effectivly to null and the rest of code in here must test for1281// it and not do things like Sym.getFlags() for it.1282S.Sym = BasicSymbolRef();1283S.SymFlags = SymbolRef::SF_Global;1284S.Section = SectionRef();1285S.NType = 0;1286S.NSect = 0;1287S.NDesc = 0;12881289uint64_t EFlags = Entry.flags();1290bool Abs = ((EFlags & MachO::EXPORT_SYMBOL_FLAGS_KIND_MASK) ==1291MachO::EXPORT_SYMBOL_FLAGS_KIND_ABSOLUTE);1292bool Resolver = (EFlags & MachO::EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER);1293ReExport = (EFlags & MachO::EXPORT_SYMBOL_FLAGS_REEXPORT);1294bool WeakDef = (EFlags & MachO::EXPORT_SYMBOL_FLAGS_WEAK_DEFINITION);1295if (WeakDef)1296S.NDesc |= MachO::N_WEAK_DEF;1297if (Abs) {1298S.NType = MachO::N_EXT | MachO::N_ABS;1299S.TypeChar = 'A';1300} else if (ReExport) {1301S.NType = MachO::N_EXT | MachO::N_INDR;1302S.TypeChar = 'I';1303} else {1304S.NType = MachO::N_EXT | MachO::N_SECT;1305if (Resolver) {1306S.Address = Entry.other() + BaseSegmentAddress;1307if ((S.Address & 1) != 0 && !MachO.is64Bit() &&1308H.cputype == MachO::CPU_TYPE_ARM) {1309S.Address &= ~1LL;1310S.NDesc |= MachO::N_ARM_THUMB_DEF;1311}1312} else {1313S.Address = Entry.address() + BaseSegmentAddress;1314}1315StringRef SegmentName = StringRef();1316StringRef SectionName = StringRef();1317for (const SectionRef &Section : MachO.sections()) {1318S.NSect++;13191320if (Expected<StringRef> NameOrErr = Section.getName())1321SectionName = *NameOrErr;1322else1323consumeError(NameOrErr.takeError());13241325SegmentName =1326MachO.getSectionFinalSegmentName(Section.getRawDataRefImpl());1327if (S.Address >= Section.getAddress() &&1328S.Address < Section.getAddress() + Section.getSize()) {1329S.Section = Section;1330break;1331} else if (Entry.name() == "__mh_execute_header" &&1332SegmentName == "__TEXT" && SectionName == "__text") {1333S.Section = Section;1334S.NDesc |= MachO::REFERENCED_DYNAMICALLY;1335break;1336}1337}1338if (SegmentName == "__TEXT" && SectionName == "__text")1339S.TypeChar = 'T';1340else if (SegmentName == "__DATA" && SectionName == "__data")1341S.TypeChar = 'D';1342else if (SegmentName == "__DATA" && SectionName == "__bss")1343S.TypeChar = 'B';1344else1345S.TypeChar = 'S';1346}1347SymbolList.push_back(S);13481349EOS << Entry.name();1350EOS << '\0';1351ExportsAdded++;13521353// For ReExports there are a two more things to do, first add the1354// indirect name and second create the undefined symbol using the1355// referened dynamic library.1356if (ReExport) {13571358// Add the indirect name.1359if (Entry.otherName().empty())1360EOS << Entry.name();1361else1362EOS << Entry.otherName();1363EOS << '\0';13641365// Now create the undefined symbol using the referened dynamic1366// library.1367NMSymbol U = {};1368U.Address = 0;1369U.Size = 0;1370U.TypeChar = 'U';1371if (Entry.otherName().empty())1372U.Name = Entry.name().str();1373else1374U.Name = Entry.otherName().str();1375// Again there is no symbol in the nlist symbol table for this so1376// we set Sym effectivly to null and the rest of code in here must1377// test for it and not do things like Sym.getFlags() for it.1378U.Sym = BasicSymbolRef();1379U.SymFlags = SymbolRef::SF_Global | SymbolRef::SF_Undefined;1380U.Section = SectionRef();1381U.NType = MachO::N_EXT | MachO::N_UNDF;1382U.NSect = 0;1383U.NDesc = 0;1384// The library ordinal for this undefined symbol is in the export1385// trie Entry.other().1386MachO::SET_LIBRARY_ORDINAL(U.NDesc, Entry.other());1387SymbolList.push_back(U);13881389// Finally add the undefined symbol's name.1390if (Entry.otherName().empty())1391EOS << Entry.name();1392else1393EOS << Entry.otherName();1394EOS << '\0';1395ExportsAdded++;1396}1397}1398}1399if (Err)1400error(std::move(Err), MachO.getFileName());1401// Set the symbol names and indirect names for the added symbols.1402if (ExportsAdded) {1403EOS.flush();1404const char *Q = ExportsNameBuffer.c_str();1405for (unsigned K = 0; K < ExportsAdded; K++) {1406SymbolList[I].Name = Q;1407Q += strlen(Q) + 1;1408if (SymbolList[I].TypeChar == 'I') {1409SymbolList[I].IndirectName = Q;1410Q += strlen(Q) + 1;1411}1412I++;1413}1414}14151416// Add the undefined symbols from the bind entries.1417unsigned BindsAdded = 0;1418Error BErr = Error::success();1419StringRef LastSymbolName = StringRef();1420for (const llvm::object::MachOBindEntry &Entry : MachO.bindTable(BErr)) {1421bool found = false;1422if (LastSymbolName == Entry.symbolName())1423found = true;1424else if (!DyldInfoOnly) {1425for (unsigned J = 0; J < SymbolList.size() && !found; ++J) {1426if (SymbolList[J].Name == Entry.symbolName())1427found = true;1428}1429}1430if (!found) {1431LastSymbolName = Entry.symbolName();1432NMSymbol B = {};1433B.Address = 0;1434B.Size = 0;1435B.TypeChar = 'U';1436// There is no symbol in the nlist symbol table for this so we set1437// Sym effectivly to null and the rest of code in here must test for1438// it and not do things like Sym.getFlags() for it.1439B.Sym = BasicSymbolRef();1440B.SymFlags = SymbolRef::SF_Global | SymbolRef::SF_Undefined;1441B.NType = MachO::N_EXT | MachO::N_UNDF;1442B.NSect = 0;1443B.NDesc = 0;1444MachO::SET_LIBRARY_ORDINAL(B.NDesc, Entry.ordinal());1445B.Name = Entry.symbolName().str();1446SymbolList.push_back(B);1447BOS << Entry.symbolName();1448BOS << '\0';1449BindsAdded++;1450}1451}1452if (BErr)1453error(std::move(BErr), MachO.getFileName());1454// Set the symbol names and indirect names for the added symbols.1455if (BindsAdded) {1456BOS.flush();1457const char *Q = BindsNameBuffer.c_str();1458for (unsigned K = 0; K < BindsAdded; K++) {1459SymbolList[I].Name = Q;1460Q += strlen(Q) + 1;1461if (SymbolList[I].TypeChar == 'I') {1462SymbolList[I].IndirectName = Q;1463Q += strlen(Q) + 1;1464}1465I++;1466}1467}14681469// Add the undefined symbols from the lazy bind entries.1470unsigned LazysAdded = 0;1471Error LErr = Error::success();1472LastSymbolName = StringRef();1473for (const llvm::object::MachOBindEntry &Entry :1474MachO.lazyBindTable(LErr)) {1475bool found = false;1476if (LastSymbolName == Entry.symbolName())1477found = true;1478else {1479// Here we must check to see it this symbol is already in the1480// SymbolList as it might have already have been added above via a1481// non-lazy (bind) entry.1482for (unsigned J = 0; J < SymbolList.size() && !found; ++J) {1483if (SymbolList[J].Name == Entry.symbolName())1484found = true;1485}1486}1487if (!found) {1488LastSymbolName = Entry.symbolName();1489NMSymbol L = {};1490L.Name = Entry.symbolName().str();1491L.Address = 0;1492L.Size = 0;1493L.TypeChar = 'U';1494// There is no symbol in the nlist symbol table for this so we set1495// Sym effectivly to null and the rest of code in here must test for1496// it and not do things like Sym.getFlags() for it.1497L.Sym = BasicSymbolRef();1498L.SymFlags = SymbolRef::SF_Global | SymbolRef::SF_Undefined;1499L.NType = MachO::N_EXT | MachO::N_UNDF;1500L.NSect = 0;1501// The REFERENCE_FLAG_UNDEFINED_LAZY is no longer used but here it1502// makes sence since we are creating this from a lazy bind entry.1503L.NDesc = MachO::REFERENCE_FLAG_UNDEFINED_LAZY;1504MachO::SET_LIBRARY_ORDINAL(L.NDesc, Entry.ordinal());1505SymbolList.push_back(L);1506LOS << Entry.symbolName();1507LOS << '\0';1508LazysAdded++;1509}1510}1511if (LErr)1512error(std::move(LErr), MachO.getFileName());1513// Set the symbol names and indirect names for the added symbols.1514if (LazysAdded) {1515LOS.flush();1516const char *Q = LazysNameBuffer.c_str();1517for (unsigned K = 0; K < LazysAdded; K++) {1518SymbolList[I].Name = Q;1519Q += strlen(Q) + 1;1520if (SymbolList[I].TypeChar == 'I') {1521SymbolList[I].IndirectName = Q;1522Q += strlen(Q) + 1;1523}1524I++;1525}1526}15271528// Add the undefineds symbol from the weak bind entries which are not1529// strong symbols.1530unsigned WeaksAdded = 0;1531Error WErr = Error::success();1532LastSymbolName = StringRef();1533for (const llvm::object::MachOBindEntry &Entry :1534MachO.weakBindTable(WErr)) {1535bool found = false;1536unsigned J = 0;1537if (LastSymbolName == Entry.symbolName() ||1538Entry.flags() & MachO::BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION) {1539found = true;1540} else {1541for (J = 0; J < SymbolList.size() && !found; ++J) {1542if (SymbolList[J].Name == Entry.symbolName()) {1543found = true;1544break;1545}1546}1547}1548if (!found) {1549LastSymbolName = Entry.symbolName();1550NMSymbol W = {};1551W.Name = Entry.symbolName().str();1552W.Address = 0;1553W.Size = 0;1554W.TypeChar = 'U';1555// There is no symbol in the nlist symbol table for this so we set1556// Sym effectivly to null and the rest of code in here must test for1557// it and not do things like Sym.getFlags() for it.1558W.Sym = BasicSymbolRef();1559W.SymFlags = SymbolRef::SF_Global | SymbolRef::SF_Undefined;1560W.NType = MachO::N_EXT | MachO::N_UNDF;1561W.NSect = 0;1562// Odd that we are using N_WEAK_DEF on an undefined symbol but that is1563// what is created in this case by the linker when there are real1564// symbols in the nlist structs.1565W.NDesc = MachO::N_WEAK_DEF;1566SymbolList.push_back(W);1567WOS << Entry.symbolName();1568WOS << '\0';1569WeaksAdded++;1570} else {1571// This is the case the symbol was previously been found and it could1572// have been added from a bind or lazy bind symbol. If so and not1573// a definition also mark it as weak.1574if (SymbolList[J].TypeChar == 'U')1575// See comment above about N_WEAK_DEF.1576SymbolList[J].NDesc |= MachO::N_WEAK_DEF;1577}1578}1579if (WErr)1580error(std::move(WErr), MachO.getFileName());1581// Set the symbol names and indirect names for the added symbols.1582if (WeaksAdded) {1583WOS.flush();1584const char *Q = WeaksNameBuffer.c_str();1585for (unsigned K = 0; K < WeaksAdded; K++) {1586SymbolList[I].Name = Q;1587Q += strlen(Q) + 1;1588if (SymbolList[I].TypeChar == 'I') {1589SymbolList[I].IndirectName = Q;1590Q += strlen(Q) + 1;1591}1592I++;1593}1594}15951596// Trying adding symbol from the function starts table and LC_MAIN entry1597// point.1598SmallVector<uint64_t, 8> FoundFns;1599uint64_t lc_main_offset = UINT64_MAX;1600for (const auto &Command : MachO.load_commands()) {1601if (Command.C.cmd == MachO::LC_FUNCTION_STARTS) {1602// We found a function starts segment, parse the addresses for1603// consumption.1604MachO::linkedit_data_command LLC =1605MachO.getLinkeditDataLoadCommand(Command);16061607MachO.ReadULEB128s(LLC.dataoff, FoundFns);1608} else if (Command.C.cmd == MachO::LC_MAIN) {1609MachO::entry_point_command LCmain = MachO.getEntryPointCommand(Command);1610lc_main_offset = LCmain.entryoff;1611}1612}1613// See if these addresses are already in the symbol table.1614unsigned FunctionStartsAdded = 0;1615for (uint64_t f = 0; f < FoundFns.size(); f++) {1616bool found = false;1617for (unsigned J = 0; J < SymbolList.size() && !found; ++J) {1618if (SymbolList[J].Address == FoundFns[f] + BaseSegmentAddress)1619found = true;1620}1621// See this address is not already in the symbol table fake up an1622// nlist for it.1623if (!found) {1624NMSymbol F = {};1625F.Name = "<redacted function X>";1626F.Address = FoundFns[f] + BaseSegmentAddress;1627F.Size = 0;1628// There is no symbol in the nlist symbol table for this so we set1629// Sym effectivly to null and the rest of code in here must test for1630// it and not do things like Sym.getFlags() for it.1631F.Sym = BasicSymbolRef();1632F.SymFlags = 0;1633F.NType = MachO::N_SECT;1634F.NSect = 0;1635StringRef SegmentName = StringRef();1636StringRef SectionName = StringRef();1637for (const SectionRef &Section : MachO.sections()) {1638if (Expected<StringRef> NameOrErr = Section.getName())1639SectionName = *NameOrErr;1640else1641consumeError(NameOrErr.takeError());16421643SegmentName =1644MachO.getSectionFinalSegmentName(Section.getRawDataRefImpl());1645F.NSect++;1646if (F.Address >= Section.getAddress() &&1647F.Address < Section.getAddress() + Section.getSize()) {1648F.Section = Section;1649break;1650}1651}1652if (SegmentName == "__TEXT" && SectionName == "__text")1653F.TypeChar = 't';1654else if (SegmentName == "__DATA" && SectionName == "__data")1655F.TypeChar = 'd';1656else if (SegmentName == "__DATA" && SectionName == "__bss")1657F.TypeChar = 'b';1658else1659F.TypeChar = 's';1660F.NDesc = 0;1661SymbolList.push_back(F);1662if (FoundFns[f] == lc_main_offset)1663FOS << "<redacted LC_MAIN>";1664else1665FOS << "<redacted function " << f << ">";1666FOS << '\0';1667FunctionStartsAdded++;1668}1669}1670if (FunctionStartsAdded) {1671FOS.flush();1672const char *Q = FunctionStartsNameBuffer.c_str();1673for (unsigned K = 0; K < FunctionStartsAdded; K++) {1674SymbolList[I].Name = Q;1675Q += strlen(Q) + 1;1676if (SymbolList[I].TypeChar == 'I') {1677SymbolList[I].IndirectName = Q;1678Q += strlen(Q) + 1;1679}1680I++;1681}1682}1683}1684}16851686static bool shouldDump(SymbolicFile &Obj) {1687// The -X option is currently only implemented for XCOFF, ELF, and IR object1688// files. The option isn't fundamentally impossible with other formats, just1689// isn't implemented.1690if (!isa<XCOFFObjectFile>(Obj) && !isa<ELFObjectFileBase>(Obj) &&1691!isa<IRObjectFile>(Obj))1692return true;16931694return Obj.is64Bit() ? BitMode != BitModeTy::Bit321695: BitMode != BitModeTy::Bit64;1696}16971698static void getXCOFFExports(XCOFFObjectFile *XCOFFObj,1699std::vector<NMSymbol> &SymbolList,1700StringRef ArchiveName) {1701// Skip Shared object file.1702if (XCOFFObj->getFlags() & XCOFF::F_SHROBJ)1703return;17041705for (SymbolRef Sym : XCOFFObj->symbols()) {1706// There is no visibility in old 32 bit XCOFF object file interpret.1707bool HasVisibilityAttr =1708XCOFFObj->is64Bit() || (XCOFFObj->auxiliaryHeader32() &&1709(XCOFFObj->auxiliaryHeader32()->getVersion() ==1710XCOFF::NEW_XCOFF_INTERPRET));17111712if (HasVisibilityAttr) {1713XCOFFSymbolRef XCOFFSym = XCOFFObj->toSymbolRef(Sym.getRawDataRefImpl());1714uint16_t SymType = XCOFFSym.getSymbolType();1715if ((SymType & XCOFF::VISIBILITY_MASK) == XCOFF::SYM_V_INTERNAL)1716continue;1717if ((SymType & XCOFF::VISIBILITY_MASK) == XCOFF::SYM_V_HIDDEN)1718continue;1719}17201721Expected<section_iterator> SymSecOrErr = Sym.getSection();1722if (!SymSecOrErr) {1723warn(SymSecOrErr.takeError(), XCOFFObj->getFileName(),1724"for symbol with index " +1725Twine(XCOFFObj->getSymbolIndex(Sym.getRawDataRefImpl().p)),1726ArchiveName);1727continue;1728}1729section_iterator SecIter = *SymSecOrErr;1730// If the symbol is not in a text or data section, it is not exported.1731if (SecIter == XCOFFObj->section_end())1732continue;1733if (!(SecIter->isText() || SecIter->isData() || SecIter->isBSS()))1734continue;17351736StringRef SymName = cantFail(Sym.getName());1737if (SymName.empty())1738continue;1739if (SymName.starts_with("__sinit") || SymName.starts_with("__sterm") ||1740SymName.front() == '.' || SymName.front() == '(')1741continue;17421743// Check the SymName regex matching with "^__[0-9]+__".1744if (SymName.size() > 4 && SymName.starts_with("__") &&1745SymName.ends_with("__")) {1746if (std::all_of(SymName.begin() + 2, SymName.end() - 2, isDigit))1747continue;1748}17491750if (SymName == "__rsrc" && NoRsrc)1751continue;17521753if (SymName.starts_with("__tf1"))1754SymName = SymName.substr(6);1755else if (SymName.starts_with("__tf9"))1756SymName = SymName.substr(14);17571758NMSymbol S = {};1759S.Name = SymName.str();1760S.Sym = Sym;17611762if (HasVisibilityAttr) {1763XCOFFSymbolRef XCOFFSym = XCOFFObj->toSymbolRef(Sym.getRawDataRefImpl());1764uint16_t SymType = XCOFFSym.getSymbolType();1765if ((SymType & XCOFF::VISIBILITY_MASK) == XCOFF::SYM_V_PROTECTED)1766S.Visibility = "protected";1767else if ((SymType & XCOFF::VISIBILITY_MASK) == XCOFF::SYM_V_EXPORTED)1768S.Visibility = "export";1769}1770if (S.initializeFlags(*XCOFFObj))1771SymbolList.push_back(S);1772}1773}17741775static Expected<SymbolicFile::basic_symbol_iterator_range>1776getDynamicSyms(SymbolicFile &Obj) {1777const auto *E = dyn_cast<ELFObjectFileBase>(&Obj);1778if (!E)1779return createError("File format has no dynamic symbol table");1780return E->getDynamicSymbolIterators();1781}17821783// Returns false if there is error found or true otherwise.1784static bool getSymbolNamesFromObject(SymbolicFile &Obj,1785std::vector<NMSymbol> &SymbolList) {1786auto Symbols = Obj.symbols();1787std::vector<VersionEntry> SymbolVersions;17881789if (DynamicSyms) {1790Expected<SymbolicFile::basic_symbol_iterator_range> SymbolsOrErr =1791getDynamicSyms(Obj);1792if (!SymbolsOrErr) {1793error(SymbolsOrErr.takeError(), Obj.getFileName());1794return false;1795}1796Symbols = *SymbolsOrErr;1797if (const auto *E = dyn_cast<ELFObjectFileBase>(&Obj)) {1798if (Expected<std::vector<VersionEntry>> VersionsOrErr =1799E->readDynsymVersions())1800SymbolVersions = std::move(*VersionsOrErr);1801else1802WithColor::warning(errs(), ToolName)1803<< "unable to read symbol versions: "1804<< toString(VersionsOrErr.takeError()) << "\n";1805}1806}1807// If a "-s segname sectname" option was specified and this is a Mach-O1808// file get the section number for that section in this object file.1809unsigned int Nsect = 0;1810MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(&Obj);1811if (!SegSect.empty() && MachO) {1812Nsect = getNsectForSegSect(MachO);1813// If this section is not in the object file no symbols are printed.1814if (Nsect == 0)1815return false;1816}18171818if (!(MachO && DyldInfoOnly)) {1819size_t I = -1;1820for (BasicSymbolRef Sym : Symbols) {1821++I;1822Expected<uint32_t> SymFlagsOrErr = Sym.getFlags();1823if (!SymFlagsOrErr) {1824error(SymFlagsOrErr.takeError(), Obj.getFileName());1825return false;1826}18271828// Don't drop format specifc symbols for ARM and AArch64 ELF targets, they1829// are used to repesent mapping symbols and needed to honor the1830// --special-syms option.1831auto *ELFObj = dyn_cast<ELFObjectFileBase>(&Obj);1832bool HasMappingSymbol =1833ELFObj && llvm::is_contained({ELF::EM_ARM, ELF::EM_AARCH64,1834ELF::EM_CSKY, ELF::EM_RISCV},1835ELFObj->getEMachine());1836if (!HasMappingSymbol && !DebugSyms &&1837(*SymFlagsOrErr & SymbolRef::SF_FormatSpecific))1838continue;1839if (WithoutAliases && (*SymFlagsOrErr & SymbolRef::SF_Indirect))1840continue;1841// If a "-s segname sectname" option was specified and this is a Mach-O1842// file and this section appears in this file, Nsect will be non-zero then1843// see if this symbol is a symbol from that section and if not skip it.1844if (Nsect && Nsect != getNsectInMachO(*MachO, Sym))1845continue;1846NMSymbol S = {};1847S.Size = 0;1848S.Address = 0;1849if (isa<ELFObjectFileBase>(&Obj))1850S.Size = ELFSymbolRef(Sym).getSize();18511852if (const XCOFFObjectFile *XCOFFObj =1853dyn_cast<const XCOFFObjectFile>(&Obj))1854S.Size = XCOFFObj->getSymbolSize(Sym.getRawDataRefImpl());18551856if (const WasmObjectFile *WasmObj = dyn_cast<WasmObjectFile>(&Obj))1857S.Size = WasmObj->getSymbolSize(Sym);18581859if (PrintAddress && isa<ObjectFile>(Obj)) {1860SymbolRef SymRef(Sym);1861Expected<uint64_t> AddressOrErr = SymRef.getAddress();1862if (!AddressOrErr) {1863consumeError(AddressOrErr.takeError());1864break;1865}1866S.Address = *AddressOrErr;1867}1868S.TypeName = getNMTypeName(Obj, Sym);1869S.TypeChar = getNMSectionTagAndName(Obj, Sym, S.SectionName);18701871raw_string_ostream OS(S.Name);1872if (Error E = Sym.printName(OS)) {1873if (MachO) {1874OS << "bad string index";1875consumeError(std::move(E));1876} else1877error(std::move(E), Obj.getFileName());1878}1879if (!SymbolVersions.empty() && !SymbolVersions[I].Name.empty())1880S.Name +=1881(SymbolVersions[I].IsVerDef ? "@@" : "@") + SymbolVersions[I].Name;18821883S.Sym = Sym;1884if (S.initializeFlags(Obj))1885SymbolList.push_back(S);1886}1887}18881889// If this is a Mach-O file where the nlist symbol table is out of sync1890// with the dyld export trie then look through exports and fake up symbols1891// for the ones that are missing (also done with the -add-dyldinfo flag).1892// This is needed if strip(1) -T is run on a binary containing swift1893// language symbols for example. The option -only-dyldinfo will fake up1894// all symbols from the dyld export trie as well as the bind info.1895if (MachO && !NoDyldInfo)1896dumpSymbolsFromDLInfoMachO(*MachO, SymbolList);18971898return true;1899}19001901static void printObjectLabel(bool PrintArchiveName, StringRef ArchiveName,1902StringRef ArchitectureName,1903StringRef ObjectFileName) {1904outs() << "\n";1905if (ArchiveName.empty() || !PrintArchiveName)1906outs() << ObjectFileName;1907else1908outs() << ArchiveName << "(" << ObjectFileName << ")";1909if (!ArchitectureName.empty())1910outs() << " (for architecture " << ArchitectureName << ")";1911outs() << ":\n";1912}19131914static Expected<bool> hasSymbols(SymbolicFile &Obj) {1915if (DynamicSyms) {1916Expected<SymbolicFile::basic_symbol_iterator_range> DynamicSymsOrErr =1917getDynamicSyms(Obj);1918if (!DynamicSymsOrErr)1919return DynamicSymsOrErr.takeError();1920return !DynamicSymsOrErr->empty();1921}1922return !Obj.symbols().empty();1923}19241925static void printSymbolNamesFromObject(1926SymbolicFile &Obj, std::vector<NMSymbol> &SymbolList,1927bool PrintSymbolObject, bool PrintObjectLabel, StringRef ArchiveName = {},1928StringRef ArchitectureName = {}, StringRef ObjectName = {},1929bool PrintArchiveName = true) {19301931if (PrintObjectLabel && !ExportSymbols)1932printObjectLabel(PrintArchiveName, ArchiveName, ArchitectureName,1933ObjectName.empty() ? Obj.getFileName() : ObjectName);19341935if (!getSymbolNamesFromObject(Obj, SymbolList) || ExportSymbols)1936return;19371938// If there is an error in hasSymbols(), the error should be encountered in1939// function getSymbolNamesFromObject first.1940if (!cantFail(hasSymbols(Obj)) && SymbolList.empty() && !Quiet) {1941writeFileName(errs(), ArchiveName, ArchitectureName);1942errs() << "no symbols\n";1943}19441945sortSymbolList(SymbolList);1946printSymbolList(Obj, SymbolList, PrintSymbolObject, ArchiveName,1947ArchitectureName);1948}19491950static void dumpSymbolsNameFromMachOFilesetEntry(1951MachOObjectFile *Obj, std::vector<NMSymbol> &SymbolList,1952bool PrintSymbolObject, bool PrintObjectLabel) {1953auto Buf = Obj->getMemoryBufferRef();1954const auto *End = Obj->load_commands().end();1955for (const auto *It = Obj->load_commands().begin(); It != End; ++It) {1956const auto &Command = *It;1957if (Command.C.cmd != MachO::LC_FILESET_ENTRY)1958continue;19591960MachO::fileset_entry_command Entry =1961Obj->getFilesetEntryLoadCommand(Command);1962auto MaybeMachO =1963MachOObjectFile::createMachOObjectFile(Buf, 0, 0, Entry.fileoff);19641965if (Error Err = MaybeMachO.takeError())1966report_fatal_error(std::move(Err));19671968const char *EntryName = Command.Ptr + Entry.entry_id.offset;1969if (EntryName)1970outs() << "Symbols for " << EntryName << ": \n";19711972std::unique_ptr<MachOObjectFile> EntryMachO = std::move(MaybeMachO.get());1973printSymbolNamesFromObject(*EntryMachO, SymbolList, PrintSymbolObject,1974PrintObjectLabel);19751976if (std::next(It) != End)1977outs() << "\n";1978}1979}19801981static void dumpSymbolNamesFromObject(1982SymbolicFile &Obj, std::vector<NMSymbol> &SymbolList,1983bool PrintSymbolObject, bool PrintObjectLabel, StringRef ArchiveName = {},1984StringRef ArchitectureName = {}, StringRef ObjectName = {},1985bool PrintArchiveName = true) {1986if (!shouldDump(Obj))1987return;19881989if (ExportSymbols && Obj.isXCOFF()) {1990XCOFFObjectFile *XCOFFObj = cast<XCOFFObjectFile>(&Obj);1991getXCOFFExports(XCOFFObj, SymbolList, ArchiveName);1992return;1993}19941995CurrentFilename = Obj.getFileName();19961997// Are we handling a MachO of type MH_FILESET?1998if (Obj.isMachO() && Obj.is64Bit() &&1999cast<MachOObjectFile>(&Obj)->getHeader64().filetype ==2000MachO::MH_FILESET) {2001dumpSymbolsNameFromMachOFilesetEntry(cast<MachOObjectFile>(&Obj),2002SymbolList, PrintSymbolObject,2003PrintObjectLabel);2004return;2005}20062007printSymbolNamesFromObject(Obj, SymbolList, PrintSymbolObject,2008PrintObjectLabel, ArchiveName, ArchitectureName,2009ObjectName, PrintArchiveName);2010}20112012// checkMachOAndArchFlags() checks to see if the SymbolicFile is a Mach-O file2013// and if it is and there is a list of architecture flags is specified then2014// check to make sure this Mach-O file is one of those architectures or all2015// architectures was specificed. If not then an error is generated and this2016// routine returns false. Else it returns true.2017static bool checkMachOAndArchFlags(SymbolicFile *O, StringRef Filename) {2018auto *MachO = dyn_cast<MachOObjectFile>(O);20192020if (!MachO || ArchAll || ArchFlags.empty())2021return true;20222023MachO::mach_header H;2024MachO::mach_header_64 H_64;2025Triple T;2026const char *McpuDefault, *ArchFlag;2027if (MachO->is64Bit()) {2028H_64 = MachO->MachOObjectFile::getHeader64();2029T = MachOObjectFile::getArchTriple(H_64.cputype, H_64.cpusubtype,2030&McpuDefault, &ArchFlag);2031} else {2032H = MachO->MachOObjectFile::getHeader();2033T = MachOObjectFile::getArchTriple(H.cputype, H.cpusubtype,2034&McpuDefault, &ArchFlag);2035}2036const std::string ArchFlagName(ArchFlag);2037if (!llvm::is_contained(ArchFlags, ArchFlagName)) {2038error("No architecture specified", Filename);2039return false;2040}2041return true;2042}20432044static void printArchiveMap(iterator_range<Archive::symbol_iterator> &map,2045StringRef Filename) {2046for (auto I : map) {2047Expected<Archive::Child> C = I.getMember();2048if (!C) {2049error(C.takeError(), Filename);2050break;2051}2052Expected<StringRef> FileNameOrErr = C->getName();2053if (!FileNameOrErr) {2054error(FileNameOrErr.takeError(), Filename);2055break;2056}2057StringRef SymName = I.getName();2058outs() << SymName << " in " << FileNameOrErr.get() << "\n";2059}20602061outs() << "\n";2062}20632064static void dumpArchiveMap(Archive *A, StringRef Filename) {2065auto Map = A->symbols();2066if (!Map.empty()) {2067outs() << "Archive map\n";2068printArchiveMap(Map, Filename);2069}20702071auto ECMap = A->ec_symbols();2072if (!ECMap) {2073warn(ECMap.takeError(), Filename);2074} else if (!ECMap->empty()) {2075outs() << "Archive EC map\n";2076printArchiveMap(*ECMap, Filename);2077}2078}20792080static void dumpArchive(Archive *A, std::vector<NMSymbol> &SymbolList,2081StringRef Filename, LLVMContext *ContextPtr) {2082if (ArchiveMap)2083dumpArchiveMap(A, Filename);20842085Error Err = Error::success();2086for (auto &C : A->children(Err)) {2087Expected<std::unique_ptr<Binary>> ChildOrErr = C.getAsBinary(ContextPtr);2088if (!ChildOrErr) {2089if (auto E = isNotObjectErrorInvalidFileType(ChildOrErr.takeError()))2090error(std::move(E), Filename, C);2091continue;2092}2093if (SymbolicFile *O = dyn_cast<SymbolicFile>(&*ChildOrErr.get())) {2094if (!MachOPrintSizeWarning && PrintSize && isa<MachOObjectFile>(O)) {2095WithColor::warning(errs(), ToolName)2096<< "sizes with -print-size for Mach-O files are always zero.\n";2097MachOPrintSizeWarning = true;2098}2099if (!checkMachOAndArchFlags(O, Filename))2100return;2101dumpSymbolNamesFromObject(*O, SymbolList, /*PrintSymbolObject=*/false,2102!PrintFileName, Filename,2103/*ArchitectureName=*/{}, O->getFileName(),2104/*PrintArchiveName=*/false);2105}2106}2107if (Err)2108error(std::move(Err), A->getFileName());2109}21102111static void dumpMachOUniversalBinaryMatchArchFlags(2112MachOUniversalBinary *UB, std::vector<NMSymbol> &SymbolList,2113StringRef Filename, LLVMContext *ContextPtr) {2114// Look for a slice in the universal binary that matches each ArchFlag.2115bool ArchFound;2116for (unsigned i = 0; i < ArchFlags.size(); ++i) {2117ArchFound = false;2118for (MachOUniversalBinary::object_iterator I = UB->begin_objects(),2119E = UB->end_objects();2120I != E; ++I) {2121if (ArchFlags[i] == I->getArchFlagName()) {2122ArchFound = true;2123Expected<std::unique_ptr<ObjectFile>> ObjOrErr = I->getAsObjectFile();2124std::string ArchiveName;2125std::string ArchitectureName;2126ArchiveName.clear();2127ArchitectureName.clear();2128if (ObjOrErr) {2129ObjectFile &Obj = *ObjOrErr.get();2130if (ArchFlags.size() > 1)2131ArchitectureName = I->getArchFlagName();2132dumpSymbolNamesFromObject(Obj, SymbolList,2133/*PrintSymbolObject=*/false,2134(ArchFlags.size() > 1) && !PrintFileName,2135ArchiveName, ArchitectureName);2136} else if (auto E =2137isNotObjectErrorInvalidFileType(ObjOrErr.takeError())) {2138error(std::move(E), Filename,2139ArchFlags.size() > 1 ? StringRef(I->getArchFlagName())2140: StringRef());2141continue;2142} else if (Expected<std::unique_ptr<Archive>> AOrErr =2143I->getAsArchive()) {2144std::unique_ptr<Archive> &A = *AOrErr;2145Error Err = Error::success();2146for (auto &C : A->children(Err)) {2147Expected<std::unique_ptr<Binary>> ChildOrErr =2148C.getAsBinary(ContextPtr);2149if (!ChildOrErr) {2150if (auto E =2151isNotObjectErrorInvalidFileType(ChildOrErr.takeError())) {2152error(std::move(E), Filename, C,2153ArchFlags.size() > 1 ? StringRef(I->getArchFlagName())2154: StringRef());2155}2156continue;2157}2158if (SymbolicFile *O = dyn_cast<SymbolicFile>(&*ChildOrErr.get())) {2159ArchiveName = std::string(A->getFileName());2160if (ArchFlags.size() > 1)2161ArchitectureName = I->getArchFlagName();2162dumpSymbolNamesFromObject(2163*O, SymbolList, /*PrintSymbolObject=*/false, !PrintFileName,2164ArchiveName, ArchitectureName);2165}2166}2167if (Err)2168error(std::move(Err), A->getFileName());2169} else {2170consumeError(AOrErr.takeError());2171error(Filename + " for architecture " +2172StringRef(I->getArchFlagName()) +2173" is not a Mach-O file or an archive file",2174"Mach-O universal file");2175}2176}2177}2178if (!ArchFound) {2179error(ArchFlags[i],2180"file: " + Filename + " does not contain architecture");2181return;2182}2183}2184}21852186// Returns true If the binary contains a slice that matches the host2187// architecture, or false otherwise.2188static bool dumpMachOUniversalBinaryMatchHost(MachOUniversalBinary *UB,2189std::vector<NMSymbol> &SymbolList,2190StringRef Filename,2191LLVMContext *ContextPtr) {2192Triple HostTriple = MachOObjectFile::getHostArch();2193StringRef HostArchName = HostTriple.getArchName();2194for (MachOUniversalBinary::object_iterator I = UB->begin_objects(),2195E = UB->end_objects();2196I != E; ++I) {2197if (HostArchName == I->getArchFlagName()) {2198Expected<std::unique_ptr<ObjectFile>> ObjOrErr = I->getAsObjectFile();2199std::string ArchiveName;2200if (ObjOrErr) {2201ObjectFile &Obj = *ObjOrErr.get();2202dumpSymbolNamesFromObject(Obj, SymbolList, /*PrintSymbolObject=*/false,2203/*PrintObjectLabel=*/false);2204} else if (auto E = isNotObjectErrorInvalidFileType(ObjOrErr.takeError()))2205error(std::move(E), Filename);2206else if (Expected<std::unique_ptr<Archive>> AOrErr = I->getAsArchive()) {2207std::unique_ptr<Archive> &A = *AOrErr;2208Error Err = Error::success();2209for (auto &C : A->children(Err)) {2210Expected<std::unique_ptr<Binary>> ChildOrErr =2211C.getAsBinary(ContextPtr);2212if (!ChildOrErr) {2213if (auto E =2214isNotObjectErrorInvalidFileType(ChildOrErr.takeError()))2215error(std::move(E), Filename, C);2216continue;2217}2218if (SymbolicFile *O = dyn_cast<SymbolicFile>(&*ChildOrErr.get())) {2219ArchiveName = std::string(A->getFileName());2220dumpSymbolNamesFromObject(*O, SymbolList,2221/*PrintSymbolObject=*/false,2222!PrintFileName, ArchiveName);2223}2224}2225if (Err)2226error(std::move(Err), A->getFileName());2227} else {2228consumeError(AOrErr.takeError());2229error(Filename + " for architecture " +2230StringRef(I->getArchFlagName()) +2231" is not a Mach-O file or an archive file",2232"Mach-O universal file");2233}2234return true;2235}2236}2237return false;2238}22392240static void dumpMachOUniversalBinaryArchAll(MachOUniversalBinary *UB,2241std::vector<NMSymbol> &SymbolList,2242StringRef Filename,2243LLVMContext *ContextPtr) {2244bool moreThanOneArch = UB->getNumberOfObjects() > 1;2245for (const MachOUniversalBinary::ObjectForArch &O : UB->objects()) {2246Expected<std::unique_ptr<ObjectFile>> ObjOrErr = O.getAsObjectFile();2247std::string ArchiveName;2248std::string ArchitectureName;2249ArchiveName.clear();2250ArchitectureName.clear();2251if (ObjOrErr) {2252ObjectFile &Obj = *ObjOrErr.get();2253if (isa<MachOObjectFile>(Obj) && moreThanOneArch)2254ArchitectureName = O.getArchFlagName();2255dumpSymbolNamesFromObject(Obj, SymbolList, /*PrintSymbolObject=*/false,2256!PrintFileName, ArchiveName, ArchitectureName);2257} else if (auto E = isNotObjectErrorInvalidFileType(ObjOrErr.takeError())) {2258error(std::move(E), Filename,2259moreThanOneArch ? StringRef(O.getArchFlagName()) : StringRef());2260continue;2261} else if (Expected<std::unique_ptr<Archive>> AOrErr = O.getAsArchive()) {2262std::unique_ptr<Archive> &A = *AOrErr;2263Error Err = Error::success();2264for (auto &C : A->children(Err)) {2265Expected<std::unique_ptr<Binary>> ChildOrErr =2266C.getAsBinary(ContextPtr);2267if (!ChildOrErr) {2268if (auto E = isNotObjectErrorInvalidFileType(ChildOrErr.takeError()))2269error(std::move(E), Filename, C,2270moreThanOneArch ? StringRef(ArchitectureName) : StringRef());2271continue;2272}2273if (SymbolicFile *F = dyn_cast<SymbolicFile>(&*ChildOrErr.get())) {2274ArchiveName = std::string(A->getFileName());2275if (isa<MachOObjectFile>(F) && moreThanOneArch)2276ArchitectureName = O.getArchFlagName();2277dumpSymbolNamesFromObject(*F, SymbolList, /*PrintSymbolObject=*/false,2278!PrintFileName, ArchiveName,2279ArchitectureName);2280}2281}2282if (Err)2283error(std::move(Err), A->getFileName());2284} else {2285consumeError(AOrErr.takeError());2286error(Filename + " for architecture " + StringRef(O.getArchFlagName()) +2287" is not a Mach-O file or an archive file",2288"Mach-O universal file");2289}2290}2291}22922293static void dumpMachOUniversalBinary(MachOUniversalBinary *UB,2294std::vector<NMSymbol> &SymbolList,2295StringRef Filename,2296LLVMContext *ContextPtr) {2297// If we have a list of architecture flags specified dump only those.2298if (!ArchAll && !ArchFlags.empty()) {2299dumpMachOUniversalBinaryMatchArchFlags(UB, SymbolList, Filename,2300ContextPtr);2301return;2302}23032304// No architecture flags were specified so if this contains a slice that2305// matches the host architecture dump only that.2306if (!ArchAll &&2307dumpMachOUniversalBinaryMatchHost(UB, SymbolList, Filename, ContextPtr))2308return;23092310// Either all architectures have been specified or none have been specified2311// and this does not contain the host architecture so dump all the slices.2312dumpMachOUniversalBinaryArchAll(UB, SymbolList, Filename, ContextPtr);2313}23142315static void dumpTapiUniversal(TapiUniversal *TU,2316std::vector<NMSymbol> &SymbolList,2317StringRef Filename) {2318for (const TapiUniversal::ObjectForArch &I : TU->objects()) {2319StringRef ArchName = I.getArchFlagName();2320const bool ShowArch =2321ArchFlags.empty() || llvm::is_contained(ArchFlags, ArchName);2322if (!ShowArch)2323continue;2324if (!AddInlinedInfo && !I.isTopLevelLib())2325continue;2326if (auto ObjOrErr = I.getAsObjectFile())2327dumpSymbolNamesFromObject(2328*ObjOrErr.get(), SymbolList, /*PrintSymbolObject=*/false,2329/*PrintObjectLabel=*/true,2330/*ArchiveName=*/{}, ArchName, I.getInstallName());2331else if (Error E = isNotObjectErrorInvalidFileType(ObjOrErr.takeError())) {2332error(std::move(E), Filename, ArchName);2333}2334}2335}23362337static void dumpSymbolicFile(SymbolicFile *O, std::vector<NMSymbol> &SymbolList,2338StringRef Filename) {2339if (!MachOPrintSizeWarning && PrintSize && isa<MachOObjectFile>(O)) {2340WithColor::warning(errs(), ToolName)2341<< "sizes with --print-size for Mach-O files are always zero.\n";2342MachOPrintSizeWarning = true;2343}2344if (!checkMachOAndArchFlags(O, Filename))2345return;2346dumpSymbolNamesFromObject(*O, SymbolList, /*PrintSymbolObject=*/true,2347/*PrintObjectLabel=*/false);2348}23492350static std::vector<NMSymbol> dumpSymbolNamesFromFile(StringRef Filename) {2351std::vector<NMSymbol> SymbolList;2352ErrorOr<std::unique_ptr<MemoryBuffer>> BufferOrErr =2353MemoryBuffer::getFileOrSTDIN(Filename);2354if (error(BufferOrErr.getError(), Filename))2355return SymbolList;23562357// Ignore AIX linker import files (these files start with "#!"), when2358// exporting symbols.2359const char *BuffStart = (*BufferOrErr)->getBufferStart();2360size_t BufferSize = (*BufferOrErr)->getBufferSize();2361if (ExportSymbols && BufferSize >= 2 && BuffStart[0] == '#' &&2362BuffStart[1] == '!')2363return SymbolList;23642365LLVMContext Context;2366LLVMContext *ContextPtr = NoLLVMBitcode ? nullptr : &Context;2367Expected<std::unique_ptr<Binary>> BinaryOrErr =2368createBinary(BufferOrErr.get()->getMemBufferRef(), ContextPtr);2369if (!BinaryOrErr) {2370error(BinaryOrErr.takeError(), Filename);2371return SymbolList;2372}2373Binary &Bin = *BinaryOrErr.get();2374if (Archive *A = dyn_cast<Archive>(&Bin))2375dumpArchive(A, SymbolList, Filename, ContextPtr);2376else if (MachOUniversalBinary *UB = dyn_cast<MachOUniversalBinary>(&Bin))2377dumpMachOUniversalBinary(UB, SymbolList, Filename, ContextPtr);2378else if (TapiUniversal *TU = dyn_cast<TapiUniversal>(&Bin))2379dumpTapiUniversal(TU, SymbolList, Filename);2380else if (SymbolicFile *O = dyn_cast<SymbolicFile>(&Bin))2381dumpSymbolicFile(O, SymbolList, Filename);2382return SymbolList;2383}23842385static void2386exportSymbolNamesFromFiles(const std::vector<std::string> &InputFilenames) {2387std::vector<NMSymbol> SymbolList;2388for (const auto &FileName : InputFilenames) {2389std::vector<NMSymbol> FileSymList = dumpSymbolNamesFromFile(FileName);2390SymbolList.insert(SymbolList.end(), FileSymList.begin(), FileSymList.end());2391}23922393// Delete symbols which should not be printed from SymolList.2394llvm::erase_if(SymbolList,2395[](const NMSymbol &s) { return !s.shouldPrint(); });2396sortSymbolList(SymbolList);2397SymbolList.erase(llvm::unique(SymbolList), SymbolList.end());2398printExportSymbolList(SymbolList);2399}24002401int llvm_nm_main(int argc, char **argv, const llvm::ToolContext &) {2402BumpPtrAllocator A;2403StringSaver Saver(A);2404NmOptTable Tbl;2405ToolName = argv[0];2406opt::InputArgList Args =2407Tbl.parseArgs(argc, argv, OPT_UNKNOWN, Saver, [&](StringRef Msg) {2408error(Msg);2409exit(1);2410});2411if (Args.hasArg(OPT_help)) {2412Tbl.printHelp(2413outs(),2414(Twine(ToolName) + " [options] <input object files>").str().c_str(),2415"LLVM symbol table dumper");2416// TODO Replace this with OptTable API once it adds extrahelp support.2417outs() << "\nPass @FILE as argument to read options from FILE.\n";2418return 0;2419}2420if (Args.hasArg(OPT_version)) {2421// This needs to contain the word "GNU", libtool looks for that string.2422outs() << "llvm-nm, compatible with GNU nm" << '\n';2423cl::PrintVersionMessage();2424return 0;2425}24262427DebugSyms = Args.hasArg(OPT_debug_syms);2428DefinedOnly = Args.hasArg(OPT_defined_only);2429Demangle = Args.hasFlag(OPT_demangle, OPT_no_demangle, false);2430DynamicSyms = Args.hasArg(OPT_dynamic);2431ExternalOnly = Args.hasArg(OPT_extern_only);2432StringRef V = Args.getLastArgValue(OPT_format_EQ, "bsd");2433if (V == "bsd")2434OutputFormat = bsd;2435else if (V == "posix")2436OutputFormat = posix;2437else if (V == "sysv")2438OutputFormat = sysv;2439else if (V == "darwin")2440OutputFormat = darwin;2441else if (V == "just-symbols")2442OutputFormat = just_symbols;2443else2444error("--format value should be one of: bsd, posix, sysv, darwin, "2445"just-symbols");2446LineNumbers = Args.hasArg(OPT_line_numbers);2447NoLLVMBitcode = Args.hasArg(OPT_no_llvm_bc);2448NoSort = Args.hasArg(OPT_no_sort);2449NoWeakSymbols = Args.hasArg(OPT_no_weak);2450NumericSort = Args.hasArg(OPT_numeric_sort);2451ArchiveMap = Args.hasArg(OPT_print_armap);2452PrintFileName = Args.hasArg(OPT_print_file_name);2453PrintSize = Args.hasArg(OPT_print_size);2454ReverseSort = Args.hasArg(OPT_reverse_sort);2455ExportSymbols = Args.hasArg(OPT_export_symbols);2456if (ExportSymbols) {2457ExternalOnly = true;2458DefinedOnly = true;2459}24602461Quiet = Args.hasArg(OPT_quiet);2462V = Args.getLastArgValue(OPT_radix_EQ, "x");2463if (V == "o")2464AddressRadix = Radix::o;2465else if (V == "d")2466AddressRadix = Radix::d;2467else if (V == "x")2468AddressRadix = Radix::x;2469else2470error("--radix value should be one of: 'o' (octal), 'd' (decimal), 'x' "2471"(hexadecimal)");2472SizeSort = Args.hasArg(OPT_size_sort);2473SpecialSyms = Args.hasArg(OPT_special_syms);2474UndefinedOnly = Args.hasArg(OPT_undefined_only);2475WithoutAliases = Args.hasArg(OPT_without_aliases);24762477// Get BitMode from enviornment variable "OBJECT_MODE" for AIX OS, if2478// specified.2479Triple HostTriple(sys::getProcessTriple());2480if (HostTriple.isOSAIX()) {2481BitMode = StringSwitch<BitModeTy>(getenv("OBJECT_MODE"))2482.Case("32", BitModeTy::Bit32)2483.Case("64", BitModeTy::Bit64)2484.Case("32_64", BitModeTy::Bit32_64)2485.Case("any", BitModeTy::Any)2486.Default(BitModeTy::Bit32);2487} else2488BitMode = BitModeTy::Any;24892490if (Arg *A = Args.getLastArg(OPT_X)) {2491StringRef Mode = A->getValue();2492if (Mode == "32")2493BitMode = BitModeTy::Bit32;2494else if (Mode == "64")2495BitMode = BitModeTy::Bit64;2496else if (Mode == "32_64")2497BitMode = BitModeTy::Bit32_64;2498else if (Mode == "any")2499BitMode = BitModeTy::Any;2500else2501error("-X value should be one of: 32, 64, 32_64, (default) any");2502}25032504// Mach-O specific options.2505FormatMachOasHex = Args.hasArg(OPT_x);2506AddDyldInfo = Args.hasArg(OPT_add_dyldinfo);2507AddInlinedInfo = Args.hasArg(OPT_add_inlinedinfo);2508DyldInfoOnly = Args.hasArg(OPT_dyldinfo_only);2509NoDyldInfo = Args.hasArg(OPT_no_dyldinfo);25102511// XCOFF specific options.2512NoRsrc = Args.hasArg(OPT_no_rsrc);25132514// llvm-nm only reads binary files.2515if (error(sys::ChangeStdinToBinary()))2516return 1;25172518// These calls are needed so that we can read bitcode correctly.2519llvm::InitializeAllTargetInfos();2520llvm::InitializeAllTargetMCs();2521llvm::InitializeAllAsmParsers();25222523// The relative order of these is important. If you pass --size-sort it should2524// only print out the size. However, if you pass -S --size-sort, it should2525// print out both the size and address.2526if (SizeSort && !PrintSize)2527PrintAddress = false;2528if (OutputFormat == sysv || SizeSort)2529PrintSize = true;25302531for (const auto *A : Args.filtered(OPT_arch_EQ)) {2532SmallVector<StringRef, 2> Values;2533llvm::SplitString(A->getValue(), Values, ",");2534for (StringRef V : Values) {2535if (V == "all")2536ArchAll = true;2537else if (MachOObjectFile::isValidArch(V))2538ArchFlags.push_back(V);2539else2540error("Unknown architecture named '" + V + "'",2541"for the --arch option");2542}2543}25442545// Mach-O takes -s to accept two arguments. We emulate this by iterating over2546// both OPT_s and OPT_INPUT.2547std::vector<std::string> InputFilenames;2548int SegSectArgs = 0;2549for (opt::Arg *A : Args.filtered(OPT_s, OPT_INPUT)) {2550if (SegSectArgs > 0) {2551--SegSectArgs;2552SegSect.push_back(A->getValue());2553} else if (A->getOption().matches(OPT_s)) {2554SegSectArgs = 2;2555} else {2556InputFilenames.push_back(A->getValue());2557}2558}2559if (!SegSect.empty() && SegSect.size() != 2)2560error("bad number of arguments (must be two arguments)",2561"for the -s option");25622563if (InputFilenames.empty())2564InputFilenames.push_back("a.out");2565if (InputFilenames.size() > 1)2566MultipleFiles = true;25672568if (NoDyldInfo && (AddDyldInfo || DyldInfoOnly))2569error("--no-dyldinfo can't be used with --add-dyldinfo or --dyldinfo-only");25702571if (ExportSymbols)2572exportSymbolNamesFromFiles(InputFilenames);2573else2574llvm::for_each(InputFilenames, dumpSymbolNamesFromFile);25752576if (HadError)2577return 1;2578return 0;2579}258025812582