X-Git-Url: http://plrg.eecs.uci.edu/git/?p=oota-llvm.git;a=blobdiff_plain;f=tools%2Fllvm-nm%2Fllvm-nm.cpp;h=ce12fe6bc0e1c85663ee6e67f82b6187734aecdf;hp=e26bc650f0d283cbfb9bf850022d1c7996f01e92;hb=e84d8c12d5157a926db15976389f703809c49aa5;hpb=c28eff1356f0a1c214c7dfda70a2090446826432 diff --git a/tools/llvm-nm/llvm-nm.cpp b/tools/llvm-nm/llvm-nm.cpp index e26bc650f0d..ce12fe6bc0e 100644 --- a/tools/llvm-nm/llvm-nm.cpp +++ b/tools/llvm-nm/llvm-nm.cpp @@ -36,6 +36,7 @@ #include "llvm/Support/PrettyStackTrace.h" #include "llvm/Support/Program.h" #include "llvm/Support/Signals.h" +#include "llvm/Support/TargetSelect.h" #include "llvm/Support/raw_ostream.h" #include #include @@ -73,6 +74,8 @@ cl::alias DynamicSyms2("D", cl::desc("Alias for --dynamic"), cl::opt DefinedOnly("defined-only", cl::desc("Show only defined symbols")); +cl::alias DefinedOnly2("U", cl::desc("Alias for --defined-only"), + cl::aliasopt(DefinedOnly)); cl::opt ExternalOnly("extern-only", cl::desc("Show only external symbols")); @@ -83,9 +86,9 @@ cl::opt BSDFormat("B", cl::desc("Alias for --format=bsd")); cl::opt POSIXFormat("P", cl::desc("Alias for --format=posix")); cl::opt DarwinFormat("m", cl::desc("Alias for --format=darwin")); -static cl::list ArchFlags("arch", - cl::desc("architecture(s) from a Mach-O file to dump"), - cl::ZeroOrMore); +static cl::list + ArchFlags("arch", cl::desc("architecture(s) from a Mach-O file to dump"), + cl::ZeroOrMore); bool ArchAll = false; cl::opt PrintFileName( @@ -111,6 +114,10 @@ cl::alias NumericSortv("v", cl::desc("Alias for --numeric-sort"), cl::opt NoSort("no-sort", cl::desc("Show symbols in order encountered")); cl::alias NoSortp("p", cl::desc("Alias for --no-sort"), cl::aliasopt(NoSort)); +cl::opt ReverseSort("reverse-sort", cl::desc("Sort in reverse order")); +cl::alias ReverseSortr("r", cl::desc("Alias for --reverse-sort"), + cl::aliasopt(ReverseSort)); + cl::opt PrintSize("print-size", cl::desc("Show symbol size instead of address")); cl::alias PrintSizeS("S", cl::desc("Alias for --print-size"), @@ -122,8 +129,29 @@ cl::opt WithoutAliases("without-aliases", cl::Hidden, cl::desc("Exclude aliases from output")); cl::opt ArchiveMap("print-armap", cl::desc("Print the archive map")); -cl::alias ArchiveMaps("s", cl::desc("Alias for --print-armap"), +cl::alias ArchiveMaps("M", cl::desc("Alias for --print-armap"), cl::aliasopt(ArchiveMap)); + +cl::opt JustSymbolName("just-symbol-name", + cl::desc("Print just the symbol's name")); +cl::alias JustSymbolNames("j", cl::desc("Alias for --just-symbol-name"), + cl::aliasopt(JustSymbolName)); + +// FIXME: This option takes exactly two strings and should be allowed anywhere +// on the command line. Such that "llvm-nm -s __TEXT __text foo.o" would work. +// But that does not as the CommandLine Library does not have a way to make +// this work. For now the "-s __TEXT __text" has to be last on the command +// line. +cl::list SegSect("s", cl::Positional, cl::ZeroOrMore, + cl::desc("Dump only symbols from this segment " + "and section name, Mach-O only")); + +cl::opt FormatMachOasHex("x", cl::desc("Print symbol entry in hex, " + "Mach-O only")); + +cl::opt NoLLVMBitcode("no-llvm-bc", + cl::desc("Disable LLVM bitcode reader")); + bool PrintAddress = true; bool MultipleFiles = false; @@ -152,60 +180,35 @@ struct NMSymbol { uint64_t Size; char TypeChar; StringRef Name; - DataRefImpl Symb; + BasicSymbolRef Sym; }; } static bool compareSymbolAddress(const NMSymbol &A, const NMSymbol &B) { - if (A.Address < B.Address) - return true; - else if (A.Address == B.Address && A.Name < B.Name) - return true; - else if (A.Address == B.Address && A.Name == B.Name && A.Size < B.Size) - return true; - else - return false; + bool ADefined = !(A.Sym.getFlags() & SymbolRef::SF_Undefined); + bool BDefined = !(B.Sym.getFlags() & SymbolRef::SF_Undefined); + return std::make_tuple(ADefined, A.Address, A.Name, A.Size) < + std::make_tuple(BDefined, B.Address, B.Name, B.Size); } static bool compareSymbolSize(const NMSymbol &A, const NMSymbol &B) { - if (A.Size < B.Size) - return true; - else if (A.Size == B.Size && A.Name < B.Name) - return true; - else if (A.Size == B.Size && A.Name == B.Name && A.Address < B.Address) - return true; - else - return false; + return std::make_tuple(A.Size, A.Name, A.Address) < + std::make_tuple(B.Size, B.Name, B.Address); } static bool compareSymbolName(const NMSymbol &A, const NMSymbol &B) { - if (A.Name < B.Name) - return true; - else if (A.Name == B.Name && A.Size < B.Size) - return true; - else if (A.Name == B.Name && A.Size == B.Size && A.Address < B.Address) - return true; - else - return false; + return std::make_tuple(A.Name, A.Size, A.Address) < + std::make_tuple(B.Name, B.Size, B.Address); } -static char isSymbolList64Bit(SymbolicFile *Obj) { +static char isSymbolList64Bit(SymbolicFile &Obj) { if (isa(Obj)) return false; - else if (isa(Obj)) + if (isa(Obj)) return false; - else if (MachOObjectFile *MachO = dyn_cast(Obj)) + if (MachOObjectFile *MachO = dyn_cast(&Obj)) return MachO->is64Bit(); - else if (isa(Obj)) - return false; - else if (isa(Obj)) - return true; - else if (isa(Obj)) - return false; - else if(isa(Obj)) - return true; - else - return false; + return cast(Obj).getBytesInAddress() == 8; } static StringRef CurrentFilename; @@ -213,8 +216,10 @@ typedef std::vector SymbolListT; static SymbolListT SymbolList; // darwinPrintSymbol() is used to print a symbol from a Mach-O file when the -// the OutputFormat is darwin. It produces the same output as darwin's nm(1) -m -// output. +// the OutputFormat is darwin or we are printing Mach-O symbols in hex. For +// the darwin format it produces the same output as darwin's nm(1) -m output +// and when printing Mach-O symbols in hex it produces the same output as +// darwin's nm(1) -x format. static void darwinPrintSymbol(MachOObjectFile *MachO, SymbolListT::iterator I, char *SymbolAddrStr, const char *printBlanks) { MachO::mach_header H; @@ -223,26 +228,55 @@ static void darwinPrintSymbol(MachOObjectFile *MachO, SymbolListT::iterator I, MachO::nlist_64 STE_64; MachO::nlist STE; uint8_t NType; + uint8_t NSect; uint16_t NDesc; + uint32_t NStrx; uint64_t NValue; + DataRefImpl SymDRI = I->Sym.getRawDataRefImpl(); if (MachO->is64Bit()) { H_64 = MachO->MachOObjectFile::getHeader64(); Filetype = H_64.filetype; Flags = H_64.flags; - STE_64 = MachO->getSymbol64TableEntry(I->Symb); + STE_64 = MachO->getSymbol64TableEntry(SymDRI); NType = STE_64.n_type; + NSect = STE_64.n_sect; NDesc = STE_64.n_desc; + NStrx = STE_64.n_strx; NValue = STE_64.n_value; } else { H = MachO->MachOObjectFile::getHeader(); Filetype = H.filetype; Flags = H.flags; - STE = MachO->getSymbolTableEntry(I->Symb); + STE = MachO->getSymbolTableEntry(SymDRI); NType = STE.n_type; + NSect = STE.n_sect; NDesc = STE.n_desc; + NStrx = STE.n_strx; NValue = STE.n_value; } + // If we are printing Mach-O symbols in hex do that and return. + if (FormatMachOasHex) { + char Str[18] = ""; + const char *printFormat; + if (MachO->is64Bit()) + printFormat = "%016" PRIx64; + else + printFormat = "%08" PRIx64; + format(printFormat, NValue).print(Str, sizeof(Str)); + outs() << Str << ' '; + format("%02x", NType).print(Str, sizeof(Str)); + outs() << Str << ' '; + format("%02x", NSect).print(Str, sizeof(Str)); + outs() << Str << ' '; + format("%04x", NDesc).print(Str, sizeof(Str)); + outs() << Str << ' '; + format("%08x", NStrx).print(Str, sizeof(Str)); + outs() << Str << ' '; + outs() << I->Name << "\n"; + return; + } + if (PrintAddress) { if ((NType & MachO::N_TYPE) == MachO::N_INDR) strcpy(SymbolAddrStr, printBlanks); @@ -254,8 +288,7 @@ static void darwinPrintSymbol(MachOObjectFile *MachO, SymbolListT::iterator I, if (NValue != 0) { outs() << "(common) "; if (MachO::GET_COMM_ALIGN(NDesc) != 0) - outs() << "(alignment 2^" << - (int)MachO::GET_COMM_ALIGN(NDesc) << ") "; + outs() << "(alignment 2^" << (int)MachO::GET_COMM_ALIGN(NDesc) << ") "; } else { if ((NType & MachO::N_TYPE) == MachO::N_PBUD) outs() << "(prebound "; @@ -281,8 +314,7 @@ static void darwinPrintSymbol(MachOObjectFile *MachO, SymbolListT::iterator I, outs() << "(indirect) "; break; case MachO::N_SECT: { - section_iterator Sec = MachO->section_end(); - MachO->getSymbolSection(I->Symb, Sec); + section_iterator Sec = *MachO->getSymbolSection(I->Sym.getRawDataRefImpl()); DataRefImpl Ref = Sec->getRawDataRefImpl(); StringRef SectionName; MachO->getSectionName(Ref, SectionName); @@ -300,19 +332,18 @@ static void darwinPrintSymbol(MachOObjectFile *MachO, SymbolListT::iterator I, outs() << "[referenced dynamically] "; if (NType & MachO::N_PEXT) { if ((NDesc & MachO::N_WEAK_DEF) == MachO::N_WEAK_DEF) - outs() << "weak private external "; + outs() << "weak private external "; else - outs() << "private external "; + outs() << "private external "; } else { if ((NDesc & MachO::N_WEAK_REF) == MachO::N_WEAK_REF || - (NDesc & MachO::N_WEAK_DEF) == MachO::N_WEAK_DEF){ + (NDesc & MachO::N_WEAK_DEF) == MachO::N_WEAK_DEF) { if ((NDesc & (MachO::N_WEAK_REF | MachO::N_WEAK_DEF)) == (MachO::N_WEAK_REF | MachO::N_WEAK_DEF)) outs() << "weak external automatically hidden "; else outs() << "weak external "; - } - else + } else outs() << "external "; } } else { @@ -342,17 +373,15 @@ static void darwinPrintSymbol(MachOObjectFile *MachO, SymbolListT::iterator I, if ((NType & MachO::N_TYPE) == MachO::N_INDR) { outs() << I->Name << " (for "; StringRef IndirectName; - if (MachO->getIndirectName(I->Symb, IndirectName)) + if (MachO->getIndirectName(I->Sym.getRawDataRefImpl(), IndirectName)) outs() << "?)"; else outs() << IndirectName << ")"; - } - else + } else outs() << I->Name; if ((Flags & MachO::MH_TWOLEVEL) == MachO::MH_TWOLEVEL && - (((NType & MachO::N_TYPE) == MachO::N_UNDF && - NValue == 0) || + (((NType & MachO::N_TYPE) == MachO::N_UNDF && NValue == 0) || (NType & MachO::N_TYPE) == MachO::N_PBUD)) { uint32_t LibraryOrdinal = MachO::GET_LIBRARY_ORDINAL(NDesc); if (LibraryOrdinal != 0) { @@ -362,10 +391,8 @@ static void darwinPrintSymbol(MachOObjectFile *MachO, SymbolListT::iterator I, outs() << " (dynamically looked up)"; else { StringRef LibraryName; - if (MachO->getLibraryShortNameByIndex(LibraryOrdinal - 1, - LibraryName)) - outs() << " (from bad library ordinal " << - LibraryOrdinal << ")"; + if (MachO->getLibraryShortNameByIndex(LibraryOrdinal - 1, LibraryName)) + outs() << " (from bad library ordinal " << LibraryOrdinal << ")"; else outs() << " (from " << LibraryName << ")"; } @@ -375,24 +402,112 @@ static void darwinPrintSymbol(MachOObjectFile *MachO, SymbolListT::iterator I, outs() << "\n"; } -static void sortAndPrintSymbolList(SymbolicFile *Obj, bool printName) { +// Table that maps Darwin's Mach-O stab constants to strings to allow printing. +struct DarwinStabName { + uint8_t NType; + const char *Name; +}; +static const struct DarwinStabName DarwinStabNames[] = { + {MachO::N_GSYM, "GSYM"}, + {MachO::N_FNAME, "FNAME"}, + {MachO::N_FUN, "FUN"}, + {MachO::N_STSYM, "STSYM"}, + {MachO::N_LCSYM, "LCSYM"}, + {MachO::N_BNSYM, "BNSYM"}, + {MachO::N_PC, "PC"}, + {MachO::N_AST, "AST"}, + {MachO::N_OPT, "OPT"}, + {MachO::N_RSYM, "RSYM"}, + {MachO::N_SLINE, "SLINE"}, + {MachO::N_ENSYM, "ENSYM"}, + {MachO::N_SSYM, "SSYM"}, + {MachO::N_SO, "SO"}, + {MachO::N_OSO, "OSO"}, + {MachO::N_LSYM, "LSYM"}, + {MachO::N_BINCL, "BINCL"}, + {MachO::N_SOL, "SOL"}, + {MachO::N_PARAMS, "PARAM"}, + {MachO::N_VERSION, "VERS"}, + {MachO::N_OLEVEL, "OLEV"}, + {MachO::N_PSYM, "PSYM"}, + {MachO::N_EINCL, "EINCL"}, + {MachO::N_ENTRY, "ENTRY"}, + {MachO::N_LBRAC, "LBRAC"}, + {MachO::N_EXCL, "EXCL"}, + {MachO::N_RBRAC, "RBRAC"}, + {MachO::N_BCOMM, "BCOMM"}, + {MachO::N_ECOMM, "ECOMM"}, + {MachO::N_ECOML, "ECOML"}, + {MachO::N_LENG, "LENG"}, + {0, 0}}; +static const char *getDarwinStabString(uint8_t NType) { + for (unsigned i = 0; DarwinStabNames[i].Name; i++) { + if (DarwinStabNames[i].NType == NType) + return DarwinStabNames[i].Name; + } + return 0; +} + +// darwinPrintStab() prints the n_sect, n_desc along with a symbolic name of +// a stab n_type value in a Mach-O file. +static void darwinPrintStab(MachOObjectFile *MachO, SymbolListT::iterator I) { + MachO::nlist_64 STE_64; + MachO::nlist STE; + uint8_t NType; + uint8_t NSect; + uint16_t NDesc; + DataRefImpl SymDRI = I->Sym.getRawDataRefImpl(); + if (MachO->is64Bit()) { + STE_64 = MachO->getSymbol64TableEntry(SymDRI); + NType = STE_64.n_type; + NSect = STE_64.n_sect; + NDesc = STE_64.n_desc; + } else { + STE = MachO->getSymbolTableEntry(SymDRI); + NType = STE.n_type; + NSect = STE.n_sect; + NDesc = STE.n_desc; + } + + char Str[18] = ""; + format("%02x", NSect).print(Str, sizeof(Str)); + outs() << ' ' << Str << ' '; + format("%04x", NDesc).print(Str, sizeof(Str)); + outs() << Str << ' '; + if (const char *stabString = getDarwinStabString(NType)) + format("%5.5s", stabString).print(Str, sizeof(Str)); + else + format(" %02x", NType).print(Str, sizeof(Str)); + outs() << Str; +} + +static void sortAndPrintSymbolList(SymbolicFile &Obj, bool printName, + std::string ArchiveName, + std::string ArchitectureName) { if (!NoSort) { + std::function Cmp; if (NumericSort) - std::sort(SymbolList.begin(), SymbolList.end(), compareSymbolAddress); + Cmp = compareSymbolAddress; else if (SizeSort) - std::sort(SymbolList.begin(), SymbolList.end(), compareSymbolSize); + Cmp = compareSymbolSize; else - std::sort(SymbolList.begin(), SymbolList.end(), compareSymbolName); + Cmp = compareSymbolName; + + if (ReverseSort) + Cmp = [=](const NMSymbol &A, const NMSymbol &B) { return Cmp(B, A); }; + std::sort(SymbolList.begin(), SymbolList.end(), Cmp); } - if (OutputFormat == posix && MultipleFiles && printName) { - outs() << '\n' << CurrentFilename << ":\n"; - } else if (OutputFormat == bsd && MultipleFiles && printName) { - outs() << "\n" << CurrentFilename << ":\n"; - } else if (OutputFormat == sysv) { - outs() << "\n\nSymbols from " << CurrentFilename << ":\n\n" - << "Name Value Class Type" - << " Size Line Section\n"; + if (!PrintFileName) { + if (OutputFormat == posix && MultipleFiles && printName) { + outs() << '\n' << CurrentFilename << ":\n"; + } else if (OutputFormat == bsd && MultipleFiles && printName) { + outs() << "\n" << CurrentFilename << ":\n"; + } else if (OutputFormat == sysv) { + outs() << "\n\nSymbols from " << CurrentFilename << ":\n\n" + << "Name Value Class Type" + << " Size Line Section\n"; + } } const char *printBlanks, *printFormat; @@ -406,32 +521,46 @@ static void sortAndPrintSymbolList(SymbolicFile *Obj, bool printName) { for (SymbolListT::iterator I = SymbolList.begin(), E = SymbolList.end(); I != E; ++I) { - if ((I->TypeChar != 'U') && UndefinedOnly) + uint32_t SymFlags = I->Sym.getFlags(); + bool Undefined = SymFlags & SymbolRef::SF_Undefined; + if (!Undefined && UndefinedOnly) continue; - if ((I->TypeChar == 'U') && DefinedOnly) + if (Undefined && DefinedOnly) continue; - if (SizeSort && !PrintAddress && I->Size == UnknownAddressOrSize) + if (SizeSort && !PrintAddress) continue; + if (PrintFileName) { + if (!ArchitectureName.empty()) + outs() << "(for architecture " << ArchitectureName << "):"; + if (!ArchiveName.empty()) + outs() << ArchiveName << ":"; + outs() << CurrentFilename << ": "; + } + if (JustSymbolName || (UndefinedOnly && isa(Obj))) { + outs() << I->Name << "\n"; + continue; + } char SymbolAddrStr[18] = ""; char SymbolSizeStr[18] = ""; - if (OutputFormat == sysv || I->Address == UnknownAddressOrSize) + if (OutputFormat == sysv || I->TypeChar == 'U') strcpy(SymbolAddrStr, printBlanks); if (OutputFormat == sysv) strcpy(SymbolSizeStr, printBlanks); - if (I->Address != UnknownAddressOrSize) + if (I->TypeChar != 'U') format(printFormat, I->Address) .print(SymbolAddrStr, sizeof(SymbolAddrStr)); - if (I->Size != UnknownAddressOrSize) - format(printFormat, I->Size).print(SymbolSizeStr, sizeof(SymbolSizeStr)); - - // If OutputFormat is darwin and we have a MachOObjectFile print as darwin's - // nm(1) -m output, else if OutputFormat is darwin and not a Mach-O object - // fall back to OutputFormat bsd (see below). - MachOObjectFile *MachO = dyn_cast(Obj); - if (OutputFormat == darwin && MachO) { + format(printFormat, I->Size).print(SymbolSizeStr, sizeof(SymbolSizeStr)); + + // If OutputFormat is darwin or we are printing Mach-O symbols in hex and + // we have a MachOObjectFile, call darwinPrintSymbol to print as darwin's + // nm(1) -m output or hex, else if OutputFormat is darwin or we are + // printing Mach-O symbols in hex and not a Mach-O object fall back to + // OutputFormat bsd (see below). + MachOObjectFile *MachO = dyn_cast(&Obj); + if ((OutputFormat == darwin || FormatMachOasHex) && MachO) { darwinPrintSymbol(MachO, I, SymbolAddrStr, printBlanks); } else if (OutputFormat == posix) { outs() << I->Name << " " << I->TypeChar << " " << SymbolAddrStr @@ -441,10 +570,12 @@ static void sortAndPrintSymbolList(SymbolicFile *Obj, bool printName) { outs() << SymbolAddrStr << ' '; if (PrintSize) { outs() << SymbolSizeStr; - if (I->Size != UnknownAddressOrSize) - outs() << ' '; + outs() << ' '; } - outs() << I->TypeChar << " " << I->Name << "\n"; + outs() << I->TypeChar; + if (I->TypeChar == '-' && MachO) + darwinPrintStab(MachO, I); + outs() << " " << I->Name << "\n"; } else if (OutputFormat == sysv) { std::string PaddedName(I->Name); while (PaddedName.length() < 20) @@ -457,33 +588,29 @@ static void sortAndPrintSymbolList(SymbolicFile *Obj, bool printName) { SymbolList.clear(); } -template -static char getSymbolNMTypeChar(ELFObjectFile &Obj, +static char getSymbolNMTypeChar(ELFObjectFileBase &Obj, basic_symbol_iterator I) { - typedef typename ELFObjectFile::Elf_Sym Elf_Sym; - typedef typename ELFObjectFile::Elf_Shdr Elf_Shdr; - // OK, this is ELF - symbol_iterator SymI(I); + elf_symbol_iterator SymI(I); - DataRefImpl Symb = I->getRawDataRefImpl(); - const Elf_Sym *ESym = Obj.getSymbol(Symb); - const ELFFile &EF = *Obj.getELFFile(); - const Elf_Shdr *ESec = EF.getSection(ESym); + ErrorOr SecIOrErr = SymI->getSection(); + if (error(SecIOrErr.getError())) + return '?'; - if (ESec) { - switch (ESec->sh_type) { + elf_section_iterator SecI = *SecIOrErr; + if (SecI != Obj.section_end()) { + switch (SecI->getType()) { case ELF::SHT_PROGBITS: case ELF::SHT_DYNAMIC: - switch (ESec->sh_flags) { - case(ELF::SHF_ALLOC | ELF::SHF_EXECINSTR) : + switch (SecI->getFlags()) { + case (ELF::SHF_ALLOC | ELF::SHF_EXECINSTR): return 't'; - case(ELF::SHF_TLS | ELF::SHF_ALLOC | ELF::SHF_WRITE) : - case(ELF::SHF_ALLOC | ELF::SHF_WRITE) : + case (ELF::SHF_TLS | ELF::SHF_ALLOC | ELF::SHF_WRITE): + case (ELF::SHF_ALLOC | ELF::SHF_WRITE): return 'd'; case ELF::SHF_ALLOC: - case(ELF::SHF_ALLOC | ELF::SHF_MERGE) : - case(ELF::SHF_ALLOC | ELF::SHF_MERGE | ELF::SHF_STRINGS) : + case (ELF::SHF_ALLOC | ELF::SHF_MERGE): + case (ELF::SHF_ALLOC | ELF::SHF_MERGE | ELF::SHF_STRINGS): return 'r'; } break; @@ -492,29 +619,29 @@ static char getSymbolNMTypeChar(ELFObjectFile &Obj, } } - if (ESym->getType() == ELF::STT_SECTION) { - StringRef Name; - if (error(SymI->getName(Name))) + if (SymI->getELFType() == ELF::STT_SECTION) { + ErrorOr Name = SymI->getName(); + if (error(Name.getError())) return '?'; - return StringSwitch(Name) + return StringSwitch(*Name) .StartsWith(".debug", 'N') .StartsWith(".note", 'n') .Default('?'); } - return '?'; + return 'n'; } static char getSymbolNMTypeChar(COFFObjectFile &Obj, symbol_iterator I) { - const coff_symbol *Symb = Obj.getCOFFSymbol(*I); + COFFSymbolRef Symb = Obj.getCOFFSymbol(*I); // OK, this is COFF. symbol_iterator SymI(I); - StringRef Name; - if (error(SymI->getName(Name))) + ErrorOr Name = SymI->getName(); + if (error(Name.getError())) return '?'; - char Ret = StringSwitch(Name) + char Ret = StringSwitch(*Name) .StartsWith(".debug", 'N') .StartsWith(".sxdata", 'N') .Default('?'); @@ -523,33 +650,30 @@ static char getSymbolNMTypeChar(COFFObjectFile &Obj, symbol_iterator I) { return Ret; uint32_t Characteristics = 0; - if (!COFF::isReservedSectionNumber(Symb->SectionNumber)) { - section_iterator SecI = Obj.section_end(); - if (error(SymI->getSection(SecI))) + if (!COFF::isReservedSectionNumber(Symb.getSectionNumber())) { + ErrorOr SecIOrErr = SymI->getSection(); + if (error(SecIOrErr.getError())) return '?'; + section_iterator SecI = *SecIOrErr; const coff_section *Section = Obj.getCOFFSection(*SecI); Characteristics = Section->Characteristics; } - switch (Symb->SectionNumber) { + switch (Symb.getSectionNumber()) { case COFF::IMAGE_SYM_DEBUG: return 'n'; default: // Check section type. if (Characteristics & COFF::IMAGE_SCN_CNT_CODE) return 't'; - else if (Characteristics & COFF::IMAGE_SCN_MEM_READ && - ~Characteristics & COFF::IMAGE_SCN_MEM_WRITE) // Read only. - return 'r'; - else if (Characteristics & COFF::IMAGE_SCN_CNT_INITIALIZED_DATA) - return 'd'; - else if (Characteristics & COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA) + if (Characteristics & COFF::IMAGE_SCN_CNT_INITIALIZED_DATA) + return Characteristics & COFF::IMAGE_SCN_MEM_WRITE ? 'd' : 'r'; + if (Characteristics & COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA) return 'b'; - else if (Characteristics & COFF::IMAGE_SCN_LNK_INFO) + if (Characteristics & COFF::IMAGE_SCN_LNK_INFO) return 'i'; - // Check for section symbol. - else if (Symb->isSectionDefinition()) + if (Symb.isSectionDefinition()) return 's'; } @@ -569,14 +693,16 @@ static char getSymbolNMTypeChar(MachOObjectFile &Obj, basic_symbol_iterator I) { DataRefImpl Symb = I->getRawDataRefImpl(); uint8_t NType = getNType(Obj, Symb); + if (NType & MachO::N_STAB) + return '-'; + switch (NType & MachO::N_TYPE) { case MachO::N_ABS: return 's'; case MachO::N_INDR: return 'i'; case MachO::N_SECT: { - section_iterator Sec = Obj.section_end(); - Obj.getSymbolSection(Symb, Sec); + section_iterator Sec = *Obj.getSymbolSection(Symb); DataRefImpl Ref = Sec->getRawDataRefImpl(); StringRef SectionName; Obj.getSectionName(Ref, SectionName); @@ -604,33 +730,21 @@ static char getSymbolNMTypeChar(const GlobalValue &GV) { } static char getSymbolNMTypeChar(IRObjectFile &Obj, basic_symbol_iterator I) { - const GlobalValue &GV = Obj.getSymbolGV(I->getRawDataRefImpl()); - return getSymbolNMTypeChar(GV); + const GlobalValue *GV = Obj.getSymbolGV(I->getRawDataRefImpl()); + if (!GV) + return 't'; + return getSymbolNMTypeChar(*GV); } -template -static bool isObject(ELFObjectFile &Obj, symbol_iterator I) { - typedef typename ELFObjectFile::Elf_Sym Elf_Sym; - - DataRefImpl Symb = I->getRawDataRefImpl(); - const Elf_Sym *ESym = Obj.getSymbol(Symb); - - return ESym->getType() == ELF::STT_OBJECT; -} +static bool isObject(SymbolicFile &Obj, basic_symbol_iterator I) { + auto *ELF = dyn_cast(&Obj); + if (!ELF) + return false; -static bool isObject(SymbolicFile *Obj, basic_symbol_iterator I) { - if (ELF32LEObjectFile *ELF = dyn_cast(Obj)) - return isObject(*ELF, I); - if (ELF64LEObjectFile *ELF = dyn_cast(Obj)) - return isObject(*ELF, I); - if (ELF32BEObjectFile *ELF = dyn_cast(Obj)) - return isObject(*ELF, I); - if (ELF64BEObjectFile *ELF = dyn_cast(Obj)) - return isObject(*ELF, I); - return false; + return elf_symbol_iterator(I)->getELFType() == ELF::STT_OBJECT; } -static char getNMTypeChar(SymbolicFile *Obj, basic_symbol_iterator I) { +static char getNMTypeChar(SymbolicFile &Obj, basic_symbol_iterator I) { uint32_t Symflags = I->getFlags(); if ((Symflags & object::SymbolRef::SF_Weak) && !isa(Obj)) { char Ret = isObject(Obj, I) ? 'v' : 'w'; @@ -648,20 +762,14 @@ static char getNMTypeChar(SymbolicFile *Obj, basic_symbol_iterator I) { char Ret = '?'; if (Symflags & object::SymbolRef::SF_Absolute) Ret = 'a'; - else if (IRObjectFile *IR = dyn_cast(Obj)) + else if (IRObjectFile *IR = dyn_cast(&Obj)) Ret = getSymbolNMTypeChar(*IR, I); - else if (COFFObjectFile *COFF = dyn_cast(Obj)) + else if (COFFObjectFile *COFF = dyn_cast(&Obj)) Ret = getSymbolNMTypeChar(*COFF, I); - else if (MachOObjectFile *MachO = dyn_cast(Obj)) + else if (MachOObjectFile *MachO = dyn_cast(&Obj)) Ret = getSymbolNMTypeChar(*MachO, I); - else if (ELF32LEObjectFile *ELF = dyn_cast(Obj)) - Ret = getSymbolNMTypeChar(*ELF, I); - else if (ELF64LEObjectFile *ELF = dyn_cast(Obj)) - Ret = getSymbolNMTypeChar(*ELF, I); - else if (ELF32BEObjectFile *ELF = dyn_cast(Obj)) - Ret = getSymbolNMTypeChar(*ELF, I); else - Ret = getSymbolNMTypeChar(*cast(Obj), I); + Ret = getSymbolNMTypeChar(cast(Obj), I); if (Symflags & object::SymbolRef::SF_Global) Ret = toupper(Ret); @@ -669,48 +777,108 @@ static char getNMTypeChar(SymbolicFile *Obj, basic_symbol_iterator I) { return Ret; } -static void dumpSymbolNamesFromObject(SymbolicFile *Obj, bool printName) { - basic_symbol_iterator IBegin = Obj->symbol_begin(); - basic_symbol_iterator IEnd = Obj->symbol_end(); +// getNsectForSegSect() is used to implement the Mach-O "-s segname sectname" +// option to dump only those symbols from that section in a Mach-O file. +// It is called once for each Mach-O file from dumpSymbolNamesFromObject() +// to get the section number for that named section from the command line +// arguments. It returns the section number for that section in the Mach-O +// file or zero it is not present. +static unsigned getNsectForSegSect(MachOObjectFile *Obj) { + unsigned Nsect = 1; + for (section_iterator I = Obj->section_begin(), E = Obj->section_end(); + I != E; ++I) { + DataRefImpl Ref = I->getRawDataRefImpl(); + StringRef SectionName; + Obj->getSectionName(Ref, SectionName); + StringRef SegmentName = Obj->getSectionFinalSegmentName(Ref); + if (SegmentName == SegSect[0] && SectionName == SegSect[1]) + return Nsect; + Nsect++; + } + return 0; +} + +// getNsectInMachO() is used to implement the Mach-O "-s segname sectname" +// option to dump only those symbols from that section in a Mach-O file. +// It is called once for each symbol in a Mach-O file from +// dumpSymbolNamesFromObject() and returns the section number for that symbol +// if it is in a section, else it returns 0. +static unsigned getNsectInMachO(MachOObjectFile &Obj, BasicSymbolRef Sym) { + DataRefImpl Symb = Sym.getRawDataRefImpl(); + if (Obj.is64Bit()) { + MachO::nlist_64 STE = Obj.getSymbol64TableEntry(Symb); + if ((STE.n_type & MachO::N_TYPE) == MachO::N_SECT) + return STE.n_sect; + return 0; + } + MachO::nlist STE = Obj.getSymbolTableEntry(Symb); + if ((STE.n_type & MachO::N_TYPE) == MachO::N_SECT) + return STE.n_sect; + return 0; +} + +static void dumpSymbolNamesFromObject(SymbolicFile &Obj, bool printName, + std::string ArchiveName = std::string(), + std::string ArchitectureName = + std::string()) { + auto Symbols = Obj.symbols(); if (DynamicSyms) { - if (!Obj->isELF()) { - error("File format has no dynamic symbol table", Obj->getFileName()); + const auto *E = dyn_cast(&Obj); + if (!E) { + error("File format has no dynamic symbol table", Obj.getFileName()); return; } - std::pair IDyn = - getELFDynamicSymbolIterators(Obj); - IBegin = IDyn.first; - IEnd = IDyn.second; + auto DynSymbols = E->getDynamicSymbolIterators(); + Symbols = + make_range(DynSymbols.begin(), DynSymbols.end()); } std::string NameBuffer; raw_string_ostream OS(NameBuffer); - for (basic_symbol_iterator I = IBegin; I != IEnd; ++I) { - uint32_t SymFlags = I->getFlags(); + // If a "-s segname sectname" option was specified and this is a Mach-O + // file get the section number for that section in this object file. + unsigned int Nsect = 0; + MachOObjectFile *MachO = dyn_cast(&Obj); + if (SegSect.size() != 0 && MachO) { + Nsect = getNsectForSegSect(MachO); + // If this section is not in the object file no symbols are printed. + if (Nsect == 0) + return; + } + for (BasicSymbolRef Sym : Symbols) { + uint32_t SymFlags = Sym.getFlags(); if (!DebugSyms && (SymFlags & SymbolRef::SF_FormatSpecific)) continue; if (WithoutAliases) { - if (IRObjectFile *IR = dyn_cast(Obj)) { - const GlobalValue &GV = IR->getSymbolGV(I->getRawDataRefImpl()); - if(isa(GV)) + if (IRObjectFile *IR = dyn_cast(&Obj)) { + const GlobalValue *GV = IR->getSymbolGV(Sym.getRawDataRefImpl()); + if (GV && isa(GV)) continue; } } + // If a "-s segname sectname" option was specified and this is a Mach-O + // file and this section appears in this file, Nsect will be non-zero then + // see if this symbol is a symbol from that section and if not skip it. + if (Nsect && Nsect != getNsectInMachO(*MachO, Sym)) + continue; NMSymbol S; - S.Size = UnknownAddressOrSize; - S.Address = UnknownAddressOrSize; - if ((PrintSize || SizeSort) && isa(Obj)) { - symbol_iterator SymI = I; - if (error(SymI->getSize(S.Size))) - break; + S.Size = 0; + S.Address = 0; + if (PrintSize) { + if (isa(&Obj)) + S.Size = ELFSymbolRef(Sym).getSize(); } - if (PrintAddress && isa(Obj)) - if (error(symbol_iterator(I)->getAddress(S.Address))) + if (PrintAddress && isa(Obj)) { + SymbolRef SymRef(Sym); + ErrorOr AddressOrErr = SymRef.getAddress(); + if (error(AddressOrErr.getError())) break; - S.TypeChar = getNMTypeChar(Obj, I); - if (error(I->printName(OS))) + S.Address = *AddressOrErr; + } + S.TypeChar = getNMTypeChar(Obj, Sym); + if (error(Sym.printName(OS))) break; OS << '\0'; - S.Symb = I->getRawDataRefImpl(); + S.Sym = Sym; SymbolList.push_back(S); } @@ -721,8 +889,8 @@ static void dumpSymbolNamesFromObject(SymbolicFile *Obj, bool printName) { P += strlen(P) + 1; } - CurrentFilename = Obj->getFileName(); - sortAndPrintSymbolList(Obj, printName); + CurrentFilename = Obj.getFileName(); + sortAndPrintSymbolList(Obj, printName, ArchiveName, ArchitectureName); } // checkMachOAndArchFlags() checks to see if the SymbolicFile is a Mach-O file @@ -731,47 +899,44 @@ static void dumpSymbolNamesFromObject(SymbolicFile *Obj, bool printName) { // architectures was specificed. If not then an error is generated and this // routine returns false. Else it returns true. static bool checkMachOAndArchFlags(SymbolicFile *O, std::string &Filename) { - if (isa(O) && !ArchAll && ArchFlags.size() != 0) { - MachOObjectFile *MachO = dyn_cast(O); - bool ArchFound = false; - MachO::mach_header H; - MachO::mach_header_64 H_64; - Triple T; - if (MachO->is64Bit()) { - H_64 = MachO->MachOObjectFile::getHeader64(); - T = MachOObjectFile::getArch(H_64.cputype, H_64.cpusubtype); - } else { - H = MachO->MachOObjectFile::getHeader(); - T = MachOObjectFile::getArch(H.cputype, H.cpusubtype); - } - unsigned i; - for (i = 0; i < ArchFlags.size(); ++i){ - if (ArchFlags[i] == T.getArchName()) - ArchFound = true; - break; - } - if (!ArchFound) { - error(ArchFlags[i], - "file: " + Filename + " does not contain architecture"); - return false; - } + MachOObjectFile *MachO = dyn_cast(O); + + if (!MachO || ArchAll || ArchFlags.size() == 0) + return true; + + MachO::mach_header H; + MachO::mach_header_64 H_64; + Triple T; + if (MachO->is64Bit()) { + H_64 = MachO->MachOObjectFile::getHeader64(); + T = MachOObjectFile::getArch(H_64.cputype, H_64.cpusubtype); + } else { + H = MachO->MachOObjectFile::getHeader(); + T = MachOObjectFile::getArch(H.cputype, H.cpusubtype); + } + if (std::none_of( + ArchFlags.begin(), ArchFlags.end(), + [&](const std::string &Name) { return Name == T.getArchName(); })) { + error("No architecture specified", Filename); + return false; } return true; } static void dumpSymbolNamesFromFile(std::string &Filename) { - std::unique_ptr Buffer; - if (error(MemoryBuffer::getFileOrSTDIN(Filename, Buffer), Filename)) + ErrorOr> BufferOrErr = + MemoryBuffer::getFileOrSTDIN(Filename); + if (error(BufferOrErr.getError(), Filename)) return; LLVMContext &Context = getGlobalContext(); - ErrorOr BinaryOrErr = createBinary(Buffer, &Context); + ErrorOr> BinaryOrErr = createBinary( + BufferOrErr.get()->getMemBufferRef(), NoLLVMBitcode ? nullptr : &Context); if (error(BinaryOrErr.getError(), Filename)) return; - Buffer.release(); - std::unique_ptr Bin(BinaryOrErr.get()); + Binary &Bin = *BinaryOrErr.get(); - if (Archive *A = dyn_cast(Bin.get())) { + if (Archive *A = dyn_cast(&Bin)) { if (ArchiveMap) { Archive::symbol_iterator I = A->symbol_begin(); Archive::symbol_iterator E = A->symbol_end(); @@ -799,42 +964,52 @@ static void dumpSymbolNamesFromFile(std::string &Filename) { if (SymbolicFile *O = dyn_cast(&*ChildOrErr.get())) { if (!checkMachOAndArchFlags(O, Filename)) return; - outs() << "\n"; - if (isa(O)) { - outs() << Filename << "(" << O->getFileName() << ")"; - } else - outs() << O->getFileName(); - outs() << ":\n"; - dumpSymbolNamesFromObject(O, false); + if (!PrintFileName) { + outs() << "\n"; + if (isa(O)) { + outs() << Filename << "(" << O->getFileName() << ")"; + } else + outs() << O->getFileName(); + outs() << ":\n"; + } + dumpSymbolNamesFromObject(*O, false, Filename); } } return; } - if (MachOUniversalBinary *UB = dyn_cast(Bin.get())) { + if (MachOUniversalBinary *UB = dyn_cast(&Bin)) { // If we have a list of architecture flags specified dump only those. if (!ArchAll && ArchFlags.size() != 0) { // Look for a slice in the universal binary that matches each ArchFlag. bool ArchFound; - for (unsigned i = 0; i < ArchFlags.size(); ++i){ + for (unsigned i = 0; i < ArchFlags.size(); ++i) { ArchFound = false; for (MachOUniversalBinary::object_iterator I = UB->begin_objects(), E = UB->end_objects(); I != E; ++I) { - if (ArchFlags[i] == I->getArchTypeName()){ + if (ArchFlags[i] == I->getArchTypeName()) { ArchFound = true; ErrorOr> ObjOrErr = - I->getAsObjectFile(); - std::unique_ptr A; + I->getAsObjectFile(); + std::string ArchiveName; + std::string ArchitectureName; + ArchiveName.clear(); + ArchitectureName.clear(); if (ObjOrErr) { - std::unique_ptr Obj = std::move(ObjOrErr.get()); + ObjectFile &Obj = *ObjOrErr.get(); if (ArchFlags.size() > 1) { - outs() << "\n" << Obj->getFileName() - << " (for architecture " << I->getArchTypeName() << ")" - << ":\n"; + if (PrintFileName) + ArchitectureName = I->getArchTypeName(); + else + outs() << "\n" << Obj.getFileName() << " (for architecture " + << I->getArchTypeName() << ")" + << ":\n"; } - dumpSymbolNamesFromObject(Obj.get(), false); - } - else if (!I->getAsArchive(A)) { + dumpSymbolNamesFromObject(Obj, false, ArchiveName, + ArchitectureName); + } else if (ErrorOr> AOrErr = + I->getAsArchive()) { + std::unique_ptr &A = *AOrErr; for (Archive::child_iterator AI = A->child_begin(), AE = A->child_end(); AI != AE; ++AI) { @@ -842,16 +1017,23 @@ static void dumpSymbolNamesFromFile(std::string &Filename) { AI->getAsBinary(&Context); if (ChildOrErr.getError()) continue; - if (SymbolicFile *O = dyn_cast - (&*ChildOrErr.get())) { - outs() << "\n" << A->getFileName(); - outs() << "(" << O->getFileName() << ")"; - if (ArchFlags.size() > 1) { - outs() << " (for architecture " << I->getArchTypeName() - << ")"; + if (SymbolicFile *O = + dyn_cast(&*ChildOrErr.get())) { + if (PrintFileName) { + ArchiveName = A->getFileName(); + if (ArchFlags.size() > 1) + ArchitectureName = I->getArchTypeName(); + } else { + outs() << "\n" << A->getFileName(); + outs() << "(" << O->getFileName() << ")"; + if (ArchFlags.size() > 1) { + outs() << " (for architecture " << I->getArchTypeName() + << ")"; + } + outs() << ":\n"; } - outs() << ":\n"; - dumpSymbolNamesFromObject(O, false); + dumpSymbolNamesFromObject(*O, false, ArchiveName, + ArchitectureName); } } } @@ -868,20 +1050,20 @@ static void dumpSymbolNamesFromFile(std::string &Filename) { // No architecture flags were specified so if this contains a slice that // matches the host architecture dump only that. if (!ArchAll) { - StringRef HostArchName = - MachOObjectFile::getHostArch().getArchName(); + StringRef HostArchName = MachOObjectFile::getHostArch().getArchName(); for (MachOUniversalBinary::object_iterator I = UB->begin_objects(), E = UB->end_objects(); I != E; ++I) { - if (HostArchName == I->getArchTypeName()){ - ErrorOr> ObjOrErr = - I->getAsObjectFile(); - std::unique_ptr A; + if (HostArchName == I->getArchTypeName()) { + ErrorOr> ObjOrErr = I->getAsObjectFile(); + std::string ArchiveName; + ArchiveName.clear(); if (ObjOrErr) { - std::unique_ptr Obj = std::move(ObjOrErr.get()); - dumpSymbolNamesFromObject(Obj.get(), false); - } - else if (!I->getAsArchive(A)) { + ObjectFile &Obj = *ObjOrErr.get(); + dumpSymbolNamesFromObject(Obj, false); + } else if (ErrorOr> AOrErr = + I->getAsArchive()) { + std::unique_ptr &A = *AOrErr; for (Archive::child_iterator AI = A->child_begin(), AE = A->child_end(); AI != AE; ++AI) { @@ -889,11 +1071,15 @@ static void dumpSymbolNamesFromFile(std::string &Filename) { AI->getAsBinary(&Context); if (ChildOrErr.getError()) continue; - if (SymbolicFile *O = dyn_cast - (&*ChildOrErr.get())) { - outs() << "\n" << A->getFileName() - << "(" << O->getFileName() << ")" << ":\n"; - dumpSymbolNamesFromObject(O, false); + if (SymbolicFile *O = + dyn_cast(&*ChildOrErr.get())) { + if (PrintFileName) + ArchiveName = A->getFileName(); + else + outs() << "\n" << A->getFileName() << "(" << O->getFileName() + << ")" + << ":\n"; + dumpSymbolNamesFromObject(*O, false, ArchiveName); } } } @@ -908,18 +1094,26 @@ static void dumpSymbolNamesFromFile(std::string &Filename) { E = UB->end_objects(); I != E; ++I) { ErrorOr> ObjOrErr = I->getAsObjectFile(); - std::unique_ptr A; + std::string ArchiveName; + std::string ArchitectureName; + ArchiveName.clear(); + ArchitectureName.clear(); if (ObjOrErr) { - std::unique_ptr Obj = std::move(ObjOrErr.get()); - if (moreThanOneArch) - outs() << "\n"; - outs() << Obj->getFileName(); - if (isa(Obj.get()) && moreThanOneArch) - outs() << " (for architecture " << I->getArchTypeName() << ")"; - outs() << ":\n"; - dumpSymbolNamesFromObject(Obj.get(), false); - } - else if (!I->getAsArchive(A)) { + ObjectFile &Obj = *ObjOrErr.get(); + if (PrintFileName) { + if (isa(Obj) && moreThanOneArch) + ArchitectureName = I->getArchTypeName(); + } else { + if (moreThanOneArch) + outs() << "\n"; + outs() << Obj.getFileName(); + if (isa(Obj) && moreThanOneArch) + outs() << " (for architecture " << I->getArchTypeName() << ")"; + outs() << ":\n"; + } + dumpSymbolNamesFromObject(Obj, false, ArchiveName, ArchitectureName); + } else if (ErrorOr> AOrErr = I->getAsArchive()) { + std::unique_ptr &A = *AOrErr; for (Archive::child_iterator AI = A->child_begin(), AE = A->child_end(); AI != AE; ++AI) { ErrorOr> ChildOrErr = @@ -927,25 +1121,32 @@ static void dumpSymbolNamesFromFile(std::string &Filename) { if (ChildOrErr.getError()) continue; if (SymbolicFile *O = dyn_cast(&*ChildOrErr.get())) { - outs() << "\n" << A->getFileName(); - if (isa(O)) { - outs() << "(" << O->getFileName() << ")"; - if (moreThanOneArch) - outs() << " (for architecture " << I->getArchTypeName() << ")"; - } else - outs() << ":" << O->getFileName(); - outs() << ":\n"; - dumpSymbolNamesFromObject(O, false); + if (PrintFileName) { + ArchiveName = A->getFileName(); + if (isa(O) && moreThanOneArch) + ArchitectureName = I->getArchTypeName(); + } else { + outs() << "\n" << A->getFileName(); + if (isa(O)) { + outs() << "(" << O->getFileName() << ")"; + if (moreThanOneArch) + outs() << " (for architecture " << I->getArchTypeName() + << ")"; + } else + outs() << ":" << O->getFileName(); + outs() << ":\n"; + } + dumpSymbolNamesFromObject(*O, false, ArchiveName, ArchitectureName); } } } } return; } - if (SymbolicFile *O = dyn_cast(Bin.get())) { + if (SymbolicFile *O = dyn_cast(&Bin)) { if (!checkMachOAndArchFlags(O, Filename)) return; - dumpSymbolNamesFromObject(O, true); + dumpSymbolNamesFromObject(*O, true); return; } error("unrecognizable file type", Filename); @@ -964,6 +1165,10 @@ int main(int argc, char **argv) { if (error(sys::ChangeStdinToBinary())) return 1; + llvm::InitializeAllTargetInfos(); + llvm::InitializeAllTargetMCs(); + llvm::InitializeAllAsmParsers(); + ToolName = argv[0]; if (BSDFormat) OutputFormat = bsd; @@ -989,18 +1194,20 @@ int main(int argc, char **argv) { MultipleFiles = true; } - for (unsigned i = 0; i < ArchFlags.size(); ++i){ + for (unsigned i = 0; i < ArchFlags.size(); ++i) { if (ArchFlags[i] == "all") { ArchAll = true; - } - else { - Triple T = MachOObjectFile::getArch(ArchFlags[i]); - if (T.getArch() == Triple::UnknownArch) + } else { + if (!MachOObjectFile::isValidArch(ArchFlags[i])) error("Unknown architecture named '" + ArchFlags[i] + "'", "for the -arch option"); } } + if (SegSect.size() != 0 && SegSect.size() != 2) + error("bad number of arguments (must be two arguments)", + "for the -s option"); + std::for_each(InputFilenames.begin(), InputFilenames.end(), dumpSymbolNamesFromFile);