]> git.saurik.com Git - apple/ld64.git/blobdiff - src/other/dyldinfo.cpp
ld64-236.3.tar.gz
[apple/ld64.git] / src / other / dyldinfo.cpp
index a6988ec2179c0be42375b73d13df7a02763facb9..6ac33119a0240262fce67521747a6fca0b06d3b0 100644 (file)
 
 #include <vector>
 #include <set>
-#include <ext/hash_set>
+#include <unordered_set>
 
+#include "configure.h"
 #include "MachOFileAbstraction.hpp"
 #include "Architectures.hpp"
 #include "MachOTrie.hpp"
+#include "../ld/code-sign-blobs/superblob.h"
 
 static bool printRebase = false;
 static bool printBind = false;
@@ -50,7 +52,9 @@ static bool printExportNodes = false;
 static bool printSharedRegion = false;
 static bool printFunctionStarts = false;
 static bool printDylibs = false;
-static cpu_type_t      sPreferredArch = CPU_TYPE_I386;
+static bool printDRs = false;
+static bool printDataCode = false;
+static cpu_type_t      sPreferredArch = 0;
 static cpu_type_t      sPreferredSubArch = 0;
 
 
@@ -73,8 +77,8 @@ class DyldInfoPrinter
 {
 public:
        static bool                                                                     validFile(const uint8_t* fileContent);
-       static DyldInfoPrinter<A>*                                      make(const uint8_t* fileContent, uint32_t fileLength, const char* path) 
-                                                                                                               { return new DyldInfoPrinter<A>(fileContent, fileLength, path); }
+       static DyldInfoPrinter<A>*                                      make(const uint8_t* fileContent, uint32_t fileLength, const char* path, bool printArch
+                                                                                                               { return new DyldInfoPrinter<A>(fileContent, fileLength, path, printArch); }
        virtual                                                                         ~DyldInfoPrinter() {}
 
 
@@ -83,15 +87,7 @@ private:
        typedef typename A::P::E                                E;
        typedef typename A::P::uint_t                   pint_t;
        
-       class CStringEquals
-       {
-       public:
-               bool operator()(const char* left, const char* right) const { return (strcmp(left, right) == 0); }
-       };
-
-       typedef __gnu_cxx::hash_set<const char*, __gnu_cxx::hash<const char*>, CStringEquals>  StringSet;
-
-                                                                                               DyldInfoPrinter(const uint8_t* fileContent, uint32_t fileLength, const char* path);
+                                                                                               DyldInfoPrinter(const uint8_t* fileContent, uint32_t fileLength, const char* path, bool printArch);
        void                                                                            printRebaseInfo();
        void                                                                            printRebaseInfoOpcodes();
        void                                                                            printBindingInfo();
@@ -110,6 +106,8 @@ private:
        void                                                                            printSharedRegionInfo();
        void                                                                            printFunctionStartsInfo();
        void                                                                            printDylibsInfo();
+       void                                                                            printDRInfo();
+       void                                                                            printDataInCode();
        void                                                                            printFunctionStartLine(uint64_t addr);
        const uint8_t*                                                          printSharedRegionInfoForEachULEB128Address(const uint8_t* p, uint8_t kind);
        pint_t                                                                          relocBase();
@@ -143,6 +141,8 @@ private:
        const macho_dyld_info_command<P>*                       fInfo;
        const macho_linkedit_data_command<P>*           fSharedRegionInfo;
        const macho_linkedit_data_command<P>*           fFunctionStartsInfo;
+       const macho_linkedit_data_command<P>*           fDataInCode;
+       const macho_linkedit_data_command<P>*           fDRInfo;
        uint64_t                                                                        fBaseAddress;
        const macho_dysymtab_command<P>*                        fDynamicSymbolTable;
        const macho_segment_command<P>*                         fFirstSegment;
@@ -166,6 +166,7 @@ bool DyldInfoPrinter<ppc>::validFile(const uint8_t* fileContent)
        switch (header->filetype()) {
                case MH_EXECUTE:
                case MH_DYLIB:
+               case MH_DYLIB_STUB:
                case MH_BUNDLE:
                case MH_DYLINKER:
                        return true;
@@ -184,6 +185,7 @@ bool DyldInfoPrinter<ppc64>::validFile(const uint8_t* fileContent)
        switch (header->filetype()) {
                case MH_EXECUTE:
                case MH_DYLIB:
+               case MH_DYLIB_STUB:
                case MH_BUNDLE:
                case MH_DYLINKER:
                        return true;
@@ -202,6 +204,7 @@ bool DyldInfoPrinter<x86>::validFile(const uint8_t* fileContent)
        switch (header->filetype()) {
                case MH_EXECUTE:
                case MH_DYLIB:
+               case MH_DYLIB_STUB:
                case MH_BUNDLE:
                case MH_DYLINKER:
                        return true;
@@ -220,6 +223,7 @@ bool DyldInfoPrinter<x86_64>::validFile(const uint8_t* fileContent)
        switch (header->filetype()) {
                case MH_EXECUTE:
                case MH_DYLIB:
+               case MH_DYLIB_STUB:
                case MH_BUNDLE:
                case MH_DYLINKER:
                        return true;
@@ -227,6 +231,7 @@ bool DyldInfoPrinter<x86_64>::validFile(const uint8_t* fileContent)
        return false;
 }
 
+#if SUPPORT_ARCH_arm_any
 template <>
 bool DyldInfoPrinter<arm>::validFile(const uint8_t* fileContent)
 {      
@@ -238,18 +243,40 @@ bool DyldInfoPrinter<arm>::validFile(const uint8_t* fileContent)
        switch (header->filetype()) {
                case MH_EXECUTE:
                case MH_DYLIB:
+               case MH_DYLIB_STUB:
                case MH_BUNDLE:
                case MH_DYLINKER:
                        return true;
        }
        return false;
 }
+#endif
+
+#if SUPPORT_ARCH_arm64
+template <>
+bool DyldInfoPrinter<arm64>::validFile(const uint8_t* fileContent)
+{      
+       const macho_header<P>* header = (const macho_header<P>*)fileContent;
+       if ( header->magic() != MH_MAGIC_64 )
+               return false;
+       if ( header->cputype() != CPU_TYPE_ARM64 )
+               return false;
+       switch (header->filetype()) {
+               case MH_EXECUTE:
+               case MH_DYLIB:
+               case MH_BUNDLE:
+               case MH_DYLINKER:
+                       return true;
+       }
+       return false;
+}
+#endif
 
 template <typename A>
-DyldInfoPrinter<A>::DyldInfoPrinter(const uint8_t* fileContent, uint32_t fileLength, const char* path)
+DyldInfoPrinter<A>::DyldInfoPrinter(const uint8_t* fileContent, uint32_t fileLength, const char* path, bool printArch)
  : fHeader(NULL), fLength(fileLength), 
    fStrings(NULL), fStringsEnd(NULL), fSymbols(NULL), fSymbolCount(0), fInfo(NULL), 
-   fSharedRegionInfo(NULL), fFunctionStartsInfo(NULL), 
+   fSharedRegionInfo(NULL), fFunctionStartsInfo(NULL), fDataInCode(NULL), fDRInfo(NULL), 
    fBaseAddress(0), fDynamicSymbolTable(NULL), fFirstSegment(NULL), fFirstWritableSegment(NULL),
    fWriteableSegmentWithAddrOver4G(false)
 {
@@ -332,10 +359,26 @@ DyldInfoPrinter<A>::DyldInfoPrinter(const uint8_t* fileContent, uint32_t fileLen
                        case LC_FUNCTION_STARTS:
                                fFunctionStartsInfo = (macho_linkedit_data_command<P>*)cmd;
                                break;
+                       case LC_DATA_IN_CODE:
+                               fDataInCode = (macho_linkedit_data_command<P>*)cmd;
+                               break;
+                       case LC_DYLIB_CODE_SIGN_DRS:
+                               fDRInfo = (macho_linkedit_data_command<P>*)cmd;
+                               break;
                }
                cmd = (const macho_load_command<P>*)endOfCmd;
        }
        
+       if ( printArch ) {
+               for (const ArchInfo* t=archInfoArray; t->archName != NULL; ++t) {
+                       if ( (cpu_type_t)fHeader->cputype() == t->cpuType ) {
+                               if ( t->isSubType && ((cpu_subtype_t)fHeader->cpusubtype() != t->cpuSubType) )
+                                       continue;
+                               printf("for arch %s:\n", t->archName);
+                       }
+               }
+       }
+       
        if ( printRebase ) {
                if ( fInfo != NULL )
                        printRebaseInfo();
@@ -378,6 +421,10 @@ DyldInfoPrinter<A>::DyldInfoPrinter(const uint8_t* fileContent, uint32_t fileLen
                printFunctionStartsInfo();
        if ( printDylibs )
                printDylibsInfo();
+       if ( printDRs )
+               printDRInfo();
+       if ( printDataCode )
+               printDataInCode();
 }
 
 static uint64_t read_uleb128(const uint8_t*& p, const uint8_t* end)
@@ -410,7 +457,7 @@ static int64_t read_sleb128(const uint8_t*& p, const uint8_t* end)
                if (p == end)
                        throwf("malformed sleb128");
                byte = *p++;
-               result |= ((byte & 0x7f) << bit);
+               result |= (((int64_t)(byte & 0x7f)) << bit);
                bit += 7;
        } while (byte & 0x80);
        // sign extend negative numbers
@@ -585,7 +632,7 @@ void DyldInfoPrinter<A>::printRebaseInfo()
                uint64_t segOffset = 0;
                uint32_t count;
                uint32_t skip;
-               int segIndex;
+               int segIndex = 0;
                pint_t segStartAddr = 0;
                const char* segName = "??";
                const char* typeName = "??";
@@ -1237,26 +1284,50 @@ void DyldInfoPrinter<A>::printExportInfo()
                parseTrie(start, end, list);
                //std::sort(list.begin(), list.end(), SortExportsByAddress());
                for (std::vector<mach_o::trie::Entry>::iterator it=list.begin(); it != list.end(); ++it) {
-                       if ( it->flags & EXPORT_SYMBOL_FLAGS_REEXPORT ) {
-                               if ( it->importName[0] == '\0' )
-                                       fprintf(stdout, "[re-export] %s from dylib=%llu\n", it->name, it->other);
-                               else
-                                       fprintf(stdout, "[re-export] %s from dylib=%llu named=%s\n", it->name, it->other, it->importName);
-                       }
-                       else {
-                               const char* flags = "";
-                               if ( it->flags & EXPORT_SYMBOL_FLAGS_WEAK_DEFINITION )
-                                       flags = "[weak_def] ";
-                               else if ( (it->flags & EXPORT_SYMBOL_FLAGS_KIND_MASK) == EXPORT_SYMBOL_FLAGS_KIND_THREAD_LOCAL )
-                                       flags = "[per-thread] ";
-                               if ( it->flags & EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER ) {
-                                       flags = "[resolver] ";
-                                       fprintf(stdout, "0x%08llX  %s%s (resolver=0x%08llX)\n", fBaseAddress+it->address, flags, it->name, it->other);
+                       const bool reExport = (it->flags & EXPORT_SYMBOL_FLAGS_REEXPORT);
+                       const bool weakDef = (it->flags & EXPORT_SYMBOL_FLAGS_WEAK_DEFINITION);
+                       const bool threadLocal = ((it->flags & EXPORT_SYMBOL_FLAGS_KIND_MASK) == EXPORT_SYMBOL_FLAGS_KIND_THREAD_LOCAL);
+                       const bool abs = ((it->flags & EXPORT_SYMBOL_FLAGS_KIND_MASK) == EXPORT_SYMBOL_FLAGS_KIND_ABSOLUTE);
+                       const bool resolver = (it->flags & EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER);
+                       if ( reExport )
+                               printf("[re-export] ");
+                       else
+                               printf("0x%08llX  ", fBaseAddress+it->address);
+                       printf("%s", it->name);
+                       if ( weakDef || threadLocal || resolver || abs ) {
+                               bool needComma = false;
+                               printf(" [");
+                               if ( weakDef ) {
+                                       printf("weak_def");
+                                       needComma = true;
                                }
-                               else {
-                                       fprintf(stdout, "0x%08llX  %s%s\n", fBaseAddress+it->address, flags, it->name);
+                               if ( threadLocal ) {
+                                       if ( needComma ) 
+                                               printf(", ");
+                                       printf("per-thread");
+                                       needComma = true;
+                               }
+                               if ( abs ) {
+                                       if ( needComma )
+                                               printf(", ");
+                                       printf("absolute");
+                                       needComma = true;
                                }
+                               if ( resolver ) {
+                                       if ( needComma ) 
+                                               printf(", ");
+                                       printf("resolver=0x%08llX", it->other);
+                                       needComma = true;
+                               }
+                               printf("]");
+                       }
+                       if ( reExport ) {
+                               if ( it->importName[0] == '\0' )
+                                       printf(" (from %s)", fDylibs[it->other - 1]);
+                               else
+                                       printf(" (%s from %s)", it->importName, fDylibs[it->other - 1]);
                        }
+                       printf("\n");
                }
        }
 }
@@ -1268,7 +1339,7 @@ void DyldInfoPrinter<A>::processExportGraphNode(const uint8_t* const start, cons
                                                                                        char* cummulativeString, int curStrOffset) 
 {
        const uint8_t* const me = p;
-       const uint8_t terminalSize = read_uleb128(p, end);
+       const uint64_t terminalSize = read_uleb128(p, end);
        const uint8_t* children = p + terminalSize;
        if ( terminalSize != 0 ) {
                uint32_t flags = read_uleb128(p, end);
@@ -1388,6 +1459,8 @@ void DyldInfoPrinter<A>::printExportInfoNodes()
                                                printf("[addr=0x%06llX] ", address);
                                        else if ( (flags & EXPORT_SYMBOL_FLAGS_KIND_MASK) == EXPORT_SYMBOL_FLAGS_KIND_THREAD_LOCAL)
                                                printf("[flags=THREAD_LOCAL addr=0x%06llX] ", address);
+                                       else if ( (flags & EXPORT_SYMBOL_FLAGS_KIND_MASK) == EXPORT_SYMBOL_FLAGS_KIND_ABSOLUTE)
+                                               printf("[flags=ABSOLUTE addr=0x%06llX] ", address);
                                        else
                                                printf("[flags=0x%llX addr=0x%06llX] ", flags, address);
                                }
@@ -1423,11 +1496,70 @@ const uint8_t* DyldInfoPrinter<A>::printSharedRegionInfoForEachULEB128Address(co
                        kindStr = "64-bit pointer";
                        break;
                case 3:
-                       kindStr = "ppc hi16";
+#if SUPPORT_ARCH_arm64
+                       if ( fHeader->cputype() == CPU_TYPE_ARM64 )
+                               kindStr = "arm64 ADRP";
+                       else
+#endif
+                               kindStr = "ppc hi16";
                        break;
                case 4:
                        kindStr = "32-bit offset to IMPORT";
                        break;
+               case 5:
+                       kindStr = "thumb2 movw";
+                       break;
+               case 6:
+                       kindStr = "ARM movw";
+                       break;
+               case 0x10:
+                       kindStr = "thumb2 movt low high 4 bits=0";
+                       break;
+               case 0x11:
+                       kindStr = "thumb2 movt low high 4 bits=1";
+                       break;
+               case 0x12:
+                       kindStr = "thumb2 movt low high 4 bits=2";
+                       break;
+               case 0x13:
+                       kindStr = "thumb2 movt low high 4 bits=3";
+                       break;
+               case 0x14:
+                       kindStr = "thumb2 movt low high 4 bits=4";
+                       break;
+               case 0x15:
+                       kindStr = "thumb2 movt low high 4 bits=5";
+                       break;
+               case 0x16:
+                       kindStr = "thumb2 movt low high 4 bits=6";
+                       break;
+               case 0x17:
+                       kindStr = "thumb2 movt low high 4 bits=7";
+                       break;
+               case 0x18:
+                       kindStr = "thumb2 movt low high 4 bits=8";
+                       break;
+               case 0x19:
+                       kindStr = "thumb2 movt low high 4 bits=9";
+                       break;
+               case 0x1A:
+                       kindStr = "thumb2 movt low high 4 bits=0xA";
+                       break;
+               case 0x1B:
+                       kindStr = "thumb2 movt low high 4 bits=0xB";
+                       break;
+               case 0x1C:
+                       kindStr = "thumb2 movt low high 4 bits=0xC";
+                       break;
+               case 0x1D:
+                       kindStr = "thumb2 movt low high 4 bits=0xD";
+                       break;
+               case 0x1E:
+                       kindStr = "thumb2 movt low high 4 bits=0xE";
+                       break;
+               case 0x1F:
+                       kindStr = "thumb2 movt low high 4 bits=0xF";
+                       break;
        }
        uint64_t address = 0;
        uint64_t delta = 0;
@@ -1469,6 +1601,7 @@ void DyldInfoPrinter<A>::printSharedRegionInfo()
        }
 }
 
+#if SUPPORT_ARCH_arm_any
 template <>
 void DyldInfoPrinter<arm>::printFunctionStartLine(uint64_t addr)
 {
@@ -1477,6 +1610,7 @@ void DyldInfoPrinter<arm>::printFunctionStartLine(uint64_t addr)
        else
                printf("0x%0llX         %s\n", addr, symbolNameForAddress(addr)); 
 }
+#endif
 
 template <typename A>
 void DyldInfoPrinter<A>::printFunctionStartLine(uint64_t addr)
@@ -1541,6 +1675,85 @@ void DyldInfoPrinter<A>::printDylibsInfo()
        }
 }
 
+template <typename A>
+void DyldInfoPrinter<A>::printDRInfo()
+{
+       if ( fDRInfo == NULL ) {
+               printf("no Designated Requirements info\n");
+       }
+       else {
+               printf("dylibs                 DRs\n");
+               const uint8_t* start = ((uint8_t*)fHeader + fDRInfo->dataoff());
+               //const uint8_t* end   = ((uint8_t*)fHeader + fDRInfo->dataoff() + fDRInfo->datasize());
+               typedef Security::SuperBlob<Security::kSecCodeMagicDRList> DRListSuperBlob;
+               typedef Security::SuperBlob<Security::kSecCodeMagicRequirementSet> InternalRequirementsSetBlob;
+               const DRListSuperBlob* topBlob = (DRListSuperBlob*)start;
+               if ( topBlob->validateBlob(fDRInfo->datasize()) ) {
+                       if ( topBlob->count() == fDylibLoadCommands.size() ) {
+                               for(unsigned i=0; i < topBlob->count(); ++i) {
+                                       printf(" %-20s   ", fDylibs[i]);
+                                       const Security::BlobCore* item = topBlob->find(i);
+                                       if ( item != NULL ) {
+                                               const uint8_t* itemStart = (uint8_t*)item;
+                                               const uint8_t* itemEnd = itemStart + item->length();
+                                               for(const uint8_t* p=itemStart; p < itemEnd; ++p)
+                                                       printf("%02X ", *p);
+                                       }
+                                       else {
+                                               printf("no DR info");
+                                       }
+                                       printf("\n");
+                               }
+                       }
+                       else {
+                               fprintf(stderr, "superblob of DRs has a different number of elements than dylib load commands\n");
+                       }
+               }
+               else {
+                       fprintf(stderr, "superblob of DRs invalid\n");
+               }
+       }
+}
+
+
+
+
+
+template <typename A>
+void DyldInfoPrinter<A>::printDataInCode()
+{
+       if ( fDataInCode == NULL ) {
+               printf("no data-in-code info\n");
+       }
+       else {
+               printf("offset      length  data-kind\n");
+               const macho_data_in_code_entry<P>* start = (macho_data_in_code_entry<P>*)((uint8_t*)fHeader + fDataInCode->dataoff());
+               const macho_data_in_code_entry<P>* end = (macho_data_in_code_entry<P>*)((uint8_t*)fHeader + fDataInCode->dataoff() + fDataInCode->datasize());
+               for (const macho_data_in_code_entry<P>* p=start; p < end; ++p) {
+                       const char* kindStr = "???";
+                       switch ( p->kind() ) {
+                               case 1:
+                                       kindStr = "data";
+                                       break;
+                               case 2:
+                                       kindStr = "jumptable8";
+                                       break;
+                               case 3:
+                                       kindStr = "jumptable16";
+                                       break;
+                               case 4:
+                                       kindStr = "jumptable32";
+                                       break;
+                               case 5:
+                                       kindStr = "jumptable32absolute";
+                                       break;
+                       }
+                       printf("0x%08X  0x%04X  %s\n", p->offset(), p->length(), kindStr);
+               }
+       }
+}
+
+
 
 template <>
 ppc::P::uint_t DyldInfoPrinter<ppc>::relocBase()
@@ -1572,10 +1785,10 @@ x86::P::uint_t DyldInfoPrinter<x86>::relocBase()
 template <>
 x86_64::P::uint_t DyldInfoPrinter<x86_64>::relocBase()
 {
-       // check for split-seg
        return fFirstWritableSegment->vmaddr();
 }
 
+#if SUPPORT_ARCH_arm_any
 template <>
 arm::P::uint_t DyldInfoPrinter<arm>::relocBase()
 {
@@ -1584,15 +1797,21 @@ arm::P::uint_t DyldInfoPrinter<arm>::relocBase()
        else
                return fFirstSegment->vmaddr();
 }
+#endif
 
+#if SUPPORT_ARCH_arm64
+template <>
+arm64::P::uint_t DyldInfoPrinter<arm64>::relocBase()
+{
+       return fFirstWritableSegment->vmaddr();
+}
+#endif
 
 template <>
 const char*    DyldInfoPrinter<ppc>::relocTypeName(uint8_t r_type)
 {
        if ( r_type == GENERIC_RELOC_VANILLA )
                return "pointer";
-       else if ( r_type == PPC_RELOC_PB_LA_PTR )
-               return "pb pointer";
        else
                return "??";
 }
@@ -1626,6 +1845,7 @@ const char*       DyldInfoPrinter<x86_64>::relocTypeName(uint8_t r_type)
                return "??";
 }
        
+#if SUPPORT_ARCH_arm_any
 template <>
 const char*    DyldInfoPrinter<arm>::relocTypeName(uint8_t r_type)
 {
@@ -1636,7 +1856,17 @@ const char*      DyldInfoPrinter<arm>::relocTypeName(uint8_t r_type)
        else
                return "??";
 }
-       
+#endif
+
+#if SUPPORT_ARCH_arm64 
+template <>
+const char*    DyldInfoPrinter<arm64>::relocTypeName(uint8_t r_type)
+{
+       if ( r_type == ARM64_RELOC_UNSIGNED )
+               return "pointer";
+       return "??";
+}
+#endif
 
 template <typename A>
 void DyldInfoPrinter<A>::printRelocRebaseInfo()
@@ -1723,22 +1953,32 @@ void DyldInfoPrinter<A>::printSymbolTableExportInfo()
 template <typename A>
 const char* DyldInfoPrinter<A>::symbolNameForAddress(uint64_t addr)
 {
-       // find exact match in globals
-       const macho_nlist<P>* lastExport = &fSymbols[fDynamicSymbolTable->iextdefsym()+fDynamicSymbolTable->nextdefsym()];
-       for (const macho_nlist<P>* sym = &fSymbols[fDynamicSymbolTable->iextdefsym()]; sym < lastExport; ++sym) {
-               if ( (sym->n_value() == addr) && ((sym->n_type() & N_TYPE) == N_SECT) && ((sym->n_type() & N_STAB) == 0) ) {
-                       return &fStrings[sym->n_strx()];
+       if ( fDynamicSymbolTable != NULL ) {
+               // find exact match in globals
+               const macho_nlist<P>* lastExport = &fSymbols[fDynamicSymbolTable->iextdefsym()+fDynamicSymbolTable->nextdefsym()];
+               for (const macho_nlist<P>* sym = &fSymbols[fDynamicSymbolTable->iextdefsym()]; sym < lastExport; ++sym) {
+                       if ( (sym->n_value() == addr) && ((sym->n_type() & N_TYPE) == N_SECT) && ((sym->n_type() & N_STAB) == 0) ) {
+                               return &fStrings[sym->n_strx()];
+                       }
+               }
+               // find exact match in local symbols
+               const macho_nlist<P>* lastLocal = &fSymbols[fDynamicSymbolTable->ilocalsym()+fDynamicSymbolTable->nlocalsym()];
+               for (const macho_nlist<P>* sym = &fSymbols[fDynamicSymbolTable->ilocalsym()]; sym < lastLocal; ++sym) {
+                       if ( (sym->n_value() == addr) && ((sym->n_type() & N_TYPE) == N_SECT) && ((sym->n_type() & N_STAB) == 0) ) {
+                               return &fStrings[sym->n_strx()];
+                       }
                }
        }
-       // find exact match in local symbols
-       const macho_nlist<P>* lastLocal = &fSymbols[fDynamicSymbolTable->ilocalsym()+fDynamicSymbolTable->nlocalsym()];
-       for (const macho_nlist<P>* sym = &fSymbols[fDynamicSymbolTable->ilocalsym()]; sym < lastLocal; ++sym) {
-               if ( (sym->n_value() == addr) && ((sym->n_type() & N_TYPE) == N_SECT) && ((sym->n_type() & N_STAB) == 0) ) {
-                       return &fStrings[sym->n_strx()];
+       else {
+               // find exact match in all symbols
+               const macho_nlist<P>* lastSym = &fSymbols[fSymbolCount];
+               for (const macho_nlist<P>* sym = &fSymbols[0]; sym < lastSym; ++sym) {
+                       if ( (sym->n_value() == addr) && ((sym->n_type() & N_TYPE) == N_SECT) && ((sym->n_type() & N_STAB) == 0) ) {
+                               return &fStrings[sym->n_strx()];
+                       }
                }
        }
 
-
        return "?";
 }
  
@@ -1889,39 +2129,50 @@ static void dump(const char* path)
                                size_t size = OSSwapBigToHostInt32(archs[i].size);
                                cpu_type_t cputype = OSSwapBigToHostInt32(archs[i].cputype);
                                cpu_type_t cpusubtype = OSSwapBigToHostInt32(archs[i].cpusubtype);
-                               if ( (cputype == sPreferredArch) 
-                                       && ((sPreferredSubArch==0) || (sPreferredSubArch==cpusubtype)) ) {      
+                               if ( ((cputype == sPreferredArch) 
+                                       && ((sPreferredSubArch==0) || (sPreferredSubArch==cpusubtype)))
+                                       || (sPreferredArch == 0) ) {    
                                        switch(cputype) {
                                        case CPU_TYPE_POWERPC:
                                                if ( DyldInfoPrinter<ppc>::validFile(p + offset) )
-                                                       DyldInfoPrinter<ppc>::make(p + offset, size, path);
+                                                       DyldInfoPrinter<ppc>::make(p + offset, size, path, (sPreferredArch == 0));
                                                else
                                                        throw "in universal file, ppc slice does not contain ppc mach-o";
                                                break;
                                        case CPU_TYPE_I386:
                                                if ( DyldInfoPrinter<x86>::validFile(p + offset) )
-                                                       DyldInfoPrinter<x86>::make(p + offset, size, path);
+                                                       DyldInfoPrinter<x86>::make(p + offset, size, path, (sPreferredArch == 0));
                                                else
                                                        throw "in universal file, i386 slice does not contain i386 mach-o";
                                                break;
                                        case CPU_TYPE_POWERPC64:
                                                if ( DyldInfoPrinter<ppc64>::validFile(p + offset) )
-                                                       DyldInfoPrinter<ppc64>::make(p + offset, size, path);
+                                                       DyldInfoPrinter<ppc64>::make(p + offset, size, path, (sPreferredArch == 0));
                                                else
                                                        throw "in universal file, ppc64 slice does not contain ppc64 mach-o";
                                                break;
                                        case CPU_TYPE_X86_64:
                                                if ( DyldInfoPrinter<x86_64>::validFile(p + offset) )
-                                                       DyldInfoPrinter<x86_64>::make(p + offset, size, path);
+                                                       DyldInfoPrinter<x86_64>::make(p + offset, size, path, (sPreferredArch == 0));
                                                else
                                                        throw "in universal file, x86_64 slice does not contain x86_64 mach-o";
                                                break;
+#if SUPPORT_ARCH_arm_any
                                        case CPU_TYPE_ARM:
-                                               if ( DyldInfoPrinter<arm>::validFile(p + offset) )
-                                                       DyldInfoPrinter<arm>::make(p + offset, size, path);
+                                               if ( DyldInfoPrinter<arm>::validFile(p + offset) ) 
+                                                       DyldInfoPrinter<arm>::make(p + offset, size, path, (sPreferredArch == 0));
                                                else
                                                        throw "in universal file, arm slice does not contain arm mach-o";
                                                break;
+#endif
+#if SUPPORT_ARCH_arm64
+                                       case CPU_TYPE_ARM64:
+                                               if ( DyldInfoPrinter<arm64>::validFile(p + offset) )
+                                                       DyldInfoPrinter<arm64>::make(p + offset, size, path, (sPreferredArch == 0));
+                                               else
+                                                       throw "in universal file, arm64 slice does not contain arm mach-o";
+                                               break;
+#endif
                                        default:
                                                        throwf("in universal file, unknown architecture slice 0x%x\n", cputype);
                                        }
@@ -1929,20 +2180,27 @@ static void dump(const char* path)
                        }
                }
                else if ( DyldInfoPrinter<x86>::validFile(p) ) {
-                       DyldInfoPrinter<x86>::make(p, length, path);
+                       DyldInfoPrinter<x86>::make(p, length, path, false);
                }
                else if ( DyldInfoPrinter<ppc>::validFile(p) ) {
-                       DyldInfoPrinter<ppc>::make(p, length, path);
+                       DyldInfoPrinter<ppc>::make(p, length, path, false);
                }
                else if ( DyldInfoPrinter<ppc64>::validFile(p) ) {
-                       DyldInfoPrinter<ppc64>::make(p, length, path);
+                       DyldInfoPrinter<ppc64>::make(p, length, path, false);
                }
                else if ( DyldInfoPrinter<x86_64>::validFile(p) ) {
-                       DyldInfoPrinter<x86_64>::make(p, length, path);
+                       DyldInfoPrinter<x86_64>::make(p, length, path, false);
                }
+#if SUPPORT_ARCH_arm_any
                else if ( DyldInfoPrinter<arm>::validFile(p) ) {
-                       DyldInfoPrinter<arm>::make(p, length, path);
+                       DyldInfoPrinter<arm>::make(p, length, path, false);
+               }
+#endif
+#if SUPPORT_ARCH_arm64
+               else if ( DyldInfoPrinter<arm64>::validFile(p) ) {
+                       DyldInfoPrinter<arm64>::make(p, length, path, false);
                }
+#endif
                else {
                        throw "not a known file type";
                }
@@ -1956,6 +2214,7 @@ static void usage()
 {
        fprintf(stderr, "Usage: dyldinfo [-arch <arch>] <options> <mach-o file>\n"
                        "\t-dylibs           print dependent dylibs\n"
+                       "\t-dr               print dependent dylibs and show any recorded DR info\n"
                        "\t-rebase           print addresses dyld will adjust if file not loaded at preferred address\n"
                        "\t-bind             print addresses dyld will set based on symbolic lookups\n"
                        "\t-weak_bind        print symbols which dyld must coalesce\n"
@@ -1964,6 +2223,7 @@ static void usage()
                        "\t-opcodes          print opcodes used to generate the rebase and binding information\n"
                        "\t-function_starts  print table of function start addresses\n"
                        "\t-export_dot       print a GraphViz .dot file of the exported symbols trie\n"
+                       "\t-data_in_code     print any data-in-code inforamtion\n"
                );
 }
 
@@ -1990,26 +2250,26 @@ int main(int argc, const char* argv[])
                                                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;
+#if SUPPORT_ARCH_arm64
+                                       else if ( strcmp(arch, "arm64") == 0 )
+                                               sPreferredArch = CPU_TYPE_ARM64;
+#endif
+                                       else {
+                                               if ( arch == NULL )
+                                                       throw "-arch missing architecture name";
+                                               bool found = false;
+                                               for (const ArchInfo* t=archInfoArray; t->archName != NULL; ++t) {
+                                                       if ( strcmp(t->archName,arch) == 0 ) {
+                                                               sPreferredArch = t->cpuType;
+                                                               if ( t->isSubType )
+                                                                       sPreferredSubArch = t->cpuSubType;
+                                                               found = true;
+                                                               break;
+                                                       }
+                                               }
+                                               if ( !found )
+                                                       throwf("unknown architecture %s", arch);
                                        }
-                                       else 
-                                               throwf("unknown architecture %s", arch);
                                }
                                else if ( strcmp(arg, "-rebase") == 0 ) {
                                        printRebase = true;
@@ -2044,6 +2304,12 @@ int main(int argc, const char* argv[])
                                else if ( strcmp(arg, "-dylibs") == 0 ) {
                                        printDylibs = true;
                                }
+                               else if ( strcmp(arg, "-dr") == 0 ) {
+                                       printDRs = true;
+                               }
+                               else if ( strcmp(arg, "-data_in_code") == 0 ) {
+                                       printDataCode = true;
+                               }
                                else {
                                        throwf("unknown option: %s\n", arg);
                                }