]> git.saurik.com Git - apple/ld64.git/blobdiff - src/other/ObjectDump.cpp
ld64-409.12.tar.gz
[apple/ld64.git] / src / other / ObjectDump.cpp
index 25352b1b3b9cf066f8c184082bc6fbf0d22cf65a..5a355dc952f7ac33b3e77869ef1096baf416f09a 100644 (file)
@@ -1,6 +1,6 @@
 /* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*- 
  *
- * Copyright (c) 2005-2006 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 2005-2010 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
 #include <sys/stat.h>
 #include <sys/mman.h>
 #include <fcntl.h>
-#include <fcntl.h>
-
-#include "MachOReaderRelocatable.hpp"
+#include <mach-o/nlist.h>
+#include <mach-o/stab.h>
+#include <mach-o/fat.h>
+#include <mach-o/loader.h>
 
-#define LTO_SUPPORT 1
+#include "MachOFileAbstraction.hpp"
+#include "parsers/macho_relocatable_file.h"
+#include "parsers/lto_file.h"
 
-#if LTO_SUPPORT
-       #include "LTOReader.hpp"
-#endif
+const ld::VersionSet ld::File::_platforms;
 
 static bool                    sDumpContent= true;
 static bool                    sDumpStabs      = false;
 static bool                    sSort           = true;
 static bool                    sNMmode         = false;
-static cpu_type_t              sPreferredArch = CPU_TYPE_I386;
+static bool                    sShowSection                    = true;
+static bool                    sShowDefinitionKind             = true;
+static bool                    sShowCombineKind                = true;
+static bool                    sShowLineInfo                   = true;
+
+static cpu_type_t              sPreferredArch = 0xFFFFFFFF;
 static cpu_subtype_t   sPreferredSubArch = 0xFFFFFFFF;
-static const char* sMatchName;
+static const char* sMatchName = NULL;
 static int sPrintRestrict;
 static int sPrintAlign;
 static int sPrintName;
 
-
  __attribute__((noreturn))
 void throwf(const char* format, ...) 
 {
@@ -71,12 +76,12 @@ void warning(const char* format, ...)
        fprintf(stderr, "\n");
 }
 
-static void dumpStabs(std::vector<ObjectFile::Reader::Stab>* stabs)
+static void dumpStabs(const std::vector<ld::relocatable::File::Stab>* stabs)
 {
        // debug info
        printf("stabs: (%lu)\n", stabs->size());
-       for (std::vector<ObjectFile::Reader::Stab>::iterator it = stabs->begin(); it != stabs->end(); ++it ) {
-               ObjectFile::Reader::Stab& stab = *it;
+       for (std::vector<ld::relocatable::File::Stab>::const_iterator it = stabs->begin(); it != stabs->end(); ++it ) {
+               const ld::relocatable::File::Stab& stab = *it;
                const char* code = "?????";
                switch (stab.type) {
                        case N_GSYM:
@@ -164,24 +169,24 @@ static void dumpStabs(std::vector<ObjectFile::Reader::Stab>* stabs)
                                code =  "LENG";
                                break;
                }
-               printf("  [atom=%20s] %02X %04X %s %s\n", ((stab.atom != NULL) ? stab.atom->getDisplayName() : ""), stab.other, stab.desc, code, stab.string);
+               printf("  [atom=%20s] %02X %04X %s %s\n", ((stab.atom != NULL) ? stab.atom->name() : ""), stab.other, stab.desc, code, stab.string);
        }
 }
 
-
-static void dumpAtomLikeNM(ObjectFile::Atom* atom)
+#if 0
+static void dumpAtomLikeNM(ld::Atom* atom)
 {
-       uint32_t size = atom->getSize();
+       uint32_t size = atom->size();
        
        const char* visibility;
-       switch ( atom->getScope() ) {
-               case ObjectFile::Atom::scopeTranslationUnit:
+       switch ( atom->scope() ) {
+               case ld::Atom::scopeTranslationUnit:
                        visibility = "internal";
                        break;
-               case ObjectFile::Atom::scopeLinkageUnit:
+               case ld::Atom::scopeLinkageUnit:
                        visibility = "hidden  ";
                        break;
-               case ObjectFile::Atom::scopeGlobal:
+               case ld::Atom::scopeGlobal:
                        visibility = "global  ";
                        break;
                default:
@@ -190,17 +195,17 @@ static void dumpAtomLikeNM(ObjectFile::Atom* atom)
        }
 
        const char* kind;
-       switch ( atom->getDefinitionKind() ) {
-               case ObjectFile::Atom::kRegularDefinition:
+       switch ( atom->definitionKind() ) {
+               case ld::Atom::kRegularDefinition:
                        kind = "regular  ";
                        break;
-               case ObjectFile::Atom::kTentativeDefinition:
+               case ld::Atom::kTentativeDefinition:
                        kind = "tentative";
                        break;
-               case ObjectFile::Atom::kWeakDefinition:
+               case ld::Atom::kWeakDefinition:
                        kind = "weak     ";
                        break;
-               case ObjectFile::Atom::kAbsoluteSymbol:
+               case ld::Atom::kAbsoluteSymbol:
                        kind = "absolute ";
                        break;
                default:
@@ -208,31 +213,31 @@ static void dumpAtomLikeNM(ObjectFile::Atom* atom)
                        break;
        }
 
-       printf("0x%08X %s %s %s\n", size, visibility, kind, atom->getDisplayName());
+       printf("0x%08X %s %s %s\n", size, visibility, kind, atom->name());
 }
 
 
-static void dumpAtom(ObjectFile::Atom* atom)
+static void dumpAtom(ld::Atom* atom)
 {
-       if(sMatchName && strcmp(sMatchName, atom->getDisplayName()))
+       if(sMatchName && strcmp(sMatchName, atom->name()))
                return;
 
        //printf("atom:    %p\n", atom);
        
        // name
        if(!sPrintRestrict || sPrintName)
-               printf("name:    %s\n",  atom->getDisplayName());
+               printf("name:    %s\n",  atom->name());
        
        // scope
        if(!sPrintRestrict)
-               switch ( atom->getScope() ) {
-               case ObjectFile::Atom::scopeTranslationUnit:
+               switch ( atom->scope() ) {
+               case ld::Atom::scopeTranslationUnit:
                        printf("scope:   translation unit\n");
                        break;
-               case ObjectFile::Atom::scopeLinkageUnit:
+               case ld::Atom::scopeLinkageUnit:
                        printf("scope:   linkage unit\n");
                        break;
-               case ObjectFile::Atom::scopeGlobal:
+               case ld::Atom::scopeGlobal:
                        printf("scope:   global\n");
                        break;
                default:
@@ -241,23 +246,23 @@ static void dumpAtom(ObjectFile::Atom* atom)
        
        // kind
        if(!sPrintRestrict)
-               switch ( atom->getDefinitionKind() ) {
-               case ObjectFile::Atom::kRegularDefinition:
+               switch ( atom->definitionKind() ) {
+               case ld::Atom::kRegularDefinition:
                        printf("kind:     regular\n");
                        break;
-               case ObjectFile::Atom::kWeakDefinition:
+               case ld::Atom::kWeakDefinition:
                        printf("kind:     weak\n");
                        break;
-               case ObjectFile::Atom::kTentativeDefinition:
+               case ld::Atom::kTentativeDefinition:
                        printf("kind:     tentative\n");
                        break;
-               case ObjectFile::Atom::kExternalDefinition:
+               case ld::Atom::kExternalDefinition:
                        printf("kind:     import\n");
                        break;
-               case ObjectFile::Atom::kExternalWeakDefinition:
+               case ld::Atom::kExternalWeakDefinition:
                        printf("kind:     weak import\n");
                        break;
-               case ObjectFile::Atom::kAbsoluteSymbol:
+               case ld::Atom::kAbsoluteSymbol:
                        printf("kind:     absolute symbol\n");
                        break;
                default:
@@ -265,16 +270,14 @@ static void dumpAtom(ObjectFile::Atom* atom)
                }
 
        // segment and section
-       if(!sPrintRestrict && (atom->getSectionName() != NULL) )
-               printf("section: %s,%s\n", atom->getSegment().getName(), atom->getSectionName());
+       if(!sPrintRestrict && (atom->section().sectionName() != NULL) )
+               printf("section: %s,%s\n", atom->section().segmentName(), atom->section().sectionName());
 
        // attributes
        if(!sPrintRestrict) {
                printf("attrs:   ");
                if ( atom->dontDeadStrip() )
                        printf("dont-dead-strip ");
-               if ( atom->isZeroFill() )
-                       printf("zero-fill ");
                if ( atom->isThumb() )
                        printf("thumb ");
                printf("\n");
@@ -282,20 +285,20 @@ static void dumpAtom(ObjectFile::Atom* atom)
        
        // size
        if(!sPrintRestrict)
-               printf("size:    0x%012llX\n", atom->getSize());
+               printf("size:    0x%012llX\n", atom->size());
        
        // alignment
        if(!sPrintRestrict || sPrintAlign)
-               printf("align:    %u mod %u\n", atom->getAlignment().modulus, (1 << atom->getAlignment().powerOf2) );
+               printf("align:    %u mod %u\n", atom->alignment().modulus, (1 << atom->alignment().powerOf2) );
 
        // content
        if (!sPrintRestrict && sDumpContent ) { 
-               uint64_t size = atom->getSize();
+               uint64_t size = atom->size();
                if ( size < 4096 ) {
                        uint8_t content[size];
                        atom->copyRawContent(content);
                        printf("content: ");
-                       if ( atom->getContentType() == ObjectFile::Atom::kCStringType ) {
+                       if ( atom->contentType() == ld::Atom::typeCString ) {
                                printf("\"");
                                for (unsigned int i=0; i < size; ++i) {
                                        if(content[i]<'!' || content[i]>=127)
@@ -317,12 +320,12 @@ static void dumpAtom(ObjectFile::Atom* atom)
        if(!sPrintRestrict) {
                if ( atom->beginUnwind() != atom->endUnwind() ) {
                        printf("unwind encodings:\n");
-                       for (ObjectFile::UnwindInfo::iterator it = atom->beginUnwind(); it != atom->endUnwind(); ++it) {
+                       for (ld::Atom::UnwindInfo::iterator it = atom->beginUnwind(); it != atom->endUnwind(); ++it) {
                                printf("\t 0x%04X  0x%08X\n", it->startOffset, it->unwindInfo);
                        }
                }
        }
-       
+#if 0  
        // references
        if(!sPrintRestrict) {
                std::vector<ObjectFile::Reference*>&  references = atom->getReferences();
@@ -333,13 +336,12 @@ static void dumpAtom(ObjectFile::Atom* atom)
                        printf("   %s\n", ref->getDescription());
                }
        }
-       
+#endif 
        // line info
        if(!sPrintRestrict) {
-               std::vector<ObjectFile::LineInfo>* lineInfo = atom->getLineInfo();
-               if ( (lineInfo != NULL) && (lineInfo->size() > 0) ) {
-                       printf("line info: (%lu)\n", lineInfo->size());
-                       for (std::vector<ObjectFile::LineInfo>::iterator it = lineInfo->begin(); it != lineInfo->end(); ++it) {
+               if ( atom->beginLineInfo() != atom->endLineInfo() ) {
+                       printf("line info:\n");
+                       for (ld::Atom::LineInfo::iterator it = atom->beginLineInfo(); it != atom->endLineInfo(); ++it) {
                                printf("   offset 0x%04X, line %d, file %s\n", it->atomOffset, it->lineNumber, it->fileName);
                        }
                }
@@ -348,31 +350,838 @@ static void dumpAtom(ObjectFile::Atom* atom)
        if(!sPrintRestrict)
                printf("\n");
 }
-
+#endif
 struct AtomSorter
 {
-     bool operator()(const ObjectFile::Atom* left, const ObjectFile::Atom* right)
+     bool operator()(const ld::Atom* left, const ld::Atom* right)
      {
                if ( left == right )
                        return false;
-               int name = strcmp(left->getDisplayName(), right->getDisplayName());
-               if ( name == 0 )
-                       return (left->getSize() < right->getSize());
-               else
-                       return ( name < 0);
+               // first sort by segment name
+               int diff = strcmp(left->section().segmentName(), right->section().segmentName());
+               if ( diff != 0 )
+                       return (diff > 0);
+               
+               // then sort by section name
+               diff = strcmp(left->section().sectionName(), right->section().sectionName());
+               if ( diff != 0 )
+                       return (diff < 0);
+               
+               // then sort by atom name
+               diff = strcmp(left->name(), right->name());
+               if ( diff != 0 )
+                       return (diff < 0);
+               
+               // if cstring, sort by content
+               if ( left->contentType() == ld::Atom::typeCString ) {
+                       diff = strcmp((char*)left->rawContentPointer(), (char*)right->rawContentPointer());
+                       if ( diff != 0 )
+                               return (diff < 0);
+               }
+               else if ( left->section().type() == ld::Section::typeCStringPointer ) {
+                       // if pointer to c-string sort by name
+                       const char* leftString = NULL;
+                       assert(left->fixupsBegin() != left->fixupsEnd());
+                       for (ld::Fixup::iterator fit = left->fixupsBegin(); fit != left->fixupsEnd(); ++fit) {
+                               if ( fit->binding == ld::Fixup::bindingByContentBound ) {
+                                       const ld::Atom* cstringAtom = fit->u.target;
+                                       assert(cstringAtom->contentType() == ld::Atom::typeCString);
+                                       leftString = (char*)cstringAtom->rawContentPointer();
+                               }
+                       }
+                       const char* rightString = NULL;
+                       assert(right->fixupsBegin() != right->fixupsEnd());
+                       for (ld::Fixup::iterator fit = right->fixupsBegin(); fit != right->fixupsEnd(); ++fit) {
+                               if ( fit->binding == ld::Fixup::bindingByContentBound ) {
+                                       const ld::Atom* cstringAtom = fit->u.target;
+                                       assert(cstringAtom->contentType() == ld::Atom::typeCString);
+                                       rightString = (char*)cstringAtom->rawContentPointer();
+                               }
+                       }
+                       if ( leftString != rightString ) {
+                               assert(leftString != NULL);
+                               assert(rightString != NULL);
+                               diff = strcmp(leftString, rightString);
+                               if ( diff != 0 )
+                                       return (diff < 0);
+                       }
+               }
+               else if ( left->section().type() == ld::Section::typeLiteral4 ) {
+                       // if literal sort by content
+                       uint32_t leftValue  = *(uint32_t*)left->rawContentPointer();
+                       uint32_t rightValue = *(uint32_t*)right->rawContentPointer();
+                       diff = (leftValue - rightValue);
+                       if ( diff != 0 )
+                               return (diff < 0);
+               }
+               else if ( left->section().type() == ld::Section::typeCFI ) {
+                       // if __he_frame sort by address
+                       diff = (left->objectAddress() - right->objectAddress());
+                       if ( diff != 0 )
+                               return (diff < 0);
+               }
+               else if ( left->section().type() == ld::Section::typeNonLazyPointer ) {
+                       // if non-lazy-pointer sort by name
+                       const char* leftString = NULL;
+                       assert(left->fixupsBegin() != left->fixupsEnd());
+                       for (ld::Fixup::iterator fit = left->fixupsBegin(); fit != left->fixupsEnd(); ++fit) {
+                               if ( fit->binding == ld::Fixup::bindingByNameUnbound ) {
+                                       leftString = fit->u.name;
+                               }
+                               else if ( fit->binding == ld::Fixup::bindingDirectlyBound ) {
+                                       leftString = fit->u.target->name();
+                               }
+                       }
+                       const char* rightString = NULL;
+                       assert(right->fixupsBegin() != right->fixupsEnd());
+                       for (ld::Fixup::iterator fit = right->fixupsBegin(); fit != right->fixupsEnd(); ++fit) {
+                               if ( fit->binding == ld::Fixup::bindingByNameUnbound ) {
+                                       rightString = fit->u.name;
+                               }
+                               else if ( fit->binding == ld::Fixup::bindingDirectlyBound ) {
+                                       rightString = fit->u.target->name();
+                               }
+                       }
+                       assert(leftString != NULL);
+                       assert(rightString != NULL);
+                       diff = strcmp(leftString, rightString);
+                       if ( diff != 0 )
+                               return (diff < 0);
+               }
+               
+               // else sort by size
+               return (left->size() < right->size());
      }
 };
 
 
-static void dumpFile(ObjectFile::Reader* reader)
+class dumper : public ld::File::AtomHandler
+{
+public:
+                       void dump();
+       virtual void doAtom(const ld::Atom&);
+       virtual void doFile(const ld::File&) {} 
+private:
+       void                    dumpAtom(const ld::Atom& atom);
+       const char*             scopeString(const ld::Atom&);
+       const char*             definitionString(const ld::Atom&);
+       const char*             combineString(const ld::Atom&);
+       const char*             inclusionString(const ld::Atom&);
+       const char*             attributeString(const ld::Atom&);
+       const char*             makeName(const ld::Atom& atom);
+       const char*             referenceTargetAtomName(const ld::Fixup* ref);
+       void                    dumpFixup(const ld::Fixup* ref);
+       
+       uint64_t                addressOfFirstAtomInSection(const ld::Section&);
+       
+       std::vector<const ld::Atom*> _atoms;
+};
+
+const char*    dumper::scopeString(const ld::Atom& atom)
+{
+       switch ( (ld::Atom::Scope)atom.scope() ) {
+               case ld::Atom::scopeTranslationUnit:
+                       return "translation-unit";
+               case ld::Atom::scopeLinkageUnit:
+                       return "hidden";
+               case ld::Atom::scopeGlobal:
+                       if ( atom.autoHide() )
+                               return "global but automatically hidden";
+                       else
+                               return "global";
+       }
+       return "UNKNOWN";       
+}
+
+const char*    dumper::definitionString(const ld::Atom& atom)
+{
+       switch ( (ld::Atom::Definition)atom.definition() ) {
+               case ld::Atom::definitionRegular:
+                       return "regular";
+               case ld::Atom::definitionTentative:
+                       return "tentative";
+               case ld::Atom::definitionAbsolute:
+                       return "absolute";
+               case ld::Atom::definitionProxy:
+                       return "proxy";
+               }
+       return "UNKNOWN";       
+}
+
+const char*    dumper::combineString(const ld::Atom& atom)
+{
+       switch ( (ld::Atom::Combine)atom.combine() ) {
+               case ld::Atom::combineNever:
+                       return "never";
+               case ld::Atom::combineByName:
+                       return "by-name";
+               case ld::Atom::combineByNameAndContent:
+                       return "by-name-and-content";
+               case ld::Atom::combineByNameAndReferences:
+                       return "by-name-and-references";
+               }
+       return "UNKNOWN";       
+}
+
+const char*    dumper::inclusionString(const ld::Atom& atom)
+{
+       switch ( (ld::Atom::SymbolTableInclusion)atom.symbolTableInclusion() ) {
+               case ld::Atom::symbolTableNotIn:
+                       return "not in";
+               case ld::Atom::symbolTableNotInFinalLinkedImages:
+                       return "not in final linked images";
+               case ld::Atom::symbolTableIn:
+                       return "in";
+               case ld::Atom::symbolTableInAndNeverStrip:
+                       return "in and never strip";
+               case ld::Atom::symbolTableInAsAbsolute:
+                       return "in as absolute";
+               case ld::Atom::symbolTableInWithRandomAutoStripLabel:
+                       return "in as random auto-strip label";
+               }
+       return "UNKNOWN";       
+}
+
+
+
+const char*    dumper::attributeString(const ld::Atom& atom)
+{
+       static char buffer[256];
+       buffer[0] = '\0';
+       
+       if ( atom.dontDeadStrip() )
+               strcat(buffer, "dont-dead-strip ");
+
+       if ( atom.isThumb() )
+               strcat(buffer, "thumb ");
+               
+       if ( atom.isAlias() )
+               strcat(buffer, "alias ");
+               
+       if ( atom.contentType() == ld::Atom::typeResolver )
+               strcat(buffer, "resolver ");
+               
+       return buffer;
+}
+
+const char* dumper::makeName(const ld::Atom& atom)
+{
+       static char buffer[4096];
+       strcpy(buffer, "???");
+       switch ( atom.symbolTableInclusion() ) {
+               case ld::Atom::symbolTableNotIn:
+                       if ( atom.contentType() == ld::Atom::typeCString ) {
+                               strcpy(buffer, "cstring=");
+                               strlcat(buffer, (char*)atom.rawContentPointer(), 4096);
+                       }
+                       else if ( atom.section().type() == ld::Section::typeLiteral4 ) {
+                               char temp[16];
+                               strcpy(buffer, "literal4=");
+                               uint32_t value = *(uint32_t*)atom.rawContentPointer();
+                               sprintf(temp, "0x%08X", value);
+                               strcat(buffer, temp);
+                       }
+                       else if ( atom.section().type() == ld::Section::typeLiteral8 ) {
+                               char temp[32];
+                               strcpy(buffer, "literal8=");
+                               uint32_t value1 = *(uint32_t*)atom.rawContentPointer();
+                               uint32_t value2 = ((uint32_t*)atom.rawContentPointer())[1];
+                               sprintf(temp, "0x%08X%08X", value1, value2);
+                               strcat(buffer, temp);
+                       }
+                       else if ( atom.section().type() == ld::Section::typeLiteral16 ) {
+                               char temp[64];
+                               strcpy(buffer, "literal16=");
+                               uint32_t value1 = *(uint32_t*)atom.rawContentPointer();
+                               uint32_t value2 = ((uint32_t*)atom.rawContentPointer())[1];
+                               uint32_t value3 = ((uint32_t*)atom.rawContentPointer())[2];
+                               uint32_t value4 = ((uint32_t*)atom.rawContentPointer())[3];
+                               sprintf(temp, "0x%08X%08X%08X%08X", value1, value2, value3, value4);
+                               strcat(buffer, temp);
+                       }
+                       else if ( atom.section().type() == ld::Section::typeCStringPointer ) {
+                               assert(atom.fixupsBegin() != atom.fixupsEnd());
+                               for (ld::Fixup::iterator fit = atom.fixupsBegin(); fit != atom.fixupsEnd(); ++fit) {
+                                       if ( fit->binding == ld::Fixup::bindingByContentBound ) {
+                                               const ld::Atom* cstringAtom = fit->u.target;
+                                               if ( (cstringAtom != NULL) && (cstringAtom->contentType() == ld::Atom::typeCString) ) {
+                                                       strlcpy(buffer, atom.name(), 4096);
+                                                       strlcat(buffer, "=", 4096);
+                                                       strlcat(buffer, (char*)cstringAtom->rawContentPointer(), 4096);
+                                               }
+                                       }
+                               }
+                       }
+                       else if ( atom.section().type() == ld::Section::typeNonLazyPointer ) {
+                               assert(atom.fixupsBegin() != atom.fixupsEnd());
+                               for (ld::Fixup::iterator fit = atom.fixupsBegin(); fit != atom.fixupsEnd(); ++fit) {
+                                       if ( fit->binding == ld::Fixup::bindingByNameUnbound ) {
+                                               strcpy(buffer, "non-lazy-pointer-to:");
+                                               strlcat(buffer, fit->u.name, 4096);
+                                               return buffer;
+                                       }
+                                       else if ( fit->binding == ld::Fixup::bindingDirectlyBound ) {
+                                               strcpy(buffer, "non-lazy-pointer-to-local:");
+                                               strlcat(buffer, fit->u.target->name(), 4096);
+                                               return buffer;
+                                       }
+                               }
+                               strlcpy(buffer, atom.name(), 4096);
+                       }
+                       else {
+                               uint64_t sectAddr = addressOfFirstAtomInSection(atom.section());
+                               sprintf(buffer, "%s@%s+0x%08llX", atom.name(), atom.section().sectionName(), atom.objectAddress()-sectAddr);
+                       }
+                       break;
+               case ld::Atom::symbolTableNotInFinalLinkedImages:
+               case ld::Atom::symbolTableIn:
+               case ld::Atom::symbolTableInAndNeverStrip:
+               case ld::Atom::symbolTableInAsAbsolute:
+               case ld::Atom::symbolTableInWithRandomAutoStripLabel:
+                       strlcpy(buffer, atom.name(), 4096);
+                       break;
+       }
+       return buffer;
+}
+
+const char* dumper::referenceTargetAtomName(const ld::Fixup* ref)
+{
+       static char buffer[4096];
+       switch ( ref->binding ) {
+               case ld::Fixup::bindingNone:
+                       return "NO BINDING";
+               case ld::Fixup::bindingByNameUnbound:
+                       strcpy(buffer, "by-name(");
+                       strlcat(buffer, ref->u.name, 4096);
+                       strlcat(buffer, ")", 4096);
+                       return buffer;
+                       //return ref->u.name;
+               case ld::Fixup::bindingByContentBound:
+                       strcpy(buffer, "by-content(");
+                       strlcat(buffer, makeName(*ref->u.target), 4096);
+                       strlcat(buffer, ")", 4096);
+                       return buffer;
+               case ld::Fixup::bindingDirectlyBound:
+                       strcpy(buffer, "direct(");
+                       strlcat(buffer, makeName(*ref->u.target), 4096);
+                       strlcat(buffer, ")", 4096);
+                       return buffer;
+               case ld::Fixup::bindingsIndirectlyBound:
+                       return "BOUND INDIRECTLY";
+       }
+       return "BAD BINDING";
+}
+
+
+void dumper::dumpFixup(const ld::Fixup* ref)
+{
+       if ( ref->weakImport ) {
+               printf("weak_import ");
+       }
+       switch ( (ld::Fixup::Kind)(ref->kind) ) {
+               case ld::Fixup::kindNone:
+                       printf("none");
+                       break;
+               case ld::Fixup::kindNoneFollowOn:
+                       printf("followed by %s", referenceTargetAtomName(ref));
+                       break;
+               case ld::Fixup::kindNoneGroupSubordinate:
+                       printf("group subordinate %s", referenceTargetAtomName(ref));
+                       break;
+               case ld::Fixup::kindNoneGroupSubordinateFDE:
+                       printf("group subordinate FDE %s", referenceTargetAtomName(ref));
+                       break;
+               case ld::Fixup::kindNoneGroupSubordinateLSDA:
+                       printf("group subordinate LSDA %s", referenceTargetAtomName(ref));
+                       break;
+               case ld::Fixup::kindNoneGroupSubordinatePersonality:
+                       printf("group subordinate personality %s", referenceTargetAtomName(ref));
+                       break;
+               case ld::Fixup::kindSetTargetAddress:
+                       printf("%s", referenceTargetAtomName(ref));
+                       break;
+               case ld::Fixup::kindSubtractTargetAddress:
+                       printf(" - %s", referenceTargetAtomName(ref));
+                       break;
+               case ld::Fixup::kindAddAddend:
+                       printf(" + 0x%llX", ref->u.addend);
+                       break;
+               case ld::Fixup::kindSubtractAddend:
+                       printf(" - 0x%llX", ref->u.addend);
+                       break;
+               case ld::Fixup::kindSetTargetImageOffset:
+                       printf("imageOffset(%s)", referenceTargetAtomName(ref));
+                       break;
+               case ld::Fixup::kindSetTargetSectionOffset:
+                       printf("sectionOffset(%s)", referenceTargetAtomName(ref));
+                       break;
+               case ld::Fixup::kindStore8:
+                       printf(", then store byte");
+                       break;
+               case ld::Fixup::kindStoreLittleEndian16:
+                       printf(", then store 16-bit little endian");
+                       break;
+               case ld::Fixup::kindStoreLittleEndianLow24of32:
+                       printf(", then store low 24-bit little endian");
+                       break;
+               case ld::Fixup::kindStoreLittleEndian32:
+                       printf(", then store 32-bit little endian");
+                       break;
+               case ld::Fixup::kindStoreLittleEndian64:
+                       printf(", then store 64-bit little endian");
+                       break;
+               case ld::Fixup::kindStoreBigEndian16:
+                       printf(", then store 16-bit big endian");
+                       break;
+               case ld::Fixup::kindStoreBigEndianLow24of32:
+                       printf(", then store low 24-bit big endian");
+                       break;
+               case ld::Fixup::kindStoreBigEndian32:
+                       printf(", then store 32-bit big endian");
+                       break;
+               case ld::Fixup::kindStoreBigEndian64:
+                       printf(", then store 64-bit big endian");
+                       break;
+               case ld::Fixup::kindStoreX86BranchPCRel8:
+                       printf(", then store as x86 8-bit pcrel branch");
+                       break;
+               case ld::Fixup::kindStoreX86BranchPCRel32:
+                       printf(", then store as x86 32-bit pcrel branch");
+                       break;
+               case ld::Fixup::kindStoreX86PCRel8:
+                       printf(", then store as x86 8-bit pcrel");
+                       break;
+               case ld::Fixup::kindStoreX86PCRel16:
+                       printf(", then store as x86 16-bit pcrel");
+                       break;
+               case ld::Fixup::kindStoreX86PCRel32:
+                       printf(", then store as x86 32-bit pcrel");
+                       break;
+               case ld::Fixup::kindStoreX86PCRel32_1:
+                       printf(", then store as x86 32-bit pcrel from +1");
+                       break;
+               case ld::Fixup::kindStoreX86PCRel32_2:
+                       printf(", then store as x86 32-bit pcrel from +2");
+                       break;
+               case ld::Fixup::kindStoreX86PCRel32_4:
+                       printf(", then store as x86 32-bit pcrel from +4");
+                       break;
+               case ld::Fixup::kindStoreX86PCRel32GOTLoad:
+                       printf(", then store as x86 32-bit pcrel GOT load");
+                       break;
+               case ld::Fixup::kindStoreX86PCRel32GOTLoadNowLEA:
+                       printf(", then store as x86 32-bit pcrel GOT load -> LEA");
+                       break;
+               case ld::Fixup::kindStoreX86PCRel32GOT:
+                       printf(", then store as x86 32-bit pcrel GOT access");
+                       break;
+               case ld::Fixup::kindStoreX86PCRel32TLVLoad:
+                       printf(", then store as x86 32-bit pcrel TLV load");
+                       break;
+               case ld::Fixup::kindStoreX86PCRel32TLVLoadNowLEA:
+                       printf(", then store as x86 32-bit pcrel TLV load");
+                       break;
+               case ld::Fixup::kindStoreX86Abs32TLVLoad:
+                       printf(", then store as x86 32-bit absolute TLV load");
+                       break;
+               case ld::Fixup::kindStoreX86Abs32TLVLoadNowLEA:
+                       printf(", then store as x86 32-bit absolute TLV load -> LEA");
+                       break;
+               case ld::Fixup::kindStoreARMBranch24:
+                       printf(", then store as ARM 24-bit pcrel branch");
+                       break;
+               case ld::Fixup::kindStoreThumbBranch22:
+                       printf(", then store as Thumb 22-bit pcrel branch");
+                       break;
+               case ld::Fixup::kindStoreARMLoad12:
+                       printf(", then store as ARM 12-bit pcrel load");
+                       break;
+               case ld::Fixup::kindStoreARMLow16:
+                       printf(", then store low-16 in ARM movw");
+                       break;
+               case ld::Fixup::kindStoreARMHigh16:
+                       printf(", then store high-16 in ARM movt");
+                       break;
+               case ld::Fixup::kindStoreThumbLow16:
+                       printf(", then store low-16 in Thumb movw");
+                       break;
+               case ld::Fixup::kindStoreThumbHigh16:
+                       printf(", then store high-16 in Thumb movt");
+                       break;
+#if SUPPORT_ARCH_arm64
+               case ld::Fixup::kindStoreARM64Branch26:
+                       printf(", then store as ARM64 26-bit pcrel branch");
+                       break;
+               case ld::Fixup::kindStoreARM64Page21:
+                       printf(", then store as ARM64 21-bit pcrel ADRP");
+                       break;
+               case ld::Fixup::kindStoreARM64PageOff12:
+                       printf(", then store as ARM64 12-bit offset");
+                       break;
+               case ld::Fixup::kindStoreARM64GOTLoadPage21:
+                       printf(", then store as ARM64 21-bit pcrel ADRP of GOT");
+                       break;
+               case ld::Fixup::kindStoreARM64GOTLoadPageOff12:
+                       printf(", then store as ARM64 12-bit page offset of GOT");
+                       break;
+               case ld::Fixup::kindStoreARM64GOTLeaPage21:
+                       printf(", then store as ARM64 21-bit pcrel ADRP of GOT lea");
+                       break;
+               case ld::Fixup::kindStoreARM64GOTLeaPageOff12:
+                       printf(", then store as ARM64 12-bit page offset of GOT lea");
+                       break;
+               case ld::Fixup::kindStoreARM64TLVPLoadPage21:
+                       printf(", then store as ARM64 21-bit pcrel ADRP of TLVP");
+                       break;
+               case ld::Fixup::kindStoreARM64TLVPLoadPageOff12:
+                       printf(", then store as ARM64 12-bit page offset of TLVP");
+                       break;
+               case ld::Fixup::kindStoreARM64TLVPLoadNowLeaPage21:
+                       printf(", then store as ARM64 21-bit pcrel ADRP of lea of TLVP");
+                       break;
+               case ld::Fixup::kindStoreARM64TLVPLoadNowLeaPageOff12:
+                       printf(", then store as ARM64 12-bit page offset of lea of TLVP");
+                       break;
+               case ld::Fixup::kindStoreARM64PointerToGOT:
+                       printf(", then store as 64-bit pointer to GOT entry");
+                       break;
+               case ld::Fixup::kindStoreARM64PCRelToGOT:
+                       printf(", then store as 32-bit delta to GOT entry");
+                       break;
+#endif
+               case ld::Fixup::kindDtraceExtra:
+                       printf("dtrace static probe extra info");
+                       break;
+               case ld::Fixup::kindStoreX86DtraceCallSiteNop:
+                       printf("x86 dtrace static probe site");
+                       break;
+               case ld::Fixup::kindStoreX86DtraceIsEnableSiteClear:
+                       printf("x86 dtrace static is-enabled site");
+                       break;
+               case ld::Fixup::kindStoreARMDtraceCallSiteNop:
+                       printf("ARM dtrace static probe site");
+                       break;
+               case ld::Fixup::kindStoreARMDtraceIsEnableSiteClear:
+                       printf("ARM dtrace static is-enabled site");
+                       break;
+               case ld::Fixup::kindStoreThumbDtraceCallSiteNop:
+                       printf("Thumb dtrace static probe site");
+                       break;
+               case ld::Fixup::kindStoreThumbDtraceIsEnableSiteClear:
+                       printf("Thumb dtrace static is-enabled site");
+                       break;
+#if SUPPORT_ARCH_arm64
+               case ld::Fixup::kindStoreARM64DtraceCallSiteNop:
+                       printf("ARM64 dtrace static probe site");
+                       break;
+               case ld::Fixup::kindStoreARM64DtraceIsEnableSiteClear:
+                       printf("ARM64 dtrace static is-enabled site");
+                       break;
+#endif
+               case ld::Fixup::kindLazyTarget:
+                       printf("lazy reference to external symbol %s", referenceTargetAtomName(ref));
+                       break;
+               case ld::Fixup::kindSetLazyOffset:
+                       printf("offset of lazy binding info for %s", referenceTargetAtomName(ref));
+                       break;
+               case ld::Fixup::kindIslandTarget:
+                       printf("ultimate target of island %s", referenceTargetAtomName(ref));
+                       break;
+               case ld::Fixup::kindDataInCodeStartData:
+                       printf("start of data in code");
+                       break;
+               case ld::Fixup::kindDataInCodeStartJT8:
+                       printf("start of jump table 8 data in code");
+                       break;
+               case ld::Fixup::kindDataInCodeStartJT16:
+                       printf("start of jump table 16 data in code");
+                       break;
+               case ld::Fixup::kindDataInCodeStartJT32:
+                       printf("start of jump table 32 data in code");
+                       break;
+               case ld::Fixup::kindDataInCodeStartJTA32:
+                       printf("start of jump table absolute 32 data in code");
+                       break;
+               case ld::Fixup::kindDataInCodeEnd:
+                       printf("end of data in code");
+                       break;
+               case ld::Fixup::kindLinkerOptimizationHint:
+#if SUPPORT_ARCH_arm64
+                       ld::Fixup::LOH_arm64 extra;
+                       extra.addend = ref->u.addend;
+                       printf("ARM64 hint: ");
+                       switch(extra.info.kind) {
+                               case LOH_ARM64_ADRP_ADRP:
+                                       printf("ADRP-ADRP");
+                                       break;
+                               case LOH_ARM64_ADRP_LDR:
+                                       printf("ADRP-LDR");
+                                       break;
+                               case LOH_ARM64_ADRP_ADD_LDR:
+                                       printf("ADRP-ADD-LDR");
+                                       break;
+                               case LOH_ARM64_ADRP_LDR_GOT_LDR:
+                                       printf("ADRP-LDR-GOT-LDR");
+                                       break;
+                               case LOH_ARM64_ADRP_ADD_STR:
+                                       printf("ADRP-ADD-STR");
+                                       break;
+                               case LOH_ARM64_ADRP_LDR_GOT_STR:
+                                       printf("ADRP-LDR-GOT-STR");
+                                       break;
+                               case LOH_ARM64_ADRP_ADD:
+                                       printf("ADRP-ADD");
+                                       break;
+                               default:
+                                       printf("kind=%d", extra.info.kind);
+                                       break;
+                       }
+                       printf(", offset1=0x%X", (extra.info.delta1 << 2)  + ref->offsetInAtom);
+                       if ( extra.info.count > 0 )
+                               printf(", offset2=0x%X", (extra.info.delta2 << 2) + ref->offsetInAtom);
+                       if ( extra.info.count > 1 )
+                               printf(", offset3=0x%X", (extra.info.delta3 << 2)  + ref->offsetInAtom);
+                       if ( extra.info.count > 2 )
+                               printf(", offset4=0x%X", (extra.info.delta4 << 2)  + ref->offsetInAtom);
+#endif                 
+                       break;
+               case ld::Fixup::kindStoreTargetAddressLittleEndian32:
+                       printf("store 32-bit little endian address of %s", referenceTargetAtomName(ref));
+                       break;
+               case ld::Fixup::kindStoreTargetAddressLittleEndian64:
+                       printf("store 64-bit little endian address of %s", referenceTargetAtomName(ref));
+                       break;
+               case ld::Fixup::kindStoreTargetAddressBigEndian32:
+                       printf("store 32-bit big endian address of %s", referenceTargetAtomName(ref));
+                       break;
+               case ld::Fixup::kindStoreTargetAddressBigEndian64:
+                       printf("store 64-bit big endian address of %s", referenceTargetAtomName(ref));
+                       break;
+               case ld::Fixup::kindStoreTargetAddressX86PCRel32:
+                       printf("x86 store 32-bit pc-rel address of %s", referenceTargetAtomName(ref));
+                       break;
+               case ld::Fixup::kindStoreTargetAddressX86BranchPCRel32:
+                       printf("x86 store 32-bit pc-rel branch to %s", referenceTargetAtomName(ref));
+                       break;
+               case ld::Fixup::kindStoreTargetAddressX86PCRel32GOTLoad:
+                       printf("x86 store 32-bit pc-rel GOT load of %s", referenceTargetAtomName(ref));
+                       break;
+               case ld::Fixup::kindStoreTargetAddressX86PCRel32GOTLoadNowLEA:
+                       printf("x86 store 32-bit pc-rel lea of %s", referenceTargetAtomName(ref));
+                       break;
+               case ld::Fixup::kindStoreTargetAddressX86PCRel32TLVLoad:
+                       printf("x86 store 32-bit pc-rel TLV load of %s", referenceTargetAtomName(ref));
+                       break;
+               case ld::Fixup::kindStoreTargetAddressX86PCRel32TLVLoadNowLEA:
+                       printf("x86 store 32-bit pc-rel TLV lea of %s", referenceTargetAtomName(ref));
+                       break;
+               case ld::Fixup::kindStoreTargetAddressX86Abs32TLVLoad:
+                       printf("x86 store 32-bit absolute TLV load of %s", referenceTargetAtomName(ref));
+                       break;
+               case ld::Fixup::kindStoreTargetAddressX86Abs32TLVLoadNowLEA:
+                       printf("x86 store 32-bit absolute TLV lea of %s", referenceTargetAtomName(ref));
+                       break;
+               case ld::Fixup::kindStoreTargetAddressARMBranch24:
+                       printf("ARM store 24-bit pc-rel branch to %s", referenceTargetAtomName(ref));
+                       break;
+               case ld::Fixup::kindStoreTargetAddressThumbBranch22:
+                       printf("Thumb store 22-bit pc-rel branch to %s", referenceTargetAtomName(ref));
+                       break;
+               case ld::Fixup::kindStoreTargetAddressARMLoad12:
+                       printf("ARM store 12-bit pc-rel branch to %s", referenceTargetAtomName(ref));
+                       break;
+               case ld::Fixup::kindSetTargetTLVTemplateOffset:
+               case ld::Fixup::kindSetTargetTLVTemplateOffsetLittleEndian32:
+               case ld::Fixup::kindSetTargetTLVTemplateOffsetLittleEndian64:
+                       printf("tlv template offset of %s", referenceTargetAtomName(ref));
+                       break;
+#if SUPPORT_ARCH_arm64
+               case ld::Fixup::kindStoreTargetAddressARM64Branch26:
+                       printf("ARM64 store 26-bit pcrel branch to %s", referenceTargetAtomName(ref));
+                       break;
+               case ld::Fixup::kindStoreTargetAddressARM64Page21:
+                       printf("ARM64 store 21-bit pcrel ADRP to %s", referenceTargetAtomName(ref));
+                       break;
+               case ld::Fixup::kindStoreTargetAddressARM64PageOff12:
+                       printf("ARM64 store 12-bit page offset of %s", referenceTargetAtomName(ref));
+                       break;
+               case ld::Fixup::kindStoreTargetAddressARM64GOTLoadPage21:
+                       printf("ARM64 store 21-bit pcrel ADRP to GOT for %s", referenceTargetAtomName(ref));
+                       break;
+               case ld::Fixup::kindStoreTargetAddressARM64GOTLoadPageOff12:
+                       printf("ARM64 store 12-bit page offset of GOT of %s", referenceTargetAtomName(ref));
+                       break;
+               case ld::Fixup::kindStoreTargetAddressARM64GOTLeaPage21:
+                       printf("ARM64 store 21-bit pcrel ADRP to GOT lea for %s", referenceTargetAtomName(ref));
+                       break;
+               case ld::Fixup::kindStoreTargetAddressARM64GOTLeaPageOff12:
+                       printf("ARM64 store 12-bit page offset of GOT lea of %s", referenceTargetAtomName(ref));
+                       break;
+               case ld::Fixup::kindStoreTargetAddressARM64TLVPLoadPage21:
+                       printf("ARM64 store 21-bit pcrel ADRP to TLV for %s", referenceTargetAtomName(ref));
+                       break;
+               case ld::Fixup::kindStoreTargetAddressARM64TLVPLoadPageOff12:
+                       printf("ARM64 store 12-bit page offset of TLV of %s", referenceTargetAtomName(ref));
+                       break;
+               case ld::Fixup::kindStoreTargetAddressARM64TLVPLoadNowLeaPage21:
+                       printf("ARM64 store 21-bit pcrel ADRP to lea for TLV for %s", referenceTargetAtomName(ref));
+                       break;
+               case ld::Fixup::kindStoreTargetAddressARM64TLVPLoadNowLeaPageOff12:
+                       printf("ARM64 store 12-bit page offset of lea for TLV of %s", referenceTargetAtomName(ref));
+                       break;
+#endif
+               //default:
+               //      printf("unknown fixup");
+               //      break;
+       }
+}
+
+uint64_t dumper::addressOfFirstAtomInSection(const ld::Section& sect)
+{
+       uint64_t lowestAddr = (uint64_t)(-1);
+       for (std::vector<const ld::Atom*>::iterator it=_atoms.begin(); it != _atoms.end(); ++it) {
+               const ld::Atom* atom = *it;
+               if ( &atom->section() == &sect ) {
+                       if ( atom->objectAddress() < lowestAddr )
+                               lowestAddr = atom->objectAddress();
+               }
+       }
+       return lowestAddr;
+}
+
+void dumper::doAtom(const ld::Atom& atom)
+{
+       if ( (sMatchName != NULL) && (strcmp(sMatchName, atom.name()) != 0) )
+               return;
+       _atoms.push_back(&atom);
+}
+
+void dumper::dump()
+{      
+       if ( sSort ) 
+               std::sort(_atoms.begin(), _atoms.end(), AtomSorter());
+
+       for (std::vector<const ld::Atom*>::iterator it=_atoms.begin(); it != _atoms.end(); ++it) {
+               this->dumpAtom(**it);
+       }
+}      
+
+void dumper::dumpAtom(const ld::Atom& atom)
+{              
+       printf("name:     %s\n", makeName(atom)); 
+       printf("size:     0x%0llX\n", atom.size());
+       printf("align:    %u mod %u\n", atom.alignment().modulus, (1 << atom.alignment().powerOf2) );
+       printf("scope:    %s\n", scopeString(atom));
+       if ( sShowDefinitionKind ) 
+               printf("def:      %s\n", definitionString(atom));
+       if ( sShowCombineKind )
+               printf("combine:  %s\n", combineString(atom));
+       printf("symbol:   %s\n", inclusionString(atom));
+       printf("attrs:    %s\n", attributeString(atom));
+       if ( sShowSection )
+               printf("section:  %s,%s\n", atom.section().segmentName(), atom.section().sectionName());
+       if ( atom.beginUnwind() != atom.endUnwind() ) {
+               uint32_t lastOffset = 0;
+               uint32_t lastCUE = 0;
+               bool first = true;
+               const char* label = "unwind:";
+               for (ld::Atom::UnwindInfo::iterator it=atom.beginUnwind(); it != atom.endUnwind(); ++it) {
+                       if ( !first ) {
+                               printf("%s   0x%08X -> 0x%08X: 0x%08X\n", label, lastOffset, it->startOffset, lastCUE);
+                               label = "       ";
+                       }
+                       lastOffset = it->startOffset;
+                       lastCUE = it->unwindInfo;
+                       first = false;
+               }
+               printf("%s   0x%08X -> 0x%08X: 0x%08X\n", label, lastOffset, (uint32_t)atom.size(), lastCUE);
+       }
+       if ( atom.contentType() == ld::Atom::typeCString ) {
+               uint8_t buffer[atom.size()+2];
+               atom.copyRawContent(buffer);
+               buffer[atom.size()] = '\0';
+               printf("content:  \"%s\"\n", buffer);
+       }
+       if ( atom.fixupsBegin() != atom.fixupsEnd() ) {
+               printf("fixups:\n");
+               for (unsigned int off=0; off < atom.size()+1; ++off) {
+                       for (ld::Fixup::iterator it = atom.fixupsBegin(); it != atom.fixupsEnd(); ++it) {
+                               if ( it->offsetInAtom == off ) {
+                                       switch ( it->clusterSize ) {
+                                               case ld::Fixup::k1of1:
+                                                       printf("    0x%04X ", it->offsetInAtom);
+                                                       dumpFixup(it);
+                                                       break;
+                                               case ld::Fixup::k1of2:
+                                                       printf("    0x%04X ", it->offsetInAtom);
+                                                       dumpFixup(it);
+                                                       ++it;
+                                                       dumpFixup(it);
+                                                       break;
+                                               case ld::Fixup::k1of3:
+                                                       printf("    0x%04X ", it->offsetInAtom);
+                                                       dumpFixup(it);
+                                                       ++it;
+                                                       dumpFixup(it);
+                                                       ++it;
+                                                       dumpFixup(it);
+                                                       break;
+                                               case ld::Fixup::k1of4:
+                                                       printf("    0x%04X ", it->offsetInAtom);
+                                                       dumpFixup(it);
+                                                       ++it;
+                                                       dumpFixup(it);
+                                                       ++it;
+                                                       dumpFixup(it);
+                                                       ++it;
+                                                       dumpFixup(it);
+                                                       break;
+                                               case ld::Fixup::k1of5:
+                                                       printf("    0x%04X ", it->offsetInAtom);
+                                                       dumpFixup(it);
+                                                       ++it;
+                                                       dumpFixup(it);
+                                                       ++it;
+                                                       dumpFixup(it);
+                                                       ++it;
+                                                       dumpFixup(it);
+                                                       ++it;
+                                                       dumpFixup(it);
+                                                       break;
+                                               default:
+                                                       printf("   BAD CLUSTER SIZE: cluster=%d\n", it->clusterSize);
+                                       }
+                                       printf("\n");
+                               }
+                       }
+               }
+       }
+       if ( sShowLineInfo ) {
+               if ( atom.beginLineInfo() != atom.endLineInfo() ) {
+                       printf("line info:\n");
+                       for (ld::Atom::LineInfo::iterator it = atom.beginLineInfo(); it != atom.endLineInfo(); ++it) {
+                               printf("   offset 0x%04X, line %d, file %s\n", it->atomOffset, it->lineNumber, it->fileName);
+                       }
+               }
+       }
+       
+       printf("\n");
+}
+
+static void dumpFile(ld::relocatable::File* file)
 {
        // stabs debug info
-       if ( sDumpStabs && (reader->getDebugInfoKind() == ObjectFile::Reader::kDebugInfoStabs) ) {
-               std::vector<ObjectFile::Reader::Stab>* stabs = reader->getStabs();
+       if ( sDumpStabs && (file->debugInfo() == ld::relocatable::File::kDebugInfoStabs) ) {
+               const std::vector<ld::relocatable::File::Stab>* stabs = file->stabs();
                if ( stabs != NULL )
                        dumpStabs(stabs);
        }
-       
+       // dump atoms
+       dumper d;
+       file->forEachAtom(d);
+       d.dump();
+
+#if 0  
        // get all atoms
        std::vector<ObjectFile::Atom*> atoms = reader->getAtoms();
        
@@ -387,10 +1196,11 @@ static void dumpFile(ObjectFile::Reader* reader)
                else
                        dumpAtom(*it);
        }
+#endif
 }
 
 
-static ObjectFile::Reader* createReader(const char* path, const ObjectFile::ReaderOptions& options)
+static ld::relocatable::File* createReader(const char* path)
 {
        struct stat stat_buf;
        
@@ -400,37 +1210,82 @@ static ObjectFile::Reader* createReader(const char* path, const ObjectFile::Read
        ::fstat(fd, &stat_buf);
        uint8_t* p = (uint8_t*)::mmap(NULL, stat_buf.st_size, PROT_READ, MAP_FILE | MAP_PRIVATE, fd, 0);
        ::close(fd);
+       if ( p == (uint8_t*)(-1) )
+               throwf("cannot mmap file: %s", path);
        const mach_header* mh = (mach_header*)p;
+       uint64_t fileLen = stat_buf.st_size;
+       bool foundFatSlice = false;
        if ( mh->magic == OSSwapBigToHostInt32(FAT_MAGIC) ) {
                const struct fat_header* fh = (struct fat_header*)p;
                const struct fat_arch* archs = (struct fat_arch*)(p + sizeof(struct fat_header));
-               for (unsigned long i=0; i < OSSwapBigToHostInt32(fh->nfat_arch); ++i) {
-                       if ( OSSwapBigToHostInt32(archs[i].cputype) == (uint32_t)sPreferredArch ) {
-                               if ( ((uint32_t)sPreferredSubArch == 0xFFFFFFFF) || ((uint32_t)sPreferredSubArch == OSSwapBigToHostInt32(archs[i].cpusubtype)) ) {
-                                       p = p + OSSwapBigToHostInt32(archs[i].offset);
-                                       mh = (struct mach_header*)p;
-                                       break;
+               if ( (uint32_t)sPreferredArch ==  0xFFFFFFFF ) {
+                       // just dump first slice of fat .o file
+                       if ( OSSwapBigToHostInt32(fh->nfat_arch) > 0 )  {
+                               p = p + OSSwapBigToHostInt32(archs[0].offset);
+                               mh = (struct mach_header*)p;
+                               fileLen = OSSwapBigToHostInt32(archs[0].size);
+                               sPreferredArch = OSSwapBigToHostInt32(archs[0].cputype);
+                               sPreferredSubArch = OSSwapBigToHostInt32(archs[0].cpusubtype);
+                               foundFatSlice = true;
+                       }
+               }
+               else {
+                       for (unsigned long i=0; i < OSSwapBigToHostInt32(fh->nfat_arch); ++i) {
+                               if ( OSSwapBigToHostInt32(archs[i].cputype) == (uint32_t)sPreferredArch ) {
+                                       if ( ((uint32_t)sPreferredSubArch == 0xFFFFFFFF) || ((uint32_t)sPreferredSubArch == OSSwapBigToHostInt32(archs[i].cpusubtype)) ) {
+                                               p = p + OSSwapBigToHostInt32(archs[i].offset);
+                                               mh = (struct mach_header*)p;
+                                               fileLen = OSSwapBigToHostInt32(archs[i].size);
+                                               foundFatSlice = true;
+                                               break;
+                                       }
                                }
                        }
                }
        }
-       if ( mach_o::relocatable::Reader<x86>::validFile(p) )
-               return new mach_o::relocatable::Reader<x86>::Reader(p, path, 0, options, 0);
-       else if ( mach_o::relocatable::Reader<ppc>::validFile(p) )
-               return new mach_o::relocatable::Reader<ppc>::Reader(p, path, 0, options, 0);
-       else if ( mach_o::relocatable::Reader<ppc64>::validFile(p) )
-               return new mach_o::relocatable::Reader<ppc64>::Reader(p, path, 0, options, 0);
-       else if ( mach_o::relocatable::Reader<x86_64>::validFile(p) )
-               return new mach_o::relocatable::Reader<x86_64>::Reader(p, path, 0, options, 0);
-       else if ( mach_o::relocatable::Reader<arm>::validFile(p) )
-               return new mach_o::relocatable::Reader<arm>::Reader(p, path, 0, options, 0);
-#if LTO_SUPPORT
-       if ( lto::Reader::validFile(p, stat_buf.st_size, 0) ) {
-               return new lto::Reader(p, stat_buf.st_size, path, 0, options, 0);
+
+       mach_o::relocatable::ParserOptions objOpts;
+       objOpts.architecture            = sPreferredArch;
+       objOpts.objSubtypeMustMatch = false;
+       objOpts.logAllFiles                     = false;
+       objOpts.warnUnwindConversionProblems    = true;
+       objOpts.keepDwarfUnwind         = false;
+       objOpts.forceDwarfConversion = false;
+       objOpts.verboseOptimizationHints = true;
+       objOpts.armUsesZeroCostExceptions = true;
+       objOpts.subType                         = sPreferredSubArch;
+       objOpts.treateBitcodeAsData  = false;
+       objOpts.usingBitcode            = true;
+#if 1
+       if ( ! foundFatSlice ) {
+               cpu_type_t archOfObj;
+               cpu_subtype_t subArchOfObj;
+               ld::Platform platform;
+               uint32_t minOS;
+               if ( mach_o::relocatable::isObjectFile(p, &archOfObj, &subArchOfObj, &platform, &minOS) ) {
+                       objOpts.architecture = archOfObj;
+                       objOpts.subType = subArchOfObj;
+               }
        }
-#endif
-       
+
+       ld::relocatable::File* objResult = mach_o::relocatable::parse(p, fileLen, path, stat_buf.st_mtime, ld::File::Ordinal::NullOrdinal(), objOpts);
+       if ( objResult != NULL )
+               return objResult;
+
+       // see if it is an llvm object file
+       objResult = lto::parse(p, fileLen, path, stat_buf.st_mtime, ld::File::Ordinal::NullOrdinal(), sPreferredArch, sPreferredSubArch, false, true);
+       if ( objResult != NULL ) 
+               return objResult;
+
        throwf("not a mach-o object file: %s", path);
+#else
+       // for peformance testing
+       for (int i=0; i < 500; ++i ) {
+               ld::relocatable::File* objResult = mach_o::relocatable::parse(p, fileLen, path, stat_buf.st_mtime, 0, objOpts);
+               delete objResult;
+       }
+       exit(0);
+#endif
 }
 
 static
@@ -439,6 +1294,9 @@ usage()
 {
        fprintf(stderr, "ObjectDump options:\n"
                        "\t-no_content\tdon't dump contents\n"
+                       "\t-no_section\tdon't dump section name\n"
+                       "\t-no_defintion\tdon't dump definition kind\n"
+                       "\t-no_combine\tdon't dump combine mode\n"
                        "\t-stabs\t\tdump stabs\n"
                        "\t-arch aaa\tonly dump info about arch aaa\n"
                        "\t-only sym\tonly dump info about sym\n"
@@ -454,8 +1312,6 @@ int main(int argc, const char* argv[])
                return 0;
        }
 
-       ObjectFile::ReaderOptions options;
-       options.fAddCompactUnwindEncoding = true;
        try {
                for(int i=1; i < argc; ++i) {
                        const char* arg = argv[i];
@@ -472,36 +1328,33 @@ int main(int argc, const char* argv[])
                                else if ( strcmp(arg, "-no_sort") == 0 ) {
                                        sSort = false;
                                }
+                               else if ( strcmp(arg, "-no_section") == 0 ) {
+                                       sShowSection = false;
+                               }
+                               else if ( strcmp(arg, "-no_definition") == 0 ) {
+                                       sShowDefinitionKind = false;
+                               }
+                               else if ( strcmp(arg, "-no_combine") == 0 ) {
+                                       sShowCombineKind = false;
+                               }
+                               else if ( strcmp(arg, "-no_line_info") == 0 ) {
+                                       sShowLineInfo = false;
+                               }
                                else if ( strcmp(arg, "-arch") == 0 ) {
-                                       const char* arch = ++i<argc? argv[i]: "";
-                                       if ( strcmp(arch, "ppc64") == 0 )
-                                               sPreferredArch = CPU_TYPE_POWERPC64;
-                                       else if ( strcmp(arch, "ppc") == 0 )
-                                               sPreferredArch = CPU_TYPE_POWERPC;
-                                       else if ( strcmp(arch, "i386") == 0 )
-                                               sPreferredArch = CPU_TYPE_I386;
-                                       else if ( strcmp(arch, "x86_64") == 0 )
-                                               sPreferredArch = CPU_TYPE_X86_64;
-                                       else if ( strcmp(arch, "arm") == 0 )
-                                               sPreferredArch = CPU_TYPE_ARM;
-                                       else if ( strcmp(arch, "armv4t") == 0 ) {
-                                               sPreferredArch = CPU_TYPE_ARM;
-                                               sPreferredSubArch = CPU_SUBTYPE_ARM_V4T;
-                                       }
-                                       else if ( strcmp(arch, "armv5") == 0 ) {
-                                               sPreferredArch = CPU_TYPE_ARM;
-                                               sPreferredSubArch = CPU_SUBTYPE_ARM_V5TEJ;
-                                       }
-                                       else if ( strcmp(arch, "armv6") == 0 ) {
-                                               sPreferredArch = CPU_TYPE_ARM;
-                                               sPreferredSubArch = CPU_SUBTYPE_ARM_V6;
-                                       }
-                                       else if ( strcmp(arch, "armv7") == 0 ) {
-                                               sPreferredArch = CPU_TYPE_ARM;
-                                               sPreferredSubArch = CPU_SUBTYPE_ARM_V7;
+                                       const char* archName = argv[++i];
+                                       if ( archName == NULL )
+                                               throw "-arch missing architecture name";
+                                       bool found = false;
+                                       for (const ArchInfo* t=archInfoArray; t->archName != NULL; ++t) {
+                                               if ( strcmp(t->archName,archName) == 0 ) {
+                                                       sPreferredArch = t->cpuType;
+                                                       if ( t->isSubType )
+                                                               sPreferredSubArch = t->cpuSubType;
+                                                       found = true;
+                                               }
                                        }
-                                       else 
-                                               throwf("unknown architecture %s", arch);
+                                       if ( !found )
+                                               throwf("unknown architecture %s", archName);
                                }
                                else if ( strcmp(arg, "-only") == 0 ) {
                                        sMatchName = ++i<argc? argv[i]: NULL;
@@ -520,7 +1373,7 @@ int main(int argc, const char* argv[])
                                }
                        }
                        else {
-                               ObjectFile::Reader* reader = createReader(arg, options);
+                               ld::relocatable::File* reader = createReader(arg);
                                dumpFile(reader);
                        }
                }