]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - opencl/llvm.git/blobdiff - tools/llvm-objdump/llvm-objdump.cpp
For llvm-objdump, hook up existing options to work when using -macho (the Mach-O...
[opencl/llvm.git] / tools / llvm-objdump / llvm-objdump.cpp
index 0074271ba7e2aa58fdd2b0ac23a10606b0716bc8..76c8af420568a976d940fd14291365766a1d4324 100644 (file)
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/ADT/Triple.h"
-#include "llvm/MC/MCAnalysis/MCAtom.h"
-#include "llvm/MC/MCAnalysis/MCFunction.h"
-#include "llvm/MC/MCAnalysis/MCModule.h"
-#include "llvm/MC/MCAnalysis/MCModuleYAML.h"
-#include "llvm/MC/MCAnalysis/MCObjectSymbolizer.h"
 #include "llvm/MC/MCAsmInfo.h"
 #include "llvm/MC/MCContext.h"
 #include "llvm/MC/MCDisassembler.h"
@@ -32,7 +27,6 @@
 #include "llvm/MC/MCInstPrinter.h"
 #include "llvm/MC/MCInstrAnalysis.h"
 #include "llvm/MC/MCInstrInfo.h"
-#include "llvm/MC/MCObjectDisassembler.h"
 #include "llvm/MC/MCObjectFileInfo.h"
 #include "llvm/MC/MCRegisterInfo.h"
 #include "llvm/MC/MCRelocationInfo.h"
@@ -50,7 +44,6 @@
 #include "llvm/Support/Host.h"
 #include "llvm/Support/ManagedStatic.h"
 #include "llvm/Support/MemoryBuffer.h"
-#include "llvm/Support/MemoryObject.h"
 #include "llvm/Support/PrettyStackTrace.h"
 #include "llvm/Support/Signals.h"
 #include "llvm/Support/SourceMgr.h"
@@ -68,21 +61,36 @@ using namespace object;
 static cl::list<std::string>
 InputFilenames(cl::Positional, cl::desc("<input object files>"),cl::ZeroOrMore);
 
-static cl::opt<bool>
-Disassemble("disassemble",
+cl::opt<bool>
+llvm::Disassemble("disassemble",
   cl::desc("Display assembler mnemonics for the machine instructions"));
 static cl::alias
 Disassembled("d", cl::desc("Alias for --disassemble"),
              cl::aliasopt(Disassemble));
 
-static cl::opt<bool>
-Relocations("r", cl::desc("Display the relocation entries in the file"));
+cl::opt<bool>
+llvm::Relocations("r", cl::desc("Display the relocation entries in the file"));
 
-static cl::opt<bool>
-SectionContents("s", cl::desc("Display the content of each section"));
+cl::opt<bool>
+llvm::SectionContents("s", cl::desc("Display the content of each section"));
 
-static cl::opt<bool>
-SymbolTable("t", cl::desc("Display the symbol table"));
+cl::opt<bool>
+llvm::SymbolTable("t", cl::desc("Display the symbol table"));
+
+cl::opt<bool>
+llvm::ExportsTrie("exports-trie", cl::desc("Display mach-o exported symbols"));
+
+cl::opt<bool>
+llvm::Rebase("rebase", cl::desc("Display mach-o rebasing info"));
+
+cl::opt<bool>
+llvm::Bind("bind", cl::desc("Display mach-o binding info"));
+
+cl::opt<bool>
+llvm::LazyBind("lazy-bind", cl::desc("Display mach-o lazy binding info"));
+
+cl::opt<bool>
+llvm::WeakBind("weak-bind", cl::desc("Display mach-o weak binding info"));
 
 static cl::opt<bool>
 MachOOpt("macho", cl::desc("Use MachO specific object file parser"));
@@ -100,12 +108,12 @@ llvm::MCPU("mcpu",
      cl::init(""));
 
 cl::opt<std::string>
-llvm::ArchName("arch", cl::desc("Target arch to disassemble for, "
+llvm::ArchName("arch-name", cl::desc("Target arch to disassemble for, "
                                 "see -version for available targets"));
 
-static cl::opt<bool>
-SectionHeaders("section-headers", cl::desc("Display summaries of the headers "
-                                           "for each section."));
+cl::opt<bool>
+llvm::SectionHeaders("section-headers", cl::desc("Display summaries of the "
+                                                 "headers for each section."));
 static cl::alias
 SectionHeadersShort("headers", cl::desc("Alias for --section-headers"),
                     cl::aliasopt(SectionHeaders));
@@ -119,40 +127,28 @@ llvm::MAttrs("mattr",
   cl::desc("Target specific attributes"),
   cl::value_desc("a1,+a2,-a3,..."));
 
-static cl::opt<bool>
-NoShowRawInsn("no-show-raw-insn", cl::desc("When disassembling instructions, "
-                                           "do not print the instruction bytes."));
+cl::opt<bool>
+llvm::NoShowRawInsn("no-show-raw-insn", cl::desc("When disassembling "
+                                                 "instructions, do not print "
+                                                 "the instruction bytes."));
 
-static cl::opt<bool>
-UnwindInfo("unwind-info", cl::desc("Display unwind information"));
+cl::opt<bool>
+llvm::UnwindInfo("unwind-info", cl::desc("Display unwind information"));
 
 static cl::alias
 UnwindInfoShort("u", cl::desc("Alias for --unwind-info"),
                 cl::aliasopt(UnwindInfo));
 
-static cl::opt<bool>
-PrivateHeaders("private-headers",
-               cl::desc("Display format specific file headers"));
+cl::opt<bool>
+llvm::PrivateHeaders("private-headers",
+                     cl::desc("Display format specific file headers"));
 
 static cl::alias
 PrivateHeadersShort("p", cl::desc("Alias for --private-headers"),
                     cl::aliasopt(PrivateHeaders));
 
-static cl::opt<bool>
-Symbolize("symbolize", cl::desc("When disassembling instructions, "
-                                "try to symbolize operands."));
-
-static cl::opt<bool>
-CFG("cfg", cl::desc("Create a CFG for every function found in the object"
-                      " and write it to a graphviz file"));
-
-// FIXME: Does it make sense to have a dedicated tool for yaml cfg output?
-static cl::opt<std::string>
-YAMLCFG("yaml-cfg",
-        cl::desc("Create a CFG and write it as a YAML MCModule."),
-        cl::value_desc("yaml output file"));
-
 static StringRef ToolName;
+static int ReturnValue = EXIT_SUCCESS;
 
 bool llvm::error(std::error_code EC) {
   if (!EC)
@@ -160,6 +156,7 @@ bool llvm::error(std::error_code EC) {
 
   outs() << ToolName << ": error reading file: " << EC.message() << ".\n";
   outs().flush();
+  ReturnValue = EXIT_FAILURE;
   return true;
 }
 
@@ -197,53 +194,6 @@ static const Target *getTarget(const ObjectFile *Obj = nullptr) {
   return TheTarget;
 }
 
-// Write a graphviz file for the CFG inside an MCFunction.
-// FIXME: Use GraphWriter
-static void emitDOTFile(const char *FileName, const MCFunction &f,
-                        MCInstPrinter *IP) {
-  // Start a new dot file.
-  std::string Error;
-  raw_fd_ostream Out(FileName, Error, sys::fs::F_Text);
-  if (!Error.empty()) {
-    errs() << "llvm-objdump: warning: " << Error << '\n';
-    return;
-  }
-
-  Out << "digraph \"" << f.getName() << "\" {\n";
-  Out << "graph [ rankdir = \"LR\" ];\n";
-  for (MCFunction::const_iterator i = f.begin(), e = f.end(); i != e; ++i) {
-    // Only print blocks that have predecessors.
-    bool hasPreds = (*i)->pred_begin() != (*i)->pred_end();
-
-    if (!hasPreds && i != f.begin())
-      continue;
-
-    Out << '"' << (*i)->getInsts()->getBeginAddr() << "\" [ label=\"<a>";
-    // Print instructions.
-    for (unsigned ii = 0, ie = (*i)->getInsts()->size(); ii != ie;
-        ++ii) {
-      if (ii != 0) // Not the first line, start a new row.
-        Out << '|';
-      if (ii + 1 == ie) // Last line, add an end id.
-        Out << "<o>";
-
-      // Escape special chars and print the instruction in mnemonic form.
-      std::string Str;
-      raw_string_ostream OS(Str);
-      IP->printInst(&(*i)->getInsts()->at(ii).Inst, OS, "");
-      Out << DOT::EscapeString(OS.str());
-    }
-    Out << "\" shape=\"record\" ];\n";
-
-    // Add edges.
-    for (MCBasicBlock::succ_const_iterator si = (*i)->succ_begin(),
-        se = (*i)->succ_end(); si != se; ++si)
-      Out << (*i)->getInsts()->getBeginAddr() << ":o -> "
-          << (*si)->getInsts()->getBeginAddr() << ":a\n";
-  }
-  Out << "}\n";
-}
-
 void llvm::DumpBytes(StringRef bytes) {
   static const char hex_rep[] = "0123456789abcdef";
   // FIXME: The real way to do this is to figure out the longest instruction
@@ -332,19 +282,6 @@ static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) {
     return;
   }
 
-
-  if (Symbolize) {
-    std::unique_ptr<MCRelocationInfo> RelInfo(
-        TheTarget->createMCRelocationInfo(TripleName, Ctx));
-    if (RelInfo) {
-      std::unique_ptr<MCSymbolizer> Symzer(
-        MCObjectSymbolizer::createObjectSymbolizer(Ctx, std::move(RelInfo),
-                                                   Obj));
-      if (Symzer)
-        DisAsm->setSymbolizer(std::move(Symzer));
-    }
-  }
-
   std::unique_ptr<const MCInstrAnalysis> MIA(
       TheTarget->createMCInstrAnalysis(MII.get()));
 
@@ -357,45 +294,6 @@ static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) {
     return;
   }
 
-  if (CFG || !YAMLCFG.empty()) {
-    std::unique_ptr<MCObjectDisassembler> OD(
-        new MCObjectDisassembler(*Obj, *DisAsm, *MIA));
-    std::unique_ptr<MCModule> Mod(OD->buildModule(/* withCFG */ true));
-    for (MCModule::const_atom_iterator AI = Mod->atom_begin(),
-                                       AE = Mod->atom_end();
-                                       AI != AE; ++AI) {
-      outs() << "Atom " << (*AI)->getName() << ": \n";
-      if (const MCTextAtom *TA = dyn_cast<MCTextAtom>(*AI)) {
-        for (MCTextAtom::const_iterator II = TA->begin(), IE = TA->end();
-             II != IE;
-             ++II) {
-          IP->printInst(&II->Inst, outs(), "");
-          outs() << "\n";
-        }
-      }
-    }
-    if (CFG) {
-      for (MCModule::const_func_iterator FI = Mod->func_begin(),
-                                         FE = Mod->func_end();
-                                         FI != FE; ++FI) {
-        static int filenum = 0;
-        emitDOTFile((Twine((*FI)->getName()) + "_" +
-                     utostr(filenum) + ".dot").str().c_str(),
-                      **FI, IP.get());
-        ++filenum;
-      }
-    }
-    if (!YAMLCFG.empty()) {
-      std::string Error;
-      raw_fd_ostream YAMLOut(YAMLCFG.c_str(), Error, sys::fs::F_Text);
-      if (!Error.empty()) {
-        errs() << ToolName << ": warning: " << Error << '\n';
-        return;
-      }
-      mcmodule2yaml(YAMLOut, *Mod, *MII, *MRI);
-    }
-  }
-
   StringRef Fmt = Obj->getBytesInAddress() > 4 ? "\t\t%016" PRIx64 ":  " :
                                                  "\t\t\t%08" PRIx64 ":  ";
 
@@ -410,25 +308,18 @@ static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) {
   }
 
   for (const SectionRef &Section : Obj->sections()) {
-    bool Text;
-    if (error(Section.isText(Text)))
-      break;
-    if (!Text)
+    if (!Section.isText() || Section.isVirtual())
       continue;
 
-    uint64_t SectionAddr;
-    if (error(Section.getAddress(SectionAddr)))
-      break;
-
-    uint64_t SectSize;
-    if (error(Section.getSize(SectSize)))
-      break;
+    uint64_t SectionAddr = Section.getAddress();
+    uint64_t SectSize = Section.getSize();
+    if (!SectSize)
+      continue;
 
     // Make a list of all the symbols in this section.
     std::vector<std::pair<uint64_t, StringRef>> Symbols;
     for (const SymbolRef &Symbol : Obj->symbols()) {
-      bool contains;
-      if (!error(Section.containsSymbol(Symbol, contains)) && contains) {
+      if (Section.containsSymbol(Symbol)) {
         uint64_t Address;
         if (error(Symbol.getAddress(Address)))
           break;
@@ -483,10 +374,12 @@ static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) {
     SmallString<40> Comments;
     raw_svector_ostream CommentStream(Comments);
 
-    StringRef Bytes;
-    if (error(Section.getContents(Bytes)))
+    StringRef BytesStr;
+    if (error(Section.getContents(BytesStr)))
       break;
-    StringRefMemoryObject memoryObject(Bytes, SectionAddr);
+    ArrayRef<uint8_t> Bytes(reinterpret_cast<const uint8_t *>(BytesStr.data()),
+                            BytesStr.size());
+
     uint64_t Size;
     uint64_t Index;
 
@@ -513,13 +406,14 @@ static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) {
       for (Index = Start; Index < End; Index += Size) {
         MCInst Inst;
 
-        if (DisAsm->getInstruction(Inst, Size, memoryObject,
-                                   SectionAddr + Index,
-                                   DebugOut, CommentStream)) {
+        if (DisAsm->getInstruction(Inst, Size, Bytes.slice(Index),
+                                   SectionAddr + Index, DebugOut,
+                                   CommentStream)) {
           outs() << format("%8" PRIx64 ":", SectionAddr + Index);
           if (!NoShowRawInsn) {
             outs() << "\t";
-            DumpBytes(StringRef(Bytes.data() + Index, Size));
+            DumpBytes(StringRef(
+                reinterpret_cast<const char *>(Bytes.data()) + Index, Size));
           }
           IP->printInst(&Inst, outs(), "");
           outs() << CommentStream.str();
@@ -559,7 +453,7 @@ static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) {
   }
 }
 
-static void PrintRelocations(const ObjectFile *Obj) {
+void llvm::PrintRelocations(const ObjectFile *Obj) {
   StringRef Fmt = Obj->getBytesInAddress() > 4 ? "%016" PRIx64 :
                                                  "%08" PRIx64;
   // Regular objdump doesn't print relocations in non-relocatable object
@@ -596,7 +490,7 @@ static void PrintRelocations(const ObjectFile *Obj) {
   }
 }
 
-static void PrintSectionHeaders(const ObjectFile *Obj) {
+void llvm::PrintSectionHeaders(const ObjectFile *Obj) {
   outs() << "Sections:\n"
             "Idx Name          Size      Address          Type\n";
   unsigned i = 0;
@@ -604,19 +498,11 @@ static void PrintSectionHeaders(const ObjectFile *Obj) {
     StringRef Name;
     if (error(Section.getName(Name)))
       return;
-    uint64_t Address;
-    if (error(Section.getAddress(Address)))
-      return;
-    uint64_t Size;
-    if (error(Section.getSize(Size)))
-      return;
-    bool Text, Data, BSS;
-    if (error(Section.isText(Text)))
-      return;
-    if (error(Section.isData(Data)))
-      return;
-    if (error(Section.isBSS(BSS)))
-      return;
+    uint64_t Address = Section.getAddress();
+    uint64_t Size = Section.getSize();
+    bool Text = Section.isText();
+    bool Data = Section.isData();
+    bool BSS = Section.isBSS();
     std::string Type = (std::string(Text ? "TEXT " : "") +
                         (Data ? "DATA " : "") + (BSS ? "BSS" : ""));
     outs() << format("%3d %-13s %08" PRIx64 " %016" PRIx64 " %s\n", i,
@@ -625,25 +511,20 @@ static void PrintSectionHeaders(const ObjectFile *Obj) {
   }
 }
 
-static void PrintSectionContents(const ObjectFile *Obj) {
+void llvm::PrintSectionContents(const ObjectFile *Obj) {
   std::error_code EC;
   for (const SectionRef &Section : Obj->sections()) {
     StringRef Name;
     StringRef Contents;
-    uint64_t BaseAddr;
-    bool BSS;
     if (error(Section.getName(Name)))
       continue;
-    if (error(Section.getAddress(BaseAddr)))
-      continue;
-    if (error(Section.isBSS(BSS)))
+    uint64_t BaseAddr = Section.getAddress();
+    uint64_t Size = Section.getSize();
+    if (!Size)
       continue;
 
     outs() << "Contents of section " << Name << ":\n";
-    if (BSS) {
-      uint64_t Size;
-      if (error(Section.getSize(Size)))
-        continue;
+    if (Section.isBSS()) {
       outs() << format("<skipping contents of bss section at [%04" PRIx64
                        ", %04" PRIx64 ")>\n",
                        BaseAddr, BaseAddr + Size);
@@ -680,34 +561,32 @@ static void PrintSectionContents(const ObjectFile *Obj) {
 }
 
 static void PrintCOFFSymbolTable(const COFFObjectFile *coff) {
-  const coff_file_header *header;
-  if (error(coff->getHeader(header)))
-    return;
-
-  for (unsigned SI = 0, SE = header->NumberOfSymbols; SI != SE; ++SI) {
-    const coff_symbol *Symbol;
+  for (unsigned SI = 0, SE = coff->getNumberOfSymbols(); SI != SE; ++SI) {
+    ErrorOr<COFFSymbolRef> Symbol = coff->getSymbol(SI);
     StringRef Name;
-    if (error(coff->getSymbol(SI, Symbol)))
+    if (error(Symbol.getError()))
       return;
 
-    if (error(coff->getSymbolName(Symbol, Name)))
+    if (error(coff->getSymbolName(*Symbol, Name)))
       return;
 
     outs() << "[" << format("%2d", SI) << "]"
-           << "(sec " << format("%2d", int(Symbol->SectionNumber)) << ")"
+           << "(sec " << format("%2d", int(Symbol->getSectionNumber())) << ")"
            << "(fl 0x00)" // Flag bits, which COFF doesn't have.
-           << "(ty " << format("%3x", unsigned(Symbol->Type)) << ")"
-           << "(scl " << format("%3x", unsigned(Symbol->StorageClass)) << ") "
-           << "(nx " << unsigned(Symbol->NumberOfAuxSymbols) << ") "
-           << "0x" << format("%08x", unsigned(Symbol->Value)) << " "
+           << "(ty " << format("%3x", unsigned(Symbol->getType())) << ")"
+           << "(scl " << format("%3x", unsigned(Symbol->getStorageClass())) << ") "
+           << "(nx " << unsigned(Symbol->getNumberOfAuxSymbols()) << ") "
+           << "0x" << format("%08x", unsigned(Symbol->getValue())) << " "
            << Name << "\n";
 
-    for (unsigned AI = 0, AE = Symbol->NumberOfAuxSymbols; AI < AE; ++AI, ++SI) {
+    for (unsigned AI = 0, AE = Symbol->getNumberOfAuxSymbols(); AI < AE; ++AI, ++SI) {
       if (Symbol->isSectionDefinition()) {
         const coff_aux_section_definition *asd;
         if (error(coff->getAuxSymbol<coff_aux_section_definition>(SI + 1, asd)))
           return;
 
+        int32_t AuxNumber = asd->getNumber(Symbol->isBigObj());
+
         outs() << "AUX "
                << format("scnlen 0x%x nreloc %d nlnno %d checksum 0x%x "
                          , unsigned(asd->Length)
@@ -715,18 +594,18 @@ static void PrintCOFFSymbolTable(const COFFObjectFile *coff) {
                          , unsigned(asd->NumberOfLinenumbers)
                          , unsigned(asd->CheckSum))
                << format("assoc %d comdat %d\n"
-                         , unsigned(asd->Number)
+                         , unsigned(AuxNumber)
                          , unsigned(asd->Selection));
       } else if (Symbol->isFileRecord()) {
-        const coff_aux_file *AF;
-        if (error(coff->getAuxSymbol<coff_aux_file>(SI + 1, AF)))
+        const char *FileName;
+        if (error(coff->getAuxSymbol<char>(SI + 1, FileName)))
           return;
 
-        StringRef Name(AF->FileName,
-                       Symbol->NumberOfAuxSymbols * COFF::SymbolSize);
+        StringRef Name(FileName, Symbol->getNumberOfAuxSymbols() *
+                                     coff->getSymbolTableEntrySize());
         outs() << "AUX " << Name.rtrim(StringRef("\0", 1))  << '\n';
 
-        SI = SI + Symbol->NumberOfAuxSymbols;
+        SI = SI + Symbol->getNumberOfAuxSymbols();
         break;
       } else {
         outs() << "AUX Unknown\n";
@@ -735,7 +614,7 @@ static void PrintCOFFSymbolTable(const COFFObjectFile *coff) {
   }
 }
 
-static void PrintSymbolTable(const ObjectFile *o) {
+void llvm::PrintSymbolTable(const ObjectFile *o) {
   outs() << "SYMBOL TABLE:\n";
 
   if (const COFFObjectFile *coff = dyn_cast<const COFFObjectFile>(o)) {
@@ -829,11 +708,68 @@ static void PrintUnwindInfo(const ObjectFile *o) {
   }
 }
 
+void llvm::printExportsTrie(const ObjectFile *o) {
+  outs() << "Exports trie:\n";
+  if (const MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(o))
+    printMachOExportsTrie(MachO);
+  else {
+    errs() << "This operation is only currently supported "
+              "for Mach-O executable files.\n";
+    return;
+  }
+}
+
+void llvm::printRebaseTable(const ObjectFile *o) {
+  outs() << "Rebase table:\n";
+  if (const MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(o))
+    printMachORebaseTable(MachO);
+  else {
+    errs() << "This operation is only currently supported "
+              "for Mach-O executable files.\n";
+    return;
+  }
+}
+
+void llvm::printBindTable(const ObjectFile *o) {
+  outs() << "Bind table:\n";
+  if (const MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(o))
+    printMachOBindTable(MachO);
+  else {
+    errs() << "This operation is only currently supported "
+              "for Mach-O executable files.\n";
+    return;
+  }
+}
+
+void llvm::printLazyBindTable(const ObjectFile *o) {
+  outs() << "Lazy bind table:\n";
+  if (const MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(o))
+    printMachOLazyBindTable(MachO);
+  else {
+    errs() << "This operation is only currently supported "
+              "for Mach-O executable files.\n";
+    return;
+  }
+}
+
+void llvm::printWeakBindTable(const ObjectFile *o) {
+  outs() << "Weak bind table:\n";
+  if (const MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(o))
+    printMachOWeakBindTable(MachO);
+  else {
+    errs() << "This operation is only currently supported "
+              "for Mach-O executable files.\n";
+    return;
+  }
+}
+
 static void printPrivateFileHeader(const ObjectFile *o) {
   if (o->isELF()) {
     printELFFileHeader(o);
   } else if (o->isCOFF()) {
     printCOFFFileHeader(o);
+  } else if (o->isMachO()) {
+    printMachOFileHeader(o);
   }
 }
 
@@ -856,6 +792,16 @@ static void DumpObject(const ObjectFile *o) {
     PrintUnwindInfo(o);
   if (PrivateHeaders)
     printPrivateFileHeader(o);
+  if (ExportsTrie)
+    printExportsTrie(o);
+  if (Rebase)
+    printRebaseTable(o);
+  if (Bind)
+    printBindTable(o);
+  if (LazyBind)
+    printLazyBindTable(o);
+  if (WeakBind)
+    printWeakBindTable(o);
 }
 
 /// @brief Dump each object file in \a a;
@@ -886,8 +832,11 @@ static void DumpInput(StringRef file) {
     return;
   }
 
-  if (MachOOpt && Disassemble) {
-    DisassembleInputMachO(file);
+  // If we are using the Mach-O specific object file parser, then let it parse
+  // the file and process the command line options.  So the -arch flags can
+  // be used to select specific slices, etc.
+  if (MachOOpt) {
+    ParseInputMachO(file);
     return;
   }
 
@@ -937,7 +886,14 @@ int main(int argc, char **argv) {
       && !SectionContents
       && !SymbolTable
       && !UnwindInfo
-      && !PrivateHeaders) {
+      && !PrivateHeaders
+      && !ExportsTrie
+      && !Rebase
+      && !Bind
+      && !LazyBind
+      && !WeakBind
+      && !(UniversalHeaders && MachOOpt)
+      && !(ArchiveHeaders && MachOOpt)) {
     cl::PrintHelpMessage();
     return 2;
   }
@@ -945,5 +901,5 @@ int main(int argc, char **argv) {
   std::for_each(InputFilenames.begin(), InputFilenames.end(),
                 DumpInput);
 
-  return 0;
+  return ReturnValue;
 }