ld64-236.3.tar.gz
[apple/ld64.git] / src / other / dyldinfo.cpp
index 4ad006a7d7828a4c34232ee9ee8a3fd5edb49886..6ac33119a0240262fce67521747a6fca0b06d3b0 100644 (file)
@@ -33,8 +33,9 @@
 
 #include <vector>
 #include <set>
-#include <ext/hash_set>
+#include <unordered_set>
 
+#include "configure.h"
 #include "MachOFileAbstraction.hpp"
 #include "Architectures.hpp"
 #include "MachOTrie.hpp"
@@ -86,14 +87,6 @@ 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, bool printArch);
        void                                                                            printRebaseInfo();
        void                                                                            printRebaseInfoOpcodes();
@@ -259,6 +252,26 @@ bool DyldInfoPrinter<arm>::validFile(const uint8_t* fileContent)
 }
 #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, bool printArch)
  : fHeader(NULL), fLength(fileLength), 
@@ -619,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 = "??";
@@ -1271,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");
                }
        }
 }
@@ -1302,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);
@@ -1422,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);
                                }
@@ -1457,7 +1496,12 @@ 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";
@@ -1741,7 +1785,6 @@ x86::P::uint_t DyldInfoPrinter<x86>::relocBase()
 template <>
 x86_64::P::uint_t DyldInfoPrinter<x86_64>::relocBase()
 {
-       // check for split-seg
        return fFirstWritableSegment->vmaddr();
 }
 
@@ -1756,6 +1799,13 @@ arm::P::uint_t DyldInfoPrinter<arm>::relocBase()
 }
 #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)
@@ -1808,6 +1858,16 @@ const char*      DyldInfoPrinter<arm>::relocTypeName(uint8_t r_type)
 }
 #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()
 {
@@ -2104,6 +2164,14 @@ static void dump(const char* path)
                                                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);
@@ -2127,6 +2195,11 @@ static void dump(const char* path)
                else if ( DyldInfoPrinter<arm>::validFile(p) ) {
                        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";
@@ -2177,20 +2250,25 @@ int main(int argc, const char* argv[])
                                                sPreferredArch = CPU_TYPE_I386;
                                        else if ( strcmp(arch, "x86_64") == 0 )
                                                sPreferredArch = CPU_TYPE_X86_64;
+#if SUPPORT_ARCH_arm64
+                                       else if ( strcmp(arch, "arm64") == 0 )
+                                               sPreferredArch = CPU_TYPE_ARM64;
+#endif
                                        else {
-                                               const char* archName = argv[++i];
-                                               if ( archName == NULL )
+                                               if ( arch == NULL )
                                                        throw "-arch missing architecture name";
                                                bool found = false;
                                                for (const ArchInfo* t=archInfoArray; t->archName != NULL; ++t) {
-                                                       if ( strcmp(t->archName,archName) == 0 ) {
+                                                       if ( strcmp(t->archName,arch) == 0 ) {
                                                                sPreferredArch = t->cpuType;
                                                                if ( t->isSubType )
                                                                        sPreferredSubArch = t->cpuSubType;
+                                                               found = true;
+                                                               break;
                                                        }
                                                }
                                                if ( !found )
-                                                       throwf("unknown architecture %s", archName);
+                                                       throwf("unknown architecture %s", arch);
                                        }
                                }
                                else if ( strcmp(arg, "-rebase") == 0 ) {