]> git.saurik.com Git - apple/ld64.git/blobdiff - src/other/ObjectDump.cpp
ld64-123.2.tar.gz
[apple/ld64.git] / src / other / ObjectDump.cpp
index c2ae578be739c6a5830d07cc37c74793ce81d1e6..abf716213f3b816b6376c5299aae1fa89b6ecbc5 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
-
-#if LTO_SUPPORT
-       #include "LTOReader.hpp"
-#endif
+#include "MachOFileAbstraction.hpp"
+#include "parsers/macho_relocatable_file.h"
+#include "parsers/lto_file.h"
 
 static bool                    sDumpContent= true;
 static bool                    sDumpStabs      = false;
 static bool                    sSort           = true;
 static bool                    sNMmode         = false;
-static cpu_type_t      sPreferredArch = CPU_TYPE_POWERPC64;
-static const char* sMatchName;
+static bool                    sShowSection                    = true;
+static bool                    sShowDefinitionKind             = true;
+static bool                    sShowCombineKind                = true;
+
+static cpu_type_t              sPreferredArch = CPU_TYPE_I386;
+static cpu_subtype_t   sPreferredSubArch = 0xFFFFFFFF;
+static const char* sMatchName = NULL;
 static int sPrintRestrict;
 static int sPrintAlign;
 static int sPrintName;
 
-
  __attribute__((noreturn))
 void throwf(const char* format, ...) 
 {
@@ -70,12 +73,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:
@@ -163,24 +166,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:
@@ -189,17 +192,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:
@@ -207,31 +210,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:
@@ -240,23 +243,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:
@@ -264,16 +267,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");
@@ -281,20 +282,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)
@@ -316,12 +317,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();
@@ -332,13 +333,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);
                        }
                }
@@ -347,31 +347,711 @@ 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();
+                               }
+                       }
+                       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::kindStorePPCBranch24:
+                       printf(", then store as PPC branch24");
+                       break;
+               case ld::Fixup::kindStorePPCBranch14:
+                       printf(", then store as PPC branch14");
+                       break;
+               case ld::Fixup::kindStorePPCPicLow14:
+                       printf(", then store as PPC low14 pic");
+                       break;
+               case ld::Fixup::kindStorePPCPicLow16:
+                       printf(", then store as PPC low14 pic");
+                       break;
+               case ld::Fixup::kindStorePPCPicHigh16AddLow:
+                       printf(", then store as PPC high16 pic");
+                       break;
+               case ld::Fixup::kindStorePPCAbsLow14:
+                       printf(", then store as PPC low14 abs");
+                       break;
+               case ld::Fixup::kindStorePPCAbsLow16:
+                       printf(", then store as PPC low14 abs");
+                       break;
+               case ld::Fixup::kindStorePPCAbsHigh16AddLow:
+                       printf(", then store as PPC high16 abs");
+                       break;
+               case ld::Fixup::kindStorePPCAbsHigh16:
+                       printf(", then store as PPC high16 abs, no carry");
+                       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;
+               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::kindStorePPCDtraceCallSiteNop:
+                       printf("ppc dtrace static probe site");
+                       break;
+               case ld::Fixup::kindStorePPCDtraceIsEnableSiteClear:
+                       printf("ppc 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;
+               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::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::kindStoreTargetAddressPPCBranch24:
+                       printf("PowerPC store 24-bit pc-rel load of %s", referenceTargetAtomName(ref));
+                       break;
+               case ld::Fixup::kindSetTargetTLVTemplateOffset:
+               case ld::Fixup::kindSetTargetTLVTemplateOffsetLittleEndian32:
+               case ld::Fixup::kindSetTargetTLVTemplateOffsetLittleEndian64:
+                       printf("tlv template offset of %s", referenceTargetAtomName(ref));
+               //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() ) {
+               printf("unwind:   0x%08X\n", atom.beginUnwind()->unwindInfo);
+       }
+       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 ( 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();
        
@@ -386,10 +1066,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;
        
@@ -399,34 +1080,61 @@ 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 ) {
-                               p = p + OSSwapBigToHostInt32(archs[i].offset);
-                               mh = (struct mach_header*)p;
+                               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.convertUnwindInfo       = true;
+       objOpts.subType                         = sPreferredSubArch;
+#if 1
+       if ( ! foundFatSlice ) {
+               cpu_type_t archOfObj;
+               cpu_subtype_t subArchOfObj;
+               if ( mach_o::relocatable::isObjectFile(p, &archOfObj, &subArchOfObj) ) {
+                       objOpts.architecture = archOfObj;
+                       objOpts.subType = subArchOfObj;
+               }
        }
-#endif
-       
+
+       ld::relocatable::File* objResult = mach_o::relocatable::parse(p, fileLen, path, stat_buf.st_mtime, 0, objOpts);
+       if ( objResult != NULL )
+               return objResult;
+
+       // see if it is an llvm object file
+       objResult = lto::parse(p, fileLen, path, stat_buf.st_mtime, 0, sPreferredArch, sPreferredSubArch, false);
+       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
@@ -435,6 +1143,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"
@@ -450,8 +1161,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];
@@ -468,6 +1177,15 @@ 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, "-arch") == 0 ) {
                                        const char* arch = ++i<argc? argv[i]: "";
                                        if ( strcmp(arch, "ppc64") == 0 )
@@ -480,8 +1198,22 @@ int main(int argc, const char* argv[])
                                                sPreferredArch = CPU_TYPE_X86_64;
                                        else if ( strcmp(arch, "arm") == 0 )
                                                sPreferredArch = CPU_TYPE_ARM;
-                                       else if ( strcmp(arch, "armv6") == 0 )
+                                       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;
+                                       }
                                        else 
                                                throwf("unknown architecture %s", arch);
                                }
@@ -502,7 +1234,7 @@ int main(int argc, const char* argv[])
                                }
                        }
                        else {
-                               ObjectFile::Reader* reader = createReader(arg, options);
+                               ld::relocatable::File* reader = createReader(arg);
                                dumpFile(reader);
                        }
                }