Home | History | Annotate | Download | only in AppleObjCRuntime
      1 //===-- AppleObjCRuntimeV2.cpp --------------------------------------*- C++ -*-===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 
     10 #include "lldb/lldb-python.h"
     11 
     12 #include <string>
     13 #include <vector>
     14 #include <stdint.h>
     15 
     16 #include "lldb/lldb-enumerations.h"
     17 #include "lldb/Core/ClangForward.h"
     18 #include "lldb/Symbol/ClangASTType.h"
     19 
     20 #include "lldb/Core/ClangForward.h"
     21 #include "lldb/Core/ConstString.h"
     22 #include "lldb/Core/Error.h"
     23 #include "lldb/Core/Log.h"
     24 #include "lldb/Core/Module.h"
     25 #include "lldb/Core/PluginManager.h"
     26 #include "lldb/Core/Scalar.h"
     27 #include "lldb/Core/Section.h"
     28 #include "lldb/Core/StreamString.h"
     29 #include "lldb/Core/Timer.h"
     30 #include "lldb/Core/ValueObjectVariable.h"
     31 #include "lldb/Expression/ClangFunction.h"
     32 #include "lldb/Expression/ClangUtilityFunction.h"
     33 #include "lldb/Symbol/ClangASTContext.h"
     34 #include "lldb/Symbol/ObjectFile.h"
     35 #include "lldb/Symbol/Symbol.h"
     36 #include "lldb/Symbol/TypeList.h"
     37 #include "lldb/Symbol/VariableList.h"
     38 #include "lldb/Target/ExecutionContext.h"
     39 #include "lldb/Target/Process.h"
     40 #include "lldb/Target/RegisterContext.h"
     41 #include "lldb/Target/Target.h"
     42 #include "lldb/Target/Thread.h"
     43 
     44 #include "AppleObjCRuntimeV2.h"
     45 #include "AppleObjCTypeVendor.h"
     46 #include "AppleObjCTrampolineHandler.h"
     47 
     48 #include <vector>
     49 
     50 using namespace lldb;
     51 using namespace lldb_private;
     52 
     53 // 2 second timeout when running utility functions
     54 #define UTILITY_FUNCTION_TIMEOUT_USEC 2*1000*1000
     55 
     56 static const char *g_get_dynamic_class_info_name = "__lldb_apple_objc_v2_get_dynamic_class_info";
     57 // Testing using the new C++11 raw string literals. If this breaks GCC then we will
     58 // need to revert to the code above...
     59 static const char *g_get_dynamic_class_info_body = R"(
     60 
     61 extern "C"
     62 {
     63     size_t strlen(const char *);
     64     char *strncpy (char * s1, const char * s2, size_t n);
     65     int printf(const char * format, ...);
     66 }
     67 //#define ENABLE_DEBUG_PRINTF // COMMENT THIS LINE OUT PRIOR TO CHECKIN
     68 #ifdef ENABLE_DEBUG_PRINTF
     69 #define DEBUG_PRINTF(fmt, ...) printf(fmt, ## __VA_ARGS__)
     70 #else
     71 #define DEBUG_PRINTF(fmt, ...)
     72 #endif
     73 
     74 typedef struct _NXMapTable {
     75     void *prototype;
     76     unsigned num_classes;
     77     unsigned num_buckets_minus_one;
     78     void *buckets;
     79 } NXMapTable;
     80 
     81 #define NX_MAPNOTAKEY   ((void *)(-1))
     82 
     83 typedef struct BucketInfo
     84 {
     85     const char *name_ptr;
     86     Class isa;
     87 } BucketInfo;
     88 
     89 struct ClassInfo
     90 {
     91     Class isa;
     92     uint32_t hash;
     93 } __attribute__((__packed__));
     94 
     95 uint32_t
     96 __lldb_apple_objc_v2_get_dynamic_class_info (void *gdb_objc_realized_classes_ptr,
     97                                              void *class_infos_ptr,
     98                                              uint32_t class_infos_byte_size)
     99 {
    100     DEBUG_PRINTF ("gdb_objc_realized_classes_ptr = %p\n", gdb_objc_realized_classes_ptr);
    101     DEBUG_PRINTF ("class_infos_ptr = %p\n", class_infos_ptr);
    102     DEBUG_PRINTF ("class_infos_byte_size = %u\n", class_infos_byte_size);
    103     const NXMapTable *grc = (const NXMapTable *)gdb_objc_realized_classes_ptr;
    104     if (grc)
    105     {
    106         const unsigned num_classes = grc->num_classes;
    107         if (class_infos_ptr)
    108         {
    109             const size_t max_class_infos = class_infos_byte_size/sizeof(ClassInfo);
    110             ClassInfo *class_infos = (ClassInfo *)class_infos_ptr;
    111             BucketInfo *buckets = (BucketInfo *)grc->buckets;
    112 
    113             uint32_t idx = 0;
    114             for (unsigned i=0; i<=grc->num_buckets_minus_one; ++i)
    115             {
    116                 if (buckets[i].name_ptr != NX_MAPNOTAKEY)
    117                 {
    118                     if (idx < max_class_infos)
    119                     {
    120                         const char *s = buckets[i].name_ptr;
    121                         uint32_t h = 5381;
    122                         for (unsigned char c = *s; c; c = *++s)
    123                             h = ((h << 5) + h) + c;
    124                         class_infos[idx].hash = h;
    125                         class_infos[idx].isa = buckets[i].isa;
    126                     }
    127                     ++idx;
    128                 }
    129             }
    130             if (idx < max_class_infos)
    131             {
    132                 class_infos[idx].isa = NULL;
    133                 class_infos[idx].hash = 0;
    134             }
    135         }
    136         return num_classes;
    137     }
    138     return 0;
    139 }
    140 
    141 )";
    142 
    143 static const char *g_get_shared_cache_class_info_name = "__lldb_apple_objc_v2_get_shared_cache_class_info";
    144 // Testing using the new C++11 raw string literals. If this breaks GCC then we will
    145 // need to revert to the code above...
    146 static const char *g_get_shared_cache_class_info_body = R"(
    147 
    148 extern "C"
    149 {
    150     const char *class_getName(void *objc_class);
    151     size_t strlen(const char *);
    152     char *strncpy (char * s1, const char * s2, size_t n);
    153     int printf(const char * format, ...);
    154 }
    155 
    156 //#define ENABLE_DEBUG_PRINTF // COMMENT THIS LINE OUT PRIOR TO CHECKIN
    157 #ifdef ENABLE_DEBUG_PRINTF
    158 #define DEBUG_PRINTF(fmt, ...) printf(fmt, ## __VA_ARGS__)
    159 #else
    160 #define DEBUG_PRINTF(fmt, ...)
    161 #endif
    162 
    163 
    164 struct objc_classheader_t {
    165     int32_t clsOffset;
    166     int32_t hiOffset;
    167 };
    168 
    169 struct objc_clsopt_t {
    170     uint32_t capacity;
    171     uint32_t occupied;
    172     uint32_t shift;
    173     uint32_t mask;
    174     uint32_t zero;
    175     uint32_t unused;
    176     uint64_t salt;
    177     uint32_t scramble[256];
    178     uint8_t tab[0]; // tab[mask+1]
    179     //  uint8_t checkbytes[capacity];
    180     //  int32_t offset[capacity];
    181     //  objc_classheader_t clsOffsets[capacity];
    182     //  uint32_t duplicateCount;
    183     //  objc_classheader_t duplicateOffsets[duplicateCount];
    184 };
    185 
    186 struct objc_opt_t {
    187     uint32_t version;
    188     int32_t selopt_offset;
    189     int32_t headeropt_offset;
    190     int32_t clsopt_offset;
    191 };
    192 
    193 struct ClassInfo
    194 {
    195     Class isa;
    196     uint32_t hash;
    197 }  __attribute__((__packed__));
    198 
    199 uint32_t
    200 __lldb_apple_objc_v2_get_shared_cache_class_info (void *objc_opt_ro_ptr,
    201                                                   void *class_infos_ptr,
    202                                                   uint32_t class_infos_byte_size)
    203 {
    204     uint32_t idx = 0;
    205     DEBUG_PRINTF ("objc_opt_ro_ptr = %p\n", objc_opt_ro_ptr);
    206     DEBUG_PRINTF ("class_infos_ptr = %p\n", class_infos_ptr);
    207     DEBUG_PRINTF ("class_infos_byte_size = %u (%zu class infos)\n", class_infos_byte_size, (size_t)(class_infos_byte_size/sizeof(ClassInfo)));
    208     if (objc_opt_ro_ptr)
    209     {
    210         const objc_opt_t *objc_opt = (objc_opt_t *)objc_opt_ro_ptr;
    211         DEBUG_PRINTF ("objc_opt->version = %u\n", objc_opt->version);
    212         DEBUG_PRINTF ("objc_opt->selopt_offset = %d\n", objc_opt->selopt_offset);
    213         DEBUG_PRINTF ("objc_opt->headeropt_offset = %d\n", objc_opt->headeropt_offset);
    214         DEBUG_PRINTF ("objc_opt->clsopt_offset = %d\n", objc_opt->clsopt_offset);
    215         if (objc_opt->version == 12)
    216         {
    217             const objc_clsopt_t* clsopt = (const objc_clsopt_t*)((uint8_t *)objc_opt + objc_opt->clsopt_offset);
    218             const size_t max_class_infos = class_infos_byte_size/sizeof(ClassInfo);
    219             ClassInfo *class_infos = (ClassInfo *)class_infos_ptr;
    220             int32_t zeroOffset = 16;
    221             const uint8_t *checkbytes = &clsopt->tab[clsopt->mask+1];
    222             const int32_t *offsets = (const int32_t *)(checkbytes + clsopt->capacity);
    223             const objc_classheader_t *classOffsets = (const objc_classheader_t *)(offsets + clsopt->capacity);
    224             DEBUG_PRINTF ("clsopt->capacity = %u\n", clsopt->capacity);
    225             DEBUG_PRINTF ("clsopt->mask = 0x%8.8x\n", clsopt->mask);
    226             DEBUG_PRINTF ("classOffsets = %p\n", classOffsets);
    227             for (uint32_t i=0; i<clsopt->capacity; ++i)
    228             {
    229                 const int32_t clsOffset = classOffsets[i].clsOffset;
    230                 if (clsOffset & 1)
    231                     continue; // duplicate
    232                 else if (clsOffset == zeroOffset)
    233                     continue; // zero offset
    234 
    235                 if (class_infos && idx < max_class_infos)
    236                 {
    237                     class_infos[idx].isa = (Class)((uint8_t *)clsopt + clsOffset);
    238                     const char *name = class_getName (class_infos[idx].isa);
    239                     DEBUG_PRINTF ("[%u] isa = %8p %s\n", idx, class_infos[idx].isa, name);
    240                     // Hash the class name so we don't have to read it
    241                     const char *s = name;
    242                     uint32_t h = 5381;
    243                     for (unsigned char c = *s; c; c = *++s)
    244                         h = ((h << 5) + h) + c;
    245                     class_infos[idx].hash = h;
    246                 }
    247                 ++idx;
    248             }
    249 
    250             const uint32_t *duplicate_count_ptr = (uint32_t *)&classOffsets[clsopt->capacity];
    251             const uint32_t duplicate_count = *duplicate_count_ptr;
    252             const objc_classheader_t *duplicateClassOffsets = (const objc_classheader_t *)(&duplicate_count_ptr[1]);
    253             DEBUG_PRINTF ("duplicate_count = %u\n", duplicate_count);
    254             DEBUG_PRINTF ("duplicateClassOffsets = %p\n", duplicateClassOffsets);
    255             for (uint32_t i=0; i<duplicate_count; ++i)
    256             {
    257                 const int32_t clsOffset = duplicateClassOffsets[i].clsOffset;
    258                 if (clsOffset & 1)
    259                     continue; // duplicate
    260                 else if (clsOffset == zeroOffset)
    261                     continue; // zero offset
    262 
    263                 if (class_infos && idx < max_class_infos)
    264                 {
    265                     class_infos[idx].isa = (Class)((uint8_t *)clsopt + clsOffset);
    266                     const char *name = class_getName (class_infos[idx].isa);
    267                     DEBUG_PRINTF ("[%u] isa = %8p %s\n", idx, class_infos[idx].isa, name);
    268                     // Hash the class name so we don't have to read it
    269                     const char *s = name;
    270                     uint32_t h = 5381;
    271                     for (unsigned char c = *s; c; c = *++s)
    272                         h = ((h << 5) + h) + c;
    273                     class_infos[idx].hash = h;
    274                 }
    275                 ++idx;
    276             }
    277         }
    278         DEBUG_PRINTF ("%u class_infos\n", idx);
    279         DEBUG_PRINTF ("done\n");
    280     }
    281     return idx;
    282 }
    283 
    284 
    285 )";
    286 
    287 static uint64_t
    288 ExtractRuntimeGlobalSymbol (Process* process,
    289                             ConstString name,
    290                             const ModuleSP &module_sp,
    291                             Error& error,
    292                             bool read_value = true,
    293                             uint8_t byte_size = 0,
    294                             uint64_t default_value = LLDB_INVALID_ADDRESS,
    295                             SymbolType sym_type = lldb::eSymbolTypeData)
    296 {
    297     if (!process)
    298     {
    299         error.SetErrorString("no process");
    300         return default_value;
    301     }
    302     if (!module_sp)
    303     {
    304         error.SetErrorString("no module");
    305         return default_value;
    306     }
    307     if (!byte_size)
    308         byte_size = process->GetAddressByteSize();
    309     const Symbol *symbol = module_sp->FindFirstSymbolWithNameAndType(name, lldb::eSymbolTypeData);
    310     if (symbol)
    311     {
    312         lldb::addr_t symbol_load_addr = symbol->GetAddress().GetLoadAddress(&process->GetTarget());
    313         if (symbol_load_addr != LLDB_INVALID_ADDRESS)
    314         {
    315             if (read_value)
    316                 return process->ReadUnsignedIntegerFromMemory(symbol_load_addr, byte_size, default_value, error);
    317             else
    318                 return symbol_load_addr;
    319         }
    320         else
    321         {
    322             error.SetErrorString("symbol address invalid");
    323             return default_value;
    324         }
    325     }
    326     else
    327     {
    328         error.SetErrorString("no symbol");
    329         return default_value;
    330     }
    331 
    332 }
    333 
    334 AppleObjCRuntimeV2::AppleObjCRuntimeV2 (Process *process,
    335                                         const ModuleSP &objc_module_sp) :
    336     AppleObjCRuntime (process),
    337     m_get_class_info_function(),
    338     m_get_class_info_code(),
    339     m_get_class_info_args (LLDB_INVALID_ADDRESS),
    340     m_get_class_info_args_mutex (Mutex::eMutexTypeNormal),
    341     m_get_shared_cache_class_info_function(),
    342     m_get_shared_cache_class_info_code(),
    343     m_get_shared_cache_class_info_args (LLDB_INVALID_ADDRESS),
    344     m_get_shared_cache_class_info_args_mutex (Mutex::eMutexTypeNormal),
    345     m_type_vendor_ap (),
    346     m_isa_hash_table_ptr (LLDB_INVALID_ADDRESS),
    347     m_hash_signature (),
    348     m_has_object_getClass (false),
    349     m_loaded_objc_opt (false),
    350     m_non_pointer_isa_cache_ap(NonPointerISACache::CreateInstance(*this,objc_module_sp)),
    351     m_tagged_pointer_vendor_ap(TaggedPointerVendor::CreateInstance(*this,objc_module_sp))
    352 {
    353     static const ConstString g_gdb_object_getClass("gdb_object_getClass");
    354     m_has_object_getClass = (objc_module_sp->FindFirstSymbolWithNameAndType(g_gdb_object_getClass, eSymbolTypeCode) != NULL);
    355 }
    356 
    357 AppleObjCRuntimeV2::~AppleObjCRuntimeV2()
    358 {
    359 }
    360 
    361 bool
    362 AppleObjCRuntimeV2::GetDynamicTypeAndAddress (ValueObject &in_value,
    363                                               DynamicValueType use_dynamic,
    364                                               TypeAndOrName &class_type_or_name,
    365                                               Address &address)
    366 {
    367     // The Runtime is attached to a particular process, you shouldn't pass in a value from another process.
    368     assert (in_value.GetProcessSP().get() == m_process);
    369     assert (m_process != NULL);
    370 
    371     class_type_or_name.Clear();
    372 
    373     // Make sure we can have a dynamic value before starting...
    374     if (CouldHaveDynamicValue (in_value))
    375     {
    376         // First job, pull out the address at 0 offset from the object  That will be the ISA pointer.
    377         ClassDescriptorSP objc_class_sp (GetNonKVOClassDescriptor (in_value));
    378         if (objc_class_sp)
    379         {
    380             const addr_t object_ptr = in_value.GetPointerValue();
    381             address.SetRawAddress(object_ptr);
    382 
    383             ConstString class_name (objc_class_sp->GetClassName());
    384             class_type_or_name.SetName(class_name);
    385             TypeSP type_sp (objc_class_sp->GetType());
    386             if (type_sp)
    387                 class_type_or_name.SetTypeSP (type_sp);
    388             else
    389             {
    390                 type_sp = LookupInCompleteClassCache (class_name);
    391                 if (type_sp)
    392                 {
    393                     objc_class_sp->SetType (type_sp);
    394                     class_type_or_name.SetTypeSP (type_sp);
    395                 }
    396             }
    397         }
    398     }
    399     return class_type_or_name.IsEmpty() == false;
    400 }
    401 
    402 //------------------------------------------------------------------
    403 // Static Functions
    404 //------------------------------------------------------------------
    405 LanguageRuntime *
    406 AppleObjCRuntimeV2::CreateInstance (Process *process, LanguageType language)
    407 {
    408     // FIXME: This should be a MacOS or iOS process, and we need to look for the OBJC section to make
    409     // sure we aren't using the V1 runtime.
    410     if (language == eLanguageTypeObjC)
    411     {
    412         ModuleSP objc_module_sp;
    413 
    414         if (AppleObjCRuntime::GetObjCVersion (process, objc_module_sp) == eAppleObjC_V2)
    415             return new AppleObjCRuntimeV2 (process, objc_module_sp);
    416         else
    417             return NULL;
    418     }
    419     else
    420         return NULL;
    421 }
    422 
    423 void
    424 AppleObjCRuntimeV2::Initialize()
    425 {
    426     PluginManager::RegisterPlugin (GetPluginNameStatic(),
    427                                    "Apple Objective C Language Runtime - Version 2",
    428                                    CreateInstance);
    429 }
    430 
    431 void
    432 AppleObjCRuntimeV2::Terminate()
    433 {
    434     PluginManager::UnregisterPlugin (CreateInstance);
    435 }
    436 
    437 lldb_private::ConstString
    438 AppleObjCRuntimeV2::GetPluginNameStatic()
    439 {
    440     static ConstString g_name("apple-objc-v2");
    441     return g_name;
    442 }
    443 
    444 
    445 //------------------------------------------------------------------
    446 // PluginInterface protocol
    447 //------------------------------------------------------------------
    448 lldb_private::ConstString
    449 AppleObjCRuntimeV2::GetPluginName()
    450 {
    451     return GetPluginNameStatic();
    452 }
    453 
    454 uint32_t
    455 AppleObjCRuntimeV2::GetPluginVersion()
    456 {
    457     return 1;
    458 }
    459 
    460 BreakpointResolverSP
    461 AppleObjCRuntimeV2::CreateExceptionResolver (Breakpoint *bkpt, bool catch_bp, bool throw_bp)
    462 {
    463     BreakpointResolverSP resolver_sp;
    464 
    465     if (throw_bp)
    466         resolver_sp.reset (new BreakpointResolverName (bkpt,
    467                                                        "objc_exception_throw",
    468                                                        eFunctionNameTypeBase,
    469                                                        Breakpoint::Exact,
    470                                                        eLazyBoolNo));
    471     // FIXME: We don't do catch breakpoints for ObjC yet.
    472     // Should there be some way for the runtime to specify what it can do in this regard?
    473     return resolver_sp;
    474 }
    475 
    476 ClangUtilityFunction *
    477 AppleObjCRuntimeV2::CreateObjectChecker(const char *name)
    478 {
    479     char check_function_code[2048];
    480 
    481     int len = 0;
    482     if (m_has_object_getClass)
    483     {
    484         len = ::snprintf (check_function_code,
    485                           sizeof(check_function_code),
    486                           "extern \"C\" void *gdb_object_getClass(void *);                                          \n"
    487                           "extern \"C\"  int printf(const char *format, ...);                                       \n"
    488                           "extern \"C\" void                                                                        \n"
    489                           "%s(void *$__lldb_arg_obj, void *$__lldb_arg_selector)                                    \n"
    490                           "{                                                                                        \n"
    491                           "   if ($__lldb_arg_obj == (void *)0)                                                     \n"
    492                           "       return; // nil is ok                                                              \n"
    493                           "   if (!gdb_object_getClass($__lldb_arg_obj))                                            \n"
    494                           "       *((volatile int *)0) = 'ocgc';                                                    \n"
    495                           "   else if ($__lldb_arg_selector != (void *)0)                                           \n"
    496                           "   {                                                                                     \n"
    497                           "        signed char responds = (signed char) [(id) $__lldb_arg_obj                       \n"
    498                           "                                                respondsToSelector:                      \n"
    499                           "                                       (struct objc_selector *) $__lldb_arg_selector];   \n"
    500                           "       if (responds == (signed char) 0)                                                  \n"
    501                           "           *((volatile int *)0) = 'ocgc';                                                \n"
    502                           "   }                                                                                     \n"
    503                           "}                                                                                        \n",
    504                           name);
    505     }
    506     else
    507     {
    508         len = ::snprintf (check_function_code,
    509                           sizeof(check_function_code),
    510                           "extern \"C\" void *gdb_class_getClass(void *);                                           \n"
    511                           "extern \"C\"  int printf(const char *format, ...);                                       \n"
    512                           "extern \"C\"  void                                                                       \n"
    513                           "%s(void *$__lldb_arg_obj, void *$__lldb_arg_selector)                                    \n"
    514                           "{                                                                                        \n"
    515                           "   if ($__lldb_arg_obj == (void *)0)                                                     \n"
    516                           "       return; // nil is ok                                                              \n"
    517                           "    void **$isa_ptr = (void **)$__lldb_arg_obj;                                          \n"
    518                           "    if (*$isa_ptr == (void *)0 || !gdb_class_getClass(*$isa_ptr))                        \n"
    519                           "       *((volatile int *)0) = 'ocgc';                                                    \n"
    520                           "   else if ($__lldb_arg_selector != (void *)0)                                           \n"
    521                           "   {                                                                                     \n"
    522                           "        signed char responds = (signed char) [(id) $__lldb_arg_obj                       \n"
    523                           "                                                respondsToSelector:                      \n"
    524                           "                                        (struct objc_selector *) $__lldb_arg_selector];  \n"
    525                           "       if (responds == (signed char) 0)                                                  \n"
    526                           "           *((volatile int *)0) = 'ocgc';                                                \n"
    527                           "   }                                                                                     \n"
    528                           "}                                                                                        \n",
    529                           name);
    530     }
    531 
    532     assert (len < (int)sizeof(check_function_code));
    533 
    534     return new ClangUtilityFunction(check_function_code, name);
    535 }
    536 
    537 size_t
    538 AppleObjCRuntimeV2::GetByteOffsetForIvar (ClangASTType &parent_ast_type, const char *ivar_name)
    539 {
    540     const char *class_name = parent_ast_type.GetConstTypeName().AsCString();
    541 
    542     if (!class_name || *class_name == '\0' || !ivar_name || *ivar_name == '\0')
    543         return LLDB_INVALID_IVAR_OFFSET;
    544 
    545     std::string buffer("OBJC_IVAR_$_");
    546     buffer.append (class_name);
    547     buffer.push_back ('.');
    548     buffer.append (ivar_name);
    549     ConstString ivar_const_str (buffer.c_str());
    550 
    551     SymbolContextList sc_list;
    552     Target &target = m_process->GetTarget();
    553 
    554     target.GetImages().FindSymbolsWithNameAndType(ivar_const_str, eSymbolTypeObjCIVar, sc_list);
    555 
    556     SymbolContext ivar_offset_symbol;
    557     if (sc_list.GetSize() != 1
    558         || !sc_list.GetContextAtIndex(0, ivar_offset_symbol)
    559         || ivar_offset_symbol.symbol == NULL)
    560         return LLDB_INVALID_IVAR_OFFSET;
    561 
    562     addr_t ivar_offset_address = ivar_offset_symbol.symbol->GetAddress().GetLoadAddress (&target);
    563 
    564     Error error;
    565 
    566     uint32_t ivar_offset = m_process->ReadUnsignedIntegerFromMemory (ivar_offset_address,
    567                                                                      4,
    568                                                                      LLDB_INVALID_IVAR_OFFSET,
    569                                                                      error);
    570     return ivar_offset;
    571 }
    572 
    573 
    574 // tagged pointers are special not-a-real-pointer values that contain both type and value information
    575 // this routine attempts to check with as little computational effort as possible whether something
    576 // could possibly be a tagged pointer - false positives are possible but false negatives shouldn't
    577 bool
    578 AppleObjCRuntimeV2::IsTaggedPointer(addr_t ptr)
    579 {
    580     if (!m_tagged_pointer_vendor_ap)
    581         return false;
    582     return m_tagged_pointer_vendor_ap->IsPossibleTaggedPointer(ptr);
    583 }
    584 
    585 class RemoteNXMapTable
    586 {
    587 public:
    588 
    589     RemoteNXMapTable () :
    590         m_count (0),
    591         m_num_buckets_minus_one (0),
    592         m_buckets_ptr (LLDB_INVALID_ADDRESS),
    593         m_process (NULL),
    594         m_end_iterator (*this, -1),
    595         m_load_addr (LLDB_INVALID_ADDRESS),
    596         m_map_pair_size (0),
    597         m_invalid_key (0)
    598     {
    599     }
    600 
    601     void
    602     Dump ()
    603     {
    604         printf ("RemoteNXMapTable.m_load_addr = 0x%" PRIx64 "\n", m_load_addr);
    605         printf ("RemoteNXMapTable.m_count = %u\n", m_count);
    606         printf ("RemoteNXMapTable.m_num_buckets_minus_one = %u\n", m_num_buckets_minus_one);
    607         printf ("RemoteNXMapTable.m_buckets_ptr = 0x%" PRIX64 "\n", m_buckets_ptr);
    608     }
    609 
    610     bool
    611     ParseHeader (Process* process, lldb::addr_t load_addr)
    612     {
    613         m_process = process;
    614         m_load_addr = load_addr;
    615         m_map_pair_size = m_process->GetAddressByteSize() * 2;
    616         m_invalid_key = m_process->GetAddressByteSize() == 8 ? UINT64_MAX : UINT32_MAX;
    617         Error err;
    618 
    619         // This currently holds true for all platforms we support, but we might
    620         // need to change this to use get the actualy byte size of "unsigned"
    621         // from the target AST...
    622         const uint32_t unsigned_byte_size = sizeof(uint32_t);
    623         // Skip the prototype as we don't need it (const struct +NXMapTablePrototype *prototype)
    624 
    625         bool success = true;
    626         if (load_addr == LLDB_INVALID_ADDRESS)
    627             success = false;
    628         else
    629         {
    630             lldb::addr_t cursor = load_addr + m_process->GetAddressByteSize();
    631 
    632             // unsigned count;
    633             m_count = m_process->ReadUnsignedIntegerFromMemory(cursor, unsigned_byte_size, 0, err);
    634             if (m_count)
    635             {
    636                 cursor += unsigned_byte_size;
    637 
    638                 // unsigned nbBucketsMinusOne;
    639                 m_num_buckets_minus_one = m_process->ReadUnsignedIntegerFromMemory(cursor, unsigned_byte_size, 0, err);
    640                 cursor += unsigned_byte_size;
    641 
    642                 // void *buckets;
    643                 m_buckets_ptr = m_process->ReadPointerFromMemory(cursor, err);
    644 
    645                 success = m_count > 0 && m_buckets_ptr != LLDB_INVALID_ADDRESS;
    646             }
    647         }
    648 
    649         if (!success)
    650         {
    651             m_count = 0;
    652             m_num_buckets_minus_one = 0;
    653             m_buckets_ptr = LLDB_INVALID_ADDRESS;
    654         }
    655         return success;
    656     }
    657 
    658     // const_iterator mimics NXMapState and its code comes from NXInitMapState and NXNextMapState.
    659     typedef std::pair<ConstString, ObjCLanguageRuntime::ObjCISA> element;
    660 
    661     friend class const_iterator;
    662     class const_iterator
    663     {
    664     public:
    665         const_iterator (RemoteNXMapTable &parent, int index) : m_parent(parent), m_index(index)
    666         {
    667             AdvanceToValidIndex();
    668         }
    669 
    670         const_iterator (const const_iterator &rhs) : m_parent(rhs.m_parent), m_index(rhs.m_index)
    671         {
    672             // AdvanceToValidIndex() has been called by rhs already.
    673         }
    674 
    675         const_iterator &operator=(const const_iterator &rhs)
    676         {
    677             // AdvanceToValidIndex() has been called by rhs already.
    678             assert (&m_parent == &rhs.m_parent);
    679             m_index = rhs.m_index;
    680             return *this;
    681         }
    682 
    683         bool operator==(const const_iterator &rhs) const
    684         {
    685             if (&m_parent != &rhs.m_parent)
    686                 return false;
    687             if (m_index != rhs.m_index)
    688                 return false;
    689 
    690             return true;
    691         }
    692 
    693         bool operator!=(const const_iterator &rhs) const
    694         {
    695             return !(operator==(rhs));
    696         }
    697 
    698         const_iterator &operator++()
    699         {
    700             AdvanceToValidIndex();
    701             return *this;
    702         }
    703 
    704         const element operator*() const
    705         {
    706             if (m_index == -1)
    707             {
    708                 // TODO find a way to make this an error, but not an assert
    709                 return element();
    710             }
    711 
    712             lldb::addr_t pairs_ptr = m_parent.m_buckets_ptr;
    713             size_t map_pair_size = m_parent.m_map_pair_size;
    714             lldb::addr_t pair_ptr = pairs_ptr + (m_index * map_pair_size);
    715 
    716             Error err;
    717 
    718             lldb::addr_t key = m_parent.m_process->ReadPointerFromMemory(pair_ptr, err);
    719             if (!err.Success())
    720                 return element();
    721             lldb::addr_t value = m_parent.m_process->ReadPointerFromMemory(pair_ptr + m_parent.m_process->GetAddressByteSize(), err);
    722             if (!err.Success())
    723                 return element();
    724 
    725             std::string key_string;
    726 
    727             m_parent.m_process->ReadCStringFromMemory(key, key_string, err);
    728             if (!err.Success())
    729                 return element();
    730 
    731             return element(ConstString(key_string.c_str()), (ObjCLanguageRuntime::ObjCISA)value);
    732         }
    733     private:
    734         void AdvanceToValidIndex ()
    735         {
    736             if (m_index == -1)
    737                 return;
    738 
    739             const lldb::addr_t pairs_ptr = m_parent.m_buckets_ptr;
    740             const size_t map_pair_size = m_parent.m_map_pair_size;
    741             const lldb::addr_t invalid_key = m_parent.m_invalid_key;
    742             Error err;
    743 
    744             while (m_index--)
    745             {
    746                 lldb::addr_t pair_ptr = pairs_ptr + (m_index * map_pair_size);
    747                 lldb::addr_t key = m_parent.m_process->ReadPointerFromMemory(pair_ptr, err);
    748 
    749                 if (!err.Success())
    750                 {
    751                     m_index = -1;
    752                     return;
    753                 }
    754 
    755                 if (key != invalid_key)
    756                     return;
    757             }
    758         }
    759         RemoteNXMapTable   &m_parent;
    760         int                 m_index;
    761     };
    762 
    763     const_iterator begin ()
    764     {
    765         return const_iterator(*this, m_num_buckets_minus_one + 1);
    766     }
    767 
    768     const_iterator end ()
    769     {
    770         return m_end_iterator;
    771     }
    772 
    773     uint32_t
    774     GetCount () const
    775     {
    776         return m_count;
    777     }
    778 
    779     uint32_t
    780     GetBucketCount () const
    781     {
    782         return m_num_buckets_minus_one;
    783     }
    784 
    785     lldb::addr_t
    786     GetBucketDataPointer () const
    787     {
    788         return m_buckets_ptr;
    789     }
    790 
    791     lldb::addr_t
    792     GetTableLoadAddress() const
    793     {
    794         return m_load_addr;
    795     }
    796 
    797 private:
    798     // contents of _NXMapTable struct
    799     uint32_t m_count;
    800     uint32_t m_num_buckets_minus_one;
    801     lldb::addr_t m_buckets_ptr;
    802     lldb_private::Process *m_process;
    803     const_iterator m_end_iterator;
    804     lldb::addr_t m_load_addr;
    805     size_t m_map_pair_size;
    806     lldb::addr_t m_invalid_key;
    807 };
    808 
    809 
    810 
    811 AppleObjCRuntimeV2::HashTableSignature::HashTableSignature() :
    812     m_count (0),
    813     m_num_buckets (0),
    814     m_buckets_ptr (0)
    815 {
    816 }
    817 
    818 void
    819 AppleObjCRuntimeV2::HashTableSignature::UpdateSignature (const RemoteNXMapTable &hash_table)
    820 {
    821     m_count = hash_table.GetCount();
    822     m_num_buckets = hash_table.GetBucketCount();
    823     m_buckets_ptr = hash_table.GetBucketDataPointer();
    824 }
    825 
    826 bool
    827 AppleObjCRuntimeV2::HashTableSignature::NeedsUpdate (Process *process, AppleObjCRuntimeV2 *runtime, RemoteNXMapTable &hash_table)
    828 {
    829     if (!hash_table.ParseHeader(process, runtime->GetISAHashTablePointer ()))
    830     {
    831         return false; // Failed to parse the header, no need to update anything
    832     }
    833 
    834     // Check with out current signature and return true if the count,
    835     // number of buckets or the hash table address changes.
    836     if (m_count == hash_table.GetCount() &&
    837         m_num_buckets == hash_table.GetBucketCount() &&
    838         m_buckets_ptr == hash_table.GetBucketDataPointer())
    839     {
    840         // Hash table hasn't changed
    841         return false;
    842     }
    843     // Hash table data has changed, we need to update
    844     return true;
    845 }
    846 
    847 class ClassDescriptorV2 : public ObjCLanguageRuntime::ClassDescriptor
    848 {
    849 public:
    850     friend class lldb_private::AppleObjCRuntimeV2;
    851 
    852 private:
    853     // The constructor should only be invoked by the runtime as it builds its caches
    854     // or populates them.  A ClassDescriptorV2 should only ever exist in a cache.
    855     ClassDescriptorV2 (AppleObjCRuntimeV2 &runtime, ObjCLanguageRuntime::ObjCISA isa, const char *name) :
    856         m_runtime (runtime),
    857         m_objc_class_ptr (isa),
    858         m_name (name)
    859     {
    860     }
    861 
    862 public:
    863     virtual ConstString
    864     GetClassName ()
    865     {
    866         if (!m_name)
    867         {
    868             lldb_private::Process *process = m_runtime.GetProcess();
    869 
    870             if (process)
    871             {
    872                 std::unique_ptr<objc_class_t> objc_class;
    873                 std::unique_ptr<class_ro_t> class_ro;
    874                 std::unique_ptr<class_rw_t> class_rw;
    875 
    876                 if (!Read_objc_class(process, objc_class))
    877                     return m_name;
    878                 if (!Read_class_row(process, *objc_class, class_ro, class_rw))
    879                     return m_name;
    880 
    881                 m_name = ConstString(class_ro->m_name.c_str());
    882             }
    883         }
    884         return m_name;
    885     }
    886 
    887     virtual ObjCLanguageRuntime::ClassDescriptorSP
    888     GetSuperclass ()
    889     {
    890         lldb_private::Process *process = m_runtime.GetProcess();
    891 
    892         if (!process)
    893             return ObjCLanguageRuntime::ClassDescriptorSP();
    894 
    895         std::unique_ptr<objc_class_t> objc_class;
    896 
    897         if (!Read_objc_class(process, objc_class))
    898             return ObjCLanguageRuntime::ClassDescriptorSP();
    899 
    900         return m_runtime.ObjCLanguageRuntime::GetClassDescriptorFromISA(objc_class->m_superclass);
    901     }
    902 
    903     virtual bool
    904     IsValid ()
    905     {
    906         return true;    // any Objective-C v2 runtime class descriptor we vend is valid
    907     }
    908 
    909     // a custom descriptor is used for tagged pointers
    910     virtual bool
    911     GetTaggedPointerInfo (uint64_t* info_bits = NULL,
    912                           uint64_t* value_bits = NULL,
    913                           uint64_t* payload = NULL)
    914     {
    915         return false;
    916     }
    917 
    918     virtual uint64_t
    919     GetInstanceSize ()
    920     {
    921         lldb_private::Process *process = m_runtime.GetProcess();
    922 
    923         if (process)
    924         {
    925             std::unique_ptr<objc_class_t> objc_class;
    926             std::unique_ptr<class_ro_t> class_ro;
    927             std::unique_ptr<class_rw_t> class_rw;
    928 
    929             if (!Read_objc_class(process, objc_class))
    930                 return 0;
    931             if (!Read_class_row(process, *objc_class, class_ro, class_rw))
    932                 return 0;
    933 
    934             return class_ro->m_instanceSize;
    935         }
    936 
    937         return 0;
    938     }
    939 
    940     virtual ObjCLanguageRuntime::ObjCISA
    941     GetISA ()
    942     {
    943         return m_objc_class_ptr;
    944     }
    945 
    946     virtual bool
    947     Describe (std::function <void (ObjCLanguageRuntime::ObjCISA)> const &superclass_func,
    948               std::function <bool (const char *, const char *)> const &instance_method_func,
    949               std::function <bool (const char *, const char *)> const &class_method_func,
    950               std::function <bool (const char *, const char *, lldb::addr_t, uint64_t)> const &ivar_func)
    951     {
    952         lldb_private::Process *process = m_runtime.GetProcess();
    953 
    954         std::unique_ptr<objc_class_t> objc_class;
    955         std::unique_ptr<class_ro_t> class_ro;
    956         std::unique_ptr<class_rw_t> class_rw;
    957 
    958         if (!Read_objc_class(process, objc_class))
    959             return 0;
    960         if (!Read_class_row(process, *objc_class, class_ro, class_rw))
    961             return 0;
    962 
    963         static ConstString NSObject_name("NSObject");
    964 
    965         if (m_name != NSObject_name && superclass_func)
    966             superclass_func(objc_class->m_superclass);
    967 
    968         if (instance_method_func)
    969         {
    970             std::unique_ptr<method_list_t> base_method_list;
    971 
    972             base_method_list.reset(new method_list_t);
    973             if (!base_method_list->Read(process, class_ro->m_baseMethods_ptr))
    974                 return false;
    975 
    976             if (base_method_list->m_entsize != method_t::GetSize(process))
    977                 return false;
    978 
    979             std::unique_ptr<method_t> method;
    980             method.reset(new method_t);
    981 
    982             for (uint32_t i = 0, e = base_method_list->m_count; i < e; ++i)
    983             {
    984                 method->Read(process, base_method_list->m_first_ptr + (i * base_method_list->m_entsize));
    985 
    986                 if (instance_method_func(method->m_name.c_str(), method->m_types.c_str()))
    987                     break;
    988             }
    989         }
    990 
    991         if (class_method_func)
    992         {
    993             ClassDescriptorV2 metaclass(m_runtime, objc_class->m_isa, NULL); // The metaclass is not in the cache
    994 
    995             // We don't care about the metaclass's superclass, or its class methods.  Its instance methods are
    996             // our class methods.
    997 
    998             metaclass.Describe(std::function <void (ObjCLanguageRuntime::ObjCISA)> (nullptr),
    999                                class_method_func,
   1000                                std::function <bool (const char *, const char *)> (nullptr),
   1001                                std::function <bool (const char *, const char *, lldb::addr_t, uint64_t)> (nullptr));
   1002         }
   1003 
   1004         if (ivar_func)
   1005         {
   1006             ivar_list_t ivar_list;
   1007             if (!ivar_list.Read(process, class_ro->m_ivars_ptr))
   1008                 return false;
   1009 
   1010             if (ivar_list.m_entsize != ivar_t::GetSize(process))
   1011                 return false;
   1012 
   1013             ivar_t ivar;
   1014 
   1015             for (uint32_t i = 0, e = ivar_list.m_count; i < e; ++i)
   1016             {
   1017                 ivar.Read(process, ivar_list.m_first_ptr + (i * ivar_list.m_entsize));
   1018 
   1019                 if (ivar_func(ivar.m_name.c_str(), ivar.m_type.c_str(), ivar.m_offset_ptr, ivar.m_size))
   1020                     break;
   1021             }
   1022         }
   1023 
   1024         return true;
   1025     }
   1026 
   1027     virtual
   1028     ~ClassDescriptorV2 ()
   1029     {
   1030     }
   1031 
   1032 private:
   1033     static const uint32_t RW_REALIZED = (1 << 31);
   1034 
   1035     struct objc_class_t {
   1036         ObjCLanguageRuntime::ObjCISA    m_isa;              // The class's metaclass.
   1037         ObjCLanguageRuntime::ObjCISA    m_superclass;
   1038         lldb::addr_t                    m_cache_ptr;
   1039         lldb::addr_t                    m_vtable_ptr;
   1040         lldb::addr_t                    m_data_ptr;
   1041         uint8_t                         m_flags;
   1042 
   1043         objc_class_t () :
   1044             m_isa (0),
   1045             m_superclass (0),
   1046             m_cache_ptr (0),
   1047             m_vtable_ptr (0),
   1048             m_data_ptr (0),
   1049             m_flags (0)
   1050         {
   1051         }
   1052 
   1053         void
   1054         Clear()
   1055         {
   1056             m_isa = 0;
   1057             m_superclass = 0;
   1058             m_cache_ptr = 0;
   1059             m_vtable_ptr = 0;
   1060             m_data_ptr = 0;
   1061             m_flags = 0;
   1062         }
   1063 
   1064         bool Read(Process *process, lldb::addr_t addr)
   1065         {
   1066             size_t ptr_size = process->GetAddressByteSize();
   1067 
   1068             size_t objc_class_size = ptr_size   // uintptr_t isa;
   1069             + ptr_size   // Class superclass;
   1070             + ptr_size   // void *cache;
   1071             + ptr_size   // IMP *vtable;
   1072             + ptr_size;  // uintptr_t data_NEVER_USE;
   1073 
   1074             DataBufferHeap objc_class_buf (objc_class_size, '\0');
   1075             Error error;
   1076 
   1077             process->ReadMemory(addr, objc_class_buf.GetBytes(), objc_class_size, error);
   1078             if (error.Fail())
   1079             {
   1080                 return false;
   1081             }
   1082 
   1083             DataExtractor extractor(objc_class_buf.GetBytes(), objc_class_size, process->GetByteOrder(), process->GetAddressByteSize());
   1084 
   1085             lldb::offset_t cursor = 0;
   1086 
   1087             m_isa           = extractor.GetAddress_unchecked(&cursor);   // uintptr_t isa;
   1088             m_superclass    = extractor.GetAddress_unchecked(&cursor);   // Class superclass;
   1089             m_cache_ptr     = extractor.GetAddress_unchecked(&cursor);   // void *cache;
   1090             m_vtable_ptr    = extractor.GetAddress_unchecked(&cursor);   // IMP *vtable;
   1091             lldb::addr_t data_NEVER_USE = extractor.GetAddress_unchecked(&cursor);   // uintptr_t data_NEVER_USE;
   1092 
   1093             m_flags         = (uint8_t)(data_NEVER_USE & (lldb::addr_t)3);
   1094             m_data_ptr      = data_NEVER_USE & ~(lldb::addr_t)3;
   1095 
   1096             return true;
   1097         }
   1098     };
   1099 
   1100     struct class_ro_t {
   1101         uint32_t                        m_flags;
   1102         uint32_t                        m_instanceStart;
   1103         uint32_t                        m_instanceSize;
   1104         uint32_t                        m_reserved;
   1105 
   1106         lldb::addr_t                    m_ivarLayout_ptr;
   1107         lldb::addr_t                    m_name_ptr;
   1108         lldb::addr_t                    m_baseMethods_ptr;
   1109         lldb::addr_t                    m_baseProtocols_ptr;
   1110         lldb::addr_t                    m_ivars_ptr;
   1111 
   1112         lldb::addr_t                    m_weakIvarLayout_ptr;
   1113         lldb::addr_t                    m_baseProperties_ptr;
   1114 
   1115         std::string                     m_name;
   1116 
   1117         bool Read(Process *process, lldb::addr_t addr)
   1118         {
   1119             size_t ptr_size = process->GetAddressByteSize();
   1120 
   1121             size_t size = sizeof(uint32_t)             // uint32_t flags;
   1122             + sizeof(uint32_t)                         // uint32_t instanceStart;
   1123             + sizeof(uint32_t)                         // uint32_t instanceSize;
   1124             + (ptr_size == 8 ? sizeof(uint32_t) : 0)   // uint32_t reserved; // __LP64__ only
   1125             + ptr_size                                 // const uint8_t *ivarLayout;
   1126             + ptr_size                                 // const char *name;
   1127             + ptr_size                                 // const method_list_t *baseMethods;
   1128             + ptr_size                                 // const protocol_list_t *baseProtocols;
   1129             + ptr_size                                 // const ivar_list_t *ivars;
   1130             + ptr_size                                 // const uint8_t *weakIvarLayout;
   1131             + ptr_size;                                // const property_list_t *baseProperties;
   1132 
   1133             DataBufferHeap buffer (size, '\0');
   1134             Error error;
   1135 
   1136             process->ReadMemory(addr, buffer.GetBytes(), size, error);
   1137             if (error.Fail())
   1138             {
   1139                 return false;
   1140             }
   1141 
   1142             DataExtractor extractor(buffer.GetBytes(), size, process->GetByteOrder(), process->GetAddressByteSize());
   1143 
   1144             lldb::offset_t cursor = 0;
   1145 
   1146             m_flags             = extractor.GetU32_unchecked(&cursor);
   1147             m_instanceStart     = extractor.GetU32_unchecked(&cursor);
   1148             m_instanceSize      = extractor.GetU32_unchecked(&cursor);
   1149             if (ptr_size == 8)
   1150                 m_reserved      = extractor.GetU32_unchecked(&cursor);
   1151             else
   1152                 m_reserved      = 0;
   1153             m_ivarLayout_ptr     = extractor.GetAddress_unchecked(&cursor);
   1154             m_name_ptr           = extractor.GetAddress_unchecked(&cursor);
   1155             m_baseMethods_ptr    = extractor.GetAddress_unchecked(&cursor);
   1156             m_baseProtocols_ptr  = extractor.GetAddress_unchecked(&cursor);
   1157             m_ivars_ptr          = extractor.GetAddress_unchecked(&cursor);
   1158             m_weakIvarLayout_ptr = extractor.GetAddress_unchecked(&cursor);
   1159             m_baseProperties_ptr = extractor.GetAddress_unchecked(&cursor);
   1160 
   1161             DataBufferHeap name_buf(1024, '\0');
   1162 
   1163             process->ReadCStringFromMemory(m_name_ptr, (char*)name_buf.GetBytes(), name_buf.GetByteSize(), error);
   1164 
   1165             if (error.Fail())
   1166             {
   1167                 return false;
   1168             }
   1169 
   1170             m_name.assign((char*)name_buf.GetBytes());
   1171 
   1172             return true;
   1173         }
   1174     };
   1175 
   1176     struct class_rw_t {
   1177         uint32_t                        m_flags;
   1178         uint32_t                        m_version;
   1179 
   1180         lldb::addr_t                    m_ro_ptr;
   1181         union {
   1182             lldb::addr_t                m_method_list_ptr;
   1183             lldb::addr_t                m_method_lists_ptr;
   1184         };
   1185         lldb::addr_t                    m_properties_ptr;
   1186         lldb::addr_t                    m_protocols_ptr;
   1187 
   1188         ObjCLanguageRuntime::ObjCISA    m_firstSubclass;
   1189         ObjCLanguageRuntime::ObjCISA    m_nextSiblingClass;
   1190 
   1191         bool Read(Process *process, lldb::addr_t addr)
   1192         {
   1193             size_t ptr_size = process->GetAddressByteSize();
   1194 
   1195             size_t size = sizeof(uint32_t)  // uint32_t flags;
   1196             + sizeof(uint32_t)  // uint32_t version;
   1197             + ptr_size          // const class_ro_t *ro;
   1198             + ptr_size          // union { method_list_t **method_lists; method_list_t *method_list; };
   1199             + ptr_size          // struct chained_property_list *properties;
   1200             + ptr_size          // const protocol_list_t **protocols;
   1201             + ptr_size          // Class firstSubclass;
   1202             + ptr_size;         // Class nextSiblingClass;
   1203 
   1204             DataBufferHeap buffer (size, '\0');
   1205             Error error;
   1206 
   1207             process->ReadMemory(addr, buffer.GetBytes(), size, error);
   1208             if (error.Fail())
   1209             {
   1210                 return false;
   1211             }
   1212 
   1213             DataExtractor extractor(buffer.GetBytes(), size, process->GetByteOrder(), process->GetAddressByteSize());
   1214 
   1215             lldb::offset_t cursor = 0;
   1216 
   1217             m_flags             = extractor.GetU32_unchecked(&cursor);
   1218             m_version           = extractor.GetU32_unchecked(&cursor);
   1219             m_ro_ptr            = extractor.GetAddress_unchecked(&cursor);
   1220             m_method_list_ptr   = extractor.GetAddress_unchecked(&cursor);
   1221             m_properties_ptr    = extractor.GetAddress_unchecked(&cursor);
   1222             m_firstSubclass     = extractor.GetAddress_unchecked(&cursor);
   1223             m_nextSiblingClass  = extractor.GetAddress_unchecked(&cursor);
   1224 
   1225             return true;
   1226         }
   1227     };
   1228 
   1229     struct method_list_t
   1230     {
   1231         uint32_t        m_entsize;
   1232         uint32_t        m_count;
   1233         lldb::addr_t    m_first_ptr;
   1234 
   1235         bool Read(Process *process, lldb::addr_t addr)
   1236         {
   1237             size_t size = sizeof(uint32_t)  // uint32_t entsize_NEVER_USE;
   1238             + sizeof(uint32_t); // uint32_t count;
   1239 
   1240             DataBufferHeap buffer (size, '\0');
   1241             Error error;
   1242 
   1243             process->ReadMemory(addr, buffer.GetBytes(), size, error);
   1244             if (error.Fail())
   1245             {
   1246                 return false;
   1247             }
   1248 
   1249             DataExtractor extractor(buffer.GetBytes(), size, process->GetByteOrder(), process->GetAddressByteSize());
   1250 
   1251             lldb::offset_t cursor = 0;
   1252 
   1253             m_entsize   = extractor.GetU32_unchecked(&cursor) & ~(uint32_t)3;
   1254             m_count     = extractor.GetU32_unchecked(&cursor);
   1255             m_first_ptr  = addr + cursor;
   1256 
   1257             return true;
   1258         }
   1259     };
   1260 
   1261     struct method_t
   1262     {
   1263         lldb::addr_t    m_name_ptr;
   1264         lldb::addr_t    m_types_ptr;
   1265         lldb::addr_t    m_imp_ptr;
   1266 
   1267         std::string     m_name;
   1268         std::string     m_types;
   1269 
   1270         static size_t GetSize(Process *process)
   1271         {
   1272             size_t ptr_size = process->GetAddressByteSize();
   1273 
   1274             return ptr_size     // SEL name;
   1275             + ptr_size   // const char *types;
   1276             + ptr_size;  // IMP imp;
   1277         }
   1278 
   1279         bool Read(Process *process, lldb::addr_t addr)
   1280         {
   1281             size_t size = GetSize(process);
   1282 
   1283             DataBufferHeap buffer (size, '\0');
   1284             Error error;
   1285 
   1286             process->ReadMemory(addr, buffer.GetBytes(), size, error);
   1287             if (error.Fail())
   1288             {
   1289                 return false;
   1290             }
   1291 
   1292             DataExtractor extractor(buffer.GetBytes(), size, process->GetByteOrder(), process->GetAddressByteSize());
   1293 
   1294             lldb::offset_t cursor = 0;
   1295 
   1296             m_name_ptr   = extractor.GetAddress_unchecked(&cursor);
   1297             m_types_ptr  = extractor.GetAddress_unchecked(&cursor);
   1298             m_imp_ptr    = extractor.GetAddress_unchecked(&cursor);
   1299 
   1300             const size_t buffer_size = 1024;
   1301             size_t count;
   1302 
   1303             DataBufferHeap string_buf(buffer_size, 0);
   1304 
   1305             count = process->ReadCStringFromMemory(m_name_ptr, (char*)string_buf.GetBytes(), buffer_size, error);
   1306             m_name.assign((char*)string_buf.GetBytes(), count);
   1307 
   1308             count = process->ReadCStringFromMemory(m_types_ptr, (char*)string_buf.GetBytes(), buffer_size, error);
   1309             m_types.assign((char*)string_buf.GetBytes(), count);
   1310 
   1311             return true;
   1312         }
   1313     };
   1314 
   1315     struct ivar_list_t
   1316     {
   1317         uint32_t        m_entsize;
   1318         uint32_t        m_count;
   1319         lldb::addr_t    m_first_ptr;
   1320 
   1321         bool Read(Process *process, lldb::addr_t addr)
   1322         {
   1323             size_t size = sizeof(uint32_t)  // uint32_t entsize;
   1324                         + sizeof(uint32_t); // uint32_t count;
   1325 
   1326             DataBufferHeap buffer (size, '\0');
   1327             Error error;
   1328 
   1329             process->ReadMemory(addr, buffer.GetBytes(), size, error);
   1330             if (error.Fail())
   1331             {
   1332                 return false;
   1333             }
   1334 
   1335             DataExtractor extractor(buffer.GetBytes(), size, process->GetByteOrder(), process->GetAddressByteSize());
   1336 
   1337             lldb::offset_t cursor = 0;
   1338 
   1339             m_entsize   = extractor.GetU32_unchecked(&cursor);
   1340             m_count     = extractor.GetU32_unchecked(&cursor);
   1341             m_first_ptr = addr + cursor;
   1342 
   1343             return true;
   1344         }
   1345     };
   1346 
   1347     struct ivar_t
   1348     {
   1349         lldb::addr_t    m_offset_ptr;
   1350         lldb::addr_t    m_name_ptr;
   1351         lldb::addr_t    m_type_ptr;
   1352         uint32_t        m_alignment;
   1353         uint32_t        m_size;
   1354 
   1355         std::string     m_name;
   1356         std::string     m_type;
   1357 
   1358         static size_t GetSize(Process *process)
   1359         {
   1360             size_t ptr_size = process->GetAddressByteSize();
   1361 
   1362             return ptr_size             // uintptr_t *offset;
   1363                  + ptr_size             // const char *name;
   1364                  + ptr_size             // const char *type;
   1365                  + sizeof(uint32_t)     // uint32_t alignment;
   1366                  + sizeof(uint32_t);    // uint32_t size;
   1367         }
   1368 
   1369         bool Read(Process *process, lldb::addr_t addr)
   1370         {
   1371             size_t size = GetSize(process);
   1372 
   1373             DataBufferHeap buffer (size, '\0');
   1374             Error error;
   1375 
   1376             process->ReadMemory(addr, buffer.GetBytes(), size, error);
   1377             if (error.Fail())
   1378             {
   1379                 return false;
   1380             }
   1381 
   1382             DataExtractor extractor(buffer.GetBytes(), size, process->GetByteOrder(), process->GetAddressByteSize());
   1383 
   1384             lldb::offset_t cursor = 0;
   1385 
   1386             m_offset_ptr = extractor.GetAddress_unchecked(&cursor);
   1387             m_name_ptr   = extractor.GetAddress_unchecked(&cursor);
   1388             m_type_ptr   = extractor.GetAddress_unchecked(&cursor);
   1389             m_alignment  = extractor.GetU32_unchecked(&cursor);
   1390             m_size       = extractor.GetU32_unchecked(&cursor);
   1391 
   1392             const size_t buffer_size = 1024;
   1393             size_t count;
   1394 
   1395             DataBufferHeap string_buf(buffer_size, 0);
   1396 
   1397             count = process->ReadCStringFromMemory(m_name_ptr, (char*)string_buf.GetBytes(), buffer_size, error);
   1398             m_name.assign((char*)string_buf.GetBytes(), count);
   1399 
   1400             count = process->ReadCStringFromMemory(m_type_ptr, (char*)string_buf.GetBytes(), buffer_size, error);
   1401             m_type.assign((char*)string_buf.GetBytes(), count);
   1402 
   1403             return true;
   1404         }
   1405     };
   1406 
   1407     bool Read_objc_class (Process* process, std::unique_ptr<objc_class_t> &objc_class)
   1408     {
   1409         objc_class.reset(new objc_class_t);
   1410 
   1411         bool ret = objc_class->Read (process, m_objc_class_ptr);
   1412 
   1413         if (!ret)
   1414             objc_class.reset();
   1415 
   1416         return ret;
   1417     }
   1418 
   1419     bool Read_class_row (Process* process, const objc_class_t &objc_class, std::unique_ptr<class_ro_t> &class_ro, std::unique_ptr<class_rw_t> &class_rw)
   1420     {
   1421         class_ro.reset();
   1422         class_rw.reset();
   1423 
   1424         Error error;
   1425         uint32_t class_row_t_flags = process->ReadUnsignedIntegerFromMemory(objc_class.m_data_ptr, sizeof(uint32_t), 0, error);
   1426         if (!error.Success())
   1427             return false;
   1428 
   1429         if (class_row_t_flags & RW_REALIZED)
   1430         {
   1431             class_rw.reset(new class_rw_t);
   1432 
   1433             if (!class_rw->Read(process, objc_class.m_data_ptr))
   1434             {
   1435                 class_rw.reset();
   1436                 return false;
   1437             }
   1438 
   1439             class_ro.reset(new class_ro_t);
   1440 
   1441             if (!class_ro->Read(process, class_rw->m_ro_ptr))
   1442             {
   1443                 class_rw.reset();
   1444                 class_ro.reset();
   1445                 return false;
   1446             }
   1447         }
   1448         else
   1449         {
   1450             class_ro.reset(new class_ro_t);
   1451 
   1452             if (!class_ro->Read(process, objc_class.m_data_ptr))
   1453             {
   1454                 class_ro.reset();
   1455                 return false;
   1456             }
   1457         }
   1458 
   1459         return true;
   1460     }
   1461 
   1462     AppleObjCRuntimeV2 &m_runtime;          // The runtime, so we can read information lazily.
   1463     lldb::addr_t        m_objc_class_ptr;   // The address of the objc_class_t.  (I.e., objects of this class type have this as their ISA)
   1464     ConstString         m_name;             // May be NULL
   1465 };
   1466 
   1467 // tagged pointer descriptor
   1468 class ClassDescriptorV2Tagged : public ObjCLanguageRuntime::ClassDescriptor
   1469 {
   1470 public:
   1471     ClassDescriptorV2Tagged (ConstString class_name,
   1472                              uint64_t payload)
   1473     {
   1474         m_name = class_name;
   1475         if (!m_name)
   1476         {
   1477             m_valid = false;
   1478             return;
   1479         }
   1480         m_valid = true;
   1481         m_payload = payload;
   1482         m_info_bits = (m_payload & 0xF0ULL) >> 4;
   1483         m_value_bits = (m_payload & ~0x0000000000000000FFULL) >> 8;
   1484     }
   1485 
   1486     ClassDescriptorV2Tagged (ObjCLanguageRuntime::ClassDescriptorSP actual_class_sp,
   1487                              uint64_t payload)
   1488     {
   1489         if (!actual_class_sp)
   1490         {
   1491             m_valid = false;
   1492             return;
   1493         }
   1494         m_name = actual_class_sp->GetClassName();
   1495         if (!m_name)
   1496         {
   1497             m_valid = false;
   1498             return;
   1499         }
   1500         m_valid = true;
   1501         m_payload = payload;
   1502         m_info_bits = (m_payload & 0x0FULL);
   1503         m_value_bits = (m_payload & ~0x0FULL) >> 4;
   1504     }
   1505 
   1506     virtual ConstString
   1507     GetClassName ()
   1508     {
   1509         return m_name;
   1510     }
   1511 
   1512     virtual ObjCLanguageRuntime::ClassDescriptorSP
   1513     GetSuperclass ()
   1514     {
   1515         // tagged pointers can represent a class that has a superclass, but since that information is not
   1516         // stored in the object itself, we would have to query the runtime to discover the hierarchy
   1517         // for the time being, we skip this step in the interest of static discovery
   1518         return ObjCLanguageRuntime::ClassDescriptorSP();
   1519     }
   1520 
   1521     virtual bool
   1522     IsValid ()
   1523     {
   1524         return m_valid;
   1525     }
   1526 
   1527     virtual bool
   1528     IsKVO ()
   1529     {
   1530         return false; // tagged pointers are not KVO'ed
   1531     }
   1532 
   1533     virtual bool
   1534     IsCFType ()
   1535     {
   1536         return false; // tagged pointers are not CF objects
   1537     }
   1538 
   1539     virtual bool
   1540     GetTaggedPointerInfo (uint64_t* info_bits = NULL,
   1541                           uint64_t* value_bits = NULL,
   1542                           uint64_t* payload = NULL)
   1543     {
   1544         if (info_bits)
   1545             *info_bits = GetInfoBits();
   1546         if (value_bits)
   1547             *value_bits = GetValueBits();
   1548         if (payload)
   1549             *payload = GetPayload();
   1550         return true;
   1551     }
   1552 
   1553     virtual uint64_t
   1554     GetInstanceSize ()
   1555     {
   1556         return (IsValid() ? m_pointer_size : 0);
   1557     }
   1558 
   1559     virtual ObjCLanguageRuntime::ObjCISA
   1560     GetISA ()
   1561     {
   1562         return 0; // tagged pointers have no ISA
   1563     }
   1564 
   1565     // these calls are not part of any formal tagged pointers specification
   1566     virtual uint64_t
   1567     GetValueBits ()
   1568     {
   1569         return (IsValid() ? m_value_bits : 0);
   1570     }
   1571 
   1572     virtual uint64_t
   1573     GetInfoBits ()
   1574     {
   1575         return (IsValid() ? m_info_bits : 0);
   1576     }
   1577 
   1578     virtual uint64_t
   1579     GetPayload ()
   1580     {
   1581         return (IsValid() ? m_payload : 0);
   1582     }
   1583 
   1584     virtual
   1585     ~ClassDescriptorV2Tagged ()
   1586     {}
   1587 
   1588 private:
   1589     ConstString m_name;
   1590     uint8_t m_pointer_size;
   1591     bool m_valid;
   1592     uint64_t m_info_bits;
   1593     uint64_t m_value_bits;
   1594     uint64_t m_payload;
   1595 
   1596 };
   1597 
   1598 ObjCLanguageRuntime::ClassDescriptorSP
   1599 AppleObjCRuntimeV2::GetClassDescriptor (ObjCISA isa)
   1600 {
   1601     ObjCLanguageRuntime::ClassDescriptorSP class_descriptor_sp;
   1602     if (m_non_pointer_isa_cache_ap.get())
   1603         class_descriptor_sp = m_non_pointer_isa_cache_ap->GetClassDescriptor(isa);
   1604     if (!class_descriptor_sp)
   1605         class_descriptor_sp = ObjCLanguageRuntime::GetClassDescriptorFromISA(isa);
   1606     return class_descriptor_sp;
   1607 }
   1608 
   1609 ObjCLanguageRuntime::ClassDescriptorSP
   1610 AppleObjCRuntimeV2::GetClassDescriptor (ValueObject& valobj)
   1611 {
   1612     ClassDescriptorSP objc_class_sp;
   1613     // if we get an invalid VO (which might still happen when playing around
   1614     // with pointers returned by the expression parser, don't consider this
   1615     // a valid ObjC object)
   1616     if (valobj.GetClangType().IsValid())
   1617     {
   1618         addr_t isa_pointer = valobj.GetPointerValue();
   1619 
   1620         // tagged pointer
   1621         if (IsTaggedPointer(isa_pointer))
   1622         {
   1623             return m_tagged_pointer_vendor_ap->GetClassDescriptor(isa_pointer);
   1624         }
   1625         else
   1626         {
   1627             ExecutionContext exe_ctx (valobj.GetExecutionContextRef());
   1628 
   1629             Process *process = exe_ctx.GetProcessPtr();
   1630             if (process)
   1631             {
   1632                 Error error;
   1633                 ObjCISA isa = process->ReadPointerFromMemory(isa_pointer, error);
   1634                 if (isa != LLDB_INVALID_ADDRESS)
   1635                 {
   1636                     objc_class_sp = ObjCLanguageRuntime::GetClassDescriptorFromISA (isa);
   1637                     if (isa && !objc_class_sp)
   1638                     {
   1639                         Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
   1640                         if (log)
   1641                             log->Printf("0x%" PRIx64 ": AppleObjCRuntimeV2::GetClassDescriptor() ISA was not in class descriptor cache 0x%" PRIx64,
   1642                                         isa_pointer,
   1643                                         isa);
   1644                     }
   1645                 }
   1646             }
   1647         }
   1648     }
   1649     return objc_class_sp;
   1650 }
   1651 
   1652 lldb::addr_t
   1653 AppleObjCRuntimeV2::GetISAHashTablePointer ()
   1654 {
   1655     if (m_isa_hash_table_ptr == LLDB_INVALID_ADDRESS)
   1656     {
   1657         Process *process = GetProcess();
   1658 
   1659         ModuleSP objc_module_sp(GetObjCModule());
   1660 
   1661         if (!objc_module_sp)
   1662             return LLDB_INVALID_ADDRESS;
   1663 
   1664         static ConstString g_gdb_objc_realized_classes("gdb_objc_realized_classes");
   1665 
   1666         const Symbol *symbol = objc_module_sp->FindFirstSymbolWithNameAndType(g_gdb_objc_realized_classes, lldb::eSymbolTypeData);
   1667         if (symbol)
   1668         {
   1669             lldb::addr_t gdb_objc_realized_classes_ptr = symbol->GetAddress().GetLoadAddress(&process->GetTarget());
   1670 
   1671             if (gdb_objc_realized_classes_ptr != LLDB_INVALID_ADDRESS)
   1672             {
   1673                 Error error;
   1674                 m_isa_hash_table_ptr = process->ReadPointerFromMemory(gdb_objc_realized_classes_ptr, error);
   1675             }
   1676         }
   1677     }
   1678     return m_isa_hash_table_ptr;
   1679 }
   1680 
   1681 bool
   1682 AppleObjCRuntimeV2::UpdateISAToDescriptorMapDynamic(RemoteNXMapTable &hash_table)
   1683 {
   1684     Process *process = GetProcess();
   1685 
   1686     if (process == NULL)
   1687         return false;
   1688 
   1689     Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
   1690 
   1691     ExecutionContext exe_ctx;
   1692 
   1693     ThreadSP thread_sp = process->GetThreadList().GetSelectedThread();
   1694 
   1695     if (!thread_sp)
   1696         return false;
   1697 
   1698     thread_sp->CalculateExecutionContext(exe_ctx);
   1699     ClangASTContext *ast = process->GetTarget().GetScratchClangASTContext();
   1700 
   1701     if (!ast)
   1702         return false;
   1703 
   1704     Address function_address;
   1705 
   1706     StreamString errors;
   1707 
   1708     const uint32_t addr_size = process->GetAddressByteSize();
   1709 
   1710     Error err;
   1711 
   1712     // Read the total number of classes from the hash table
   1713     const uint32_t num_classes = hash_table.GetCount();
   1714     if (num_classes == 0)
   1715     {
   1716         if (log)
   1717             log->Printf ("No dynamic classes found in gdb_objc_realized_classes.");
   1718         return false;
   1719     }
   1720 
   1721     // Make some types for our arguments
   1722     ClangASTType clang_uint32_t_type = ast->GetBuiltinTypeForEncodingAndBitSize(eEncodingUint, 32);
   1723     ClangASTType clang_void_pointer_type = ast->GetBasicType(eBasicTypeVoid).GetPointerType();
   1724 
   1725     if (!m_get_class_info_code.get())
   1726     {
   1727         m_get_class_info_code.reset (new ClangUtilityFunction (g_get_dynamic_class_info_body,
   1728                                                                g_get_dynamic_class_info_name));
   1729 
   1730         errors.Clear();
   1731 
   1732         if (!m_get_class_info_code->Install(errors, exe_ctx))
   1733         {
   1734             if (log)
   1735                 log->Printf ("Failed to install implementation lookup: %s.", errors.GetData());
   1736             m_get_class_info_code.reset();
   1737         }
   1738     }
   1739 
   1740     if (m_get_class_info_code.get())
   1741         function_address.SetOffset(m_get_class_info_code->StartAddress());
   1742     else
   1743         return false;
   1744 
   1745     ValueList arguments;
   1746 
   1747     // Next make the runner function for our implementation utility function.
   1748     if (!m_get_class_info_function.get())
   1749     {
   1750         Value value;
   1751         value.SetValueType (Value::eValueTypeScalar);
   1752 //        value.SetContext (Value::eContextTypeClangType, clang_void_pointer_type);
   1753         value.SetClangType (clang_void_pointer_type);
   1754         arguments.PushValue (value);
   1755         arguments.PushValue (value);
   1756 
   1757         value.SetValueType (Value::eValueTypeScalar);
   1758 //        value.SetContext (Value::eContextTypeClangType, clang_uint32_t_type);
   1759         value.SetClangType (clang_uint32_t_type);
   1760         arguments.PushValue (value);
   1761 
   1762         m_get_class_info_function.reset(new ClangFunction (*m_process,
   1763                                                            clang_uint32_t_type,
   1764                                                            function_address,
   1765                                                            arguments));
   1766 
   1767         if (m_get_class_info_function.get() == NULL)
   1768             return false;
   1769 
   1770         errors.Clear();
   1771 
   1772         unsigned num_errors = m_get_class_info_function->CompileFunction(errors);
   1773         if (num_errors)
   1774         {
   1775             if (log)
   1776                 log->Printf ("Error compiling function: \"%s\".", errors.GetData());
   1777             return false;
   1778         }
   1779 
   1780         errors.Clear();
   1781 
   1782         if (!m_get_class_info_function->WriteFunctionWrapper(exe_ctx, errors))
   1783         {
   1784             if (log)
   1785                 log->Printf ("Error Inserting function: \"%s\".", errors.GetData());
   1786             return false;
   1787         }
   1788     }
   1789     else
   1790     {
   1791         arguments = m_get_class_info_function->GetArgumentValues ();
   1792     }
   1793 
   1794     const uint32_t class_info_byte_size = addr_size + 4;
   1795     const uint32_t class_infos_byte_size = num_classes * class_info_byte_size;
   1796     lldb::addr_t class_infos_addr = process->AllocateMemory(class_infos_byte_size,
   1797                                                             ePermissionsReadable | ePermissionsWritable,
   1798                                                             err);
   1799 
   1800     if (class_infos_addr == LLDB_INVALID_ADDRESS)
   1801         return false;
   1802 
   1803     Mutex::Locker locker(m_get_class_info_args_mutex);
   1804 
   1805     // Fill in our function argument values
   1806     arguments.GetValueAtIndex(0)->GetScalar() = hash_table.GetTableLoadAddress();
   1807     arguments.GetValueAtIndex(1)->GetScalar() = class_infos_addr;
   1808     arguments.GetValueAtIndex(2)->GetScalar() = class_infos_byte_size;
   1809 
   1810     bool success = false;
   1811 
   1812     errors.Clear();
   1813 
   1814     // Write our function arguments into the process so we can run our function
   1815     if (m_get_class_info_function->WriteFunctionArguments (exe_ctx,
   1816                                                            m_get_class_info_args,
   1817                                                            function_address,
   1818                                                            arguments,
   1819                                                            errors))
   1820     {
   1821         bool stop_others = true;
   1822         bool try_all_threads = false;
   1823         bool unwind_on_error = true;
   1824         bool ignore_breakpoints = true;
   1825 
   1826         Value return_value;
   1827         return_value.SetValueType (Value::eValueTypeScalar);
   1828         //return_value.SetContext (Value::eContextTypeClangType, clang_uint32_t_type);
   1829         return_value.SetClangType (clang_uint32_t_type);
   1830         return_value.GetScalar() = 0;
   1831 
   1832         errors.Clear();
   1833 
   1834         // Run the function
   1835         ExecutionResults results = m_get_class_info_function->ExecuteFunction (exe_ctx,
   1836                                                                                &m_get_class_info_args,
   1837                                                                                errors,
   1838                                                                                stop_others,
   1839                                                                                UTILITY_FUNCTION_TIMEOUT_USEC,
   1840                                                                                try_all_threads,
   1841                                                                                unwind_on_error,
   1842                                                                                ignore_breakpoints,
   1843                                                                                return_value);
   1844 
   1845         if (results == eExecutionCompleted)
   1846         {
   1847             // The result is the number of ClassInfo structures that were filled in
   1848             uint32_t num_class_infos = return_value.GetScalar().ULong();
   1849             if (log)
   1850                 log->Printf("Discovered %u ObjC classes\n",num_class_infos);
   1851             if (num_class_infos > 0)
   1852             {
   1853                 // Read the ClassInfo structures
   1854                 DataBufferHeap buffer (num_class_infos * class_info_byte_size, 0);
   1855                 if (process->ReadMemory(class_infos_addr, buffer.GetBytes(), buffer.GetByteSize(), err) == buffer.GetByteSize())
   1856                 {
   1857                     DataExtractor class_infos_data (buffer.GetBytes(),
   1858                                                     buffer.GetByteSize(),
   1859                                                     process->GetByteOrder(),
   1860                                                     addr_size);
   1861                     ParseClassInfoArray (class_infos_data, num_class_infos);
   1862                 }
   1863             }
   1864             success = true;
   1865         }
   1866         else
   1867         {
   1868             if (log)
   1869                 log->Printf("Error evaluating our find class name function: %s.\n", errors.GetData());
   1870         }
   1871     }
   1872     else
   1873     {
   1874         if (log)
   1875             log->Printf ("Error writing function arguments: \"%s\".", errors.GetData());
   1876     }
   1877 
   1878     // Deallocate the memory we allocated for the ClassInfo array
   1879     process->DeallocateMemory(class_infos_addr);
   1880 
   1881     return success;
   1882 }
   1883 
   1884 void
   1885 AppleObjCRuntimeV2::ParseClassInfoArray (const DataExtractor &data, uint32_t num_class_infos)
   1886 {
   1887     // Parses an array of "num_class_infos" packed ClassInfo structures:
   1888     //
   1889     //    struct ClassInfo
   1890     //    {
   1891     //        Class isa;
   1892     //        uint32_t hash;
   1893     //    } __attribute__((__packed__));
   1894 
   1895     Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
   1896 
   1897     // Iterate through all ClassInfo structures
   1898     lldb::offset_t offset = 0;
   1899     for (uint32_t i=0; i<num_class_infos; ++i)
   1900     {
   1901         ObjCISA isa = data.GetPointer(&offset);
   1902 
   1903         if (isa == 0)
   1904         {
   1905             if (log)
   1906                 log->Printf("AppleObjCRuntimeV2 found NULL isa, ignoring this class info");
   1907             continue;
   1908         }
   1909         // Check if we already know about this ISA, if we do, the info will
   1910         // never change, so we can just skip it.
   1911         if (ISAIsCached(isa))
   1912         {
   1913             offset += 4;
   1914         }
   1915         else
   1916         {
   1917             // Read the 32 bit hash for the class name
   1918             const uint32_t name_hash = data.GetU32(&offset);
   1919             ClassDescriptorSP descriptor_sp (new ClassDescriptorV2(*this, isa, NULL));
   1920             AddClass (isa, descriptor_sp, name_hash);
   1921             if (log && log->GetVerbose())
   1922                 log->Printf("AppleObjCRuntimeV2 added isa=0x%" PRIx64 ", hash=0x%8.8x", isa, name_hash);
   1923         }
   1924     }
   1925 }
   1926 
   1927 bool
   1928 AppleObjCRuntimeV2::UpdateISAToDescriptorMapSharedCache()
   1929 {
   1930     Process *process = GetProcess();
   1931 
   1932     if (process == NULL)
   1933         return false;
   1934 
   1935     Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
   1936 
   1937     ExecutionContext exe_ctx;
   1938 
   1939     ThreadSP thread_sp = process->GetThreadList().GetSelectedThread();
   1940 
   1941     if (!thread_sp)
   1942         return false;
   1943 
   1944     thread_sp->CalculateExecutionContext(exe_ctx);
   1945     ClangASTContext *ast = process->GetTarget().GetScratchClangASTContext();
   1946 
   1947     if (!ast)
   1948         return false;
   1949 
   1950     Address function_address;
   1951 
   1952     StreamString errors;
   1953 
   1954     const uint32_t addr_size = process->GetAddressByteSize();
   1955 
   1956     Error err;
   1957 
   1958     const lldb::addr_t objc_opt_ptr = GetSharedCacheReadOnlyAddress();
   1959 
   1960     if (objc_opt_ptr == LLDB_INVALID_ADDRESS)
   1961         return false;
   1962 
   1963     // Read the total number of classes from the hash table
   1964     const uint32_t num_classes = 16*1024;
   1965     if (num_classes == 0)
   1966     {
   1967         if (log)
   1968             log->Printf ("No dynamic classes found in gdb_objc_realized_classes_addr.");
   1969         return false;
   1970     }
   1971 
   1972     // Make some types for our arguments
   1973     ClangASTType clang_uint32_t_type = ast->GetBuiltinTypeForEncodingAndBitSize(eEncodingUint, 32);
   1974     ClangASTType clang_void_pointer_type = ast->GetBasicType(eBasicTypeVoid).GetPointerType();
   1975 
   1976     if (!m_get_shared_cache_class_info_code.get())
   1977     {
   1978         m_get_shared_cache_class_info_code.reset (new ClangUtilityFunction (g_get_shared_cache_class_info_body,
   1979                                                                             g_get_shared_cache_class_info_name));
   1980 
   1981         errors.Clear();
   1982 
   1983         if (!m_get_shared_cache_class_info_code->Install(errors, exe_ctx))
   1984         {
   1985             if (log)
   1986                 log->Printf ("Failed to install implementation lookup: %s.", errors.GetData());
   1987             m_get_shared_cache_class_info_code.reset();
   1988         }
   1989     }
   1990 
   1991     if (m_get_shared_cache_class_info_code.get())
   1992         function_address.SetOffset(m_get_shared_cache_class_info_code->StartAddress());
   1993     else
   1994         return false;
   1995 
   1996     ValueList arguments;
   1997 
   1998     // Next make the runner function for our implementation utility function.
   1999     if (!m_get_shared_cache_class_info_function.get())
   2000     {
   2001         Value value;
   2002         value.SetValueType (Value::eValueTypeScalar);
   2003         //value.SetContext (Value::eContextTypeClangType, clang_void_pointer_type);
   2004         value.SetClangType (clang_void_pointer_type);
   2005         arguments.PushValue (value);
   2006         arguments.PushValue (value);
   2007 
   2008         value.SetValueType (Value::eValueTypeScalar);
   2009         //value.SetContext (Value::eContextTypeClangType, clang_uint32_t_type);
   2010         value.SetClangType (clang_uint32_t_type);
   2011         arguments.PushValue (value);
   2012 
   2013         m_get_shared_cache_class_info_function.reset(new ClangFunction (*m_process,
   2014                                                                         clang_uint32_t_type,
   2015                                                                         function_address,
   2016                                                                         arguments));
   2017 
   2018         if (m_get_shared_cache_class_info_function.get() == NULL)
   2019             return false;
   2020 
   2021         errors.Clear();
   2022 
   2023         unsigned num_errors = m_get_shared_cache_class_info_function->CompileFunction(errors);
   2024         if (num_errors)
   2025         {
   2026             if (log)
   2027                 log->Printf ("Error compiling function: \"%s\".", errors.GetData());
   2028             return false;
   2029         }
   2030 
   2031         errors.Clear();
   2032 
   2033         if (!m_get_shared_cache_class_info_function->WriteFunctionWrapper(exe_ctx, errors))
   2034         {
   2035             if (log)
   2036                 log->Printf ("Error Inserting function: \"%s\".", errors.GetData());
   2037             return false;
   2038         }
   2039     }
   2040     else
   2041     {
   2042         arguments = m_get_shared_cache_class_info_function->GetArgumentValues ();
   2043     }
   2044 
   2045     const uint32_t class_info_byte_size = addr_size + 4;
   2046     const uint32_t class_infos_byte_size = num_classes * class_info_byte_size;
   2047     lldb::addr_t class_infos_addr = process->AllocateMemory (class_infos_byte_size,
   2048                                                              ePermissionsReadable | ePermissionsWritable,
   2049                                                              err);
   2050 
   2051     if (class_infos_addr == LLDB_INVALID_ADDRESS)
   2052         return false;
   2053 
   2054     Mutex::Locker locker(m_get_shared_cache_class_info_args_mutex);
   2055 
   2056     // Fill in our function argument values
   2057     arguments.GetValueAtIndex(0)->GetScalar() = objc_opt_ptr;
   2058     arguments.GetValueAtIndex(1)->GetScalar() = class_infos_addr;
   2059     arguments.GetValueAtIndex(2)->GetScalar() = class_infos_byte_size;
   2060 
   2061     bool success = false;
   2062 
   2063     errors.Clear();
   2064 
   2065     // Write our function arguments into the process so we can run our function
   2066     if (m_get_shared_cache_class_info_function->WriteFunctionArguments (exe_ctx,
   2067                                                                         m_get_shared_cache_class_info_args,
   2068                                                                         function_address,
   2069                                                                         arguments,
   2070                                                                         errors))
   2071     {
   2072         bool stop_others = true;
   2073         bool try_all_threads = false;
   2074         bool unwind_on_error = true;
   2075         bool ignore_breakpoints = true;
   2076 
   2077         Value return_value;
   2078         return_value.SetValueType (Value::eValueTypeScalar);
   2079         //return_value.SetContext (Value::eContextTypeClangType, clang_uint32_t_type);
   2080         return_value.SetClangType (clang_uint32_t_type);
   2081         return_value.GetScalar() = 0;
   2082 
   2083         errors.Clear();
   2084 
   2085         // Run the function
   2086         ExecutionResults results = m_get_shared_cache_class_info_function->ExecuteFunction (exe_ctx,
   2087                                                                                             &m_get_shared_cache_class_info_args,
   2088                                                                                             errors,
   2089                                                                                             stop_others,
   2090                                                                                             UTILITY_FUNCTION_TIMEOUT_USEC,
   2091                                                                                             try_all_threads,
   2092                                                                                             unwind_on_error,
   2093                                                                                             ignore_breakpoints,
   2094                                                                                             return_value);
   2095 
   2096         if (results == eExecutionCompleted)
   2097         {
   2098             // The result is the number of ClassInfo structures that were filled in
   2099             uint32_t num_class_infos = return_value.GetScalar().ULong();
   2100             if (log)
   2101                 log->Printf("Discovered %u ObjC classes in shared cache\n",num_class_infos);
   2102             if (num_class_infos > 0)
   2103             {
   2104                 // Read the ClassInfo structures
   2105                 DataBufferHeap buffer (num_class_infos * class_info_byte_size, 0);
   2106                 if (process->ReadMemory(class_infos_addr,
   2107                                         buffer.GetBytes(),
   2108                                         buffer.GetByteSize(),
   2109                                         err) == buffer.GetByteSize())
   2110                 {
   2111                     DataExtractor class_infos_data (buffer.GetBytes(),
   2112                                                     buffer.GetByteSize(),
   2113                                                     process->GetByteOrder(),
   2114                                                     addr_size);
   2115 
   2116                     ParseClassInfoArray (class_infos_data, num_class_infos);
   2117                 }
   2118             }
   2119             success = true;
   2120         }
   2121         else
   2122         {
   2123             if (log)
   2124                 log->Printf("Error evaluating our find class name function: %s.\n", errors.GetData());
   2125         }
   2126     }
   2127     else
   2128     {
   2129         if (log)
   2130             log->Printf ("Error writing function arguments: \"%s\".", errors.GetData());
   2131     }
   2132 
   2133     // Deallocate the memory we allocated for the ClassInfo array
   2134     process->DeallocateMemory(class_infos_addr);
   2135 
   2136     return success;
   2137 }
   2138 
   2139 
   2140 bool
   2141 AppleObjCRuntimeV2::UpdateISAToDescriptorMapFromMemory (RemoteNXMapTable &hash_table)
   2142 {
   2143     Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
   2144 
   2145     Process *process = GetProcess();
   2146 
   2147     if (process == NULL)
   2148         return false;
   2149 
   2150     uint32_t num_map_table_isas = 0;
   2151 
   2152     ModuleSP objc_module_sp(GetObjCModule());
   2153 
   2154     if (objc_module_sp)
   2155     {
   2156         for (RemoteNXMapTable::element elt : hash_table)
   2157         {
   2158             ++num_map_table_isas;
   2159 
   2160             if (ISAIsCached(elt.second))
   2161                 continue;
   2162 
   2163             ClassDescriptorSP descriptor_sp = ClassDescriptorSP(new ClassDescriptorV2(*this, elt.second, elt.first.AsCString()));
   2164 
   2165             if (log && log->GetVerbose())
   2166                 log->Printf("AppleObjCRuntimeV2 added (ObjCISA)0x%" PRIx64 " (%s) from dynamic table to isa->descriptor cache", elt.second, elt.first.AsCString());
   2167 
   2168             AddClass (elt.second, descriptor_sp, elt.first.AsCString());
   2169         }
   2170     }
   2171 
   2172     return num_map_table_isas > 0;
   2173 }
   2174 
   2175 lldb::addr_t
   2176 AppleObjCRuntimeV2::GetSharedCacheReadOnlyAddress()
   2177 {
   2178     Process *process = GetProcess();
   2179 
   2180     if (process)
   2181     {
   2182         ModuleSP objc_module_sp(GetObjCModule());
   2183 
   2184         if (objc_module_sp)
   2185         {
   2186             ObjectFile *objc_object = objc_module_sp->GetObjectFile();
   2187 
   2188             if (objc_object)
   2189             {
   2190                 SectionList *section_list = objc_module_sp->GetSectionList();
   2191 
   2192                 if (section_list)
   2193                 {
   2194                     SectionSP text_segment_sp (section_list->FindSectionByName(ConstString("__TEXT")));
   2195 
   2196                     if (text_segment_sp)
   2197                     {
   2198                         SectionSP objc_opt_section_sp (text_segment_sp->GetChildren().FindSectionByName(ConstString("__objc_opt_ro")));
   2199 
   2200                         if (objc_opt_section_sp)
   2201                         {
   2202                             return objc_opt_section_sp->GetLoadBaseAddress(&process->GetTarget());
   2203                         }
   2204                     }
   2205                 }
   2206             }
   2207         }
   2208     }
   2209     return LLDB_INVALID_ADDRESS;
   2210 }
   2211 
   2212 void
   2213 AppleObjCRuntimeV2::UpdateISAToDescriptorMapIfNeeded()
   2214 {
   2215     Timer scoped_timer (__PRETTY_FUNCTION__, __PRETTY_FUNCTION__);
   2216 
   2217     // Else we need to check with our process to see when the map was updated.
   2218     Process *process = GetProcess();
   2219 
   2220     if (process)
   2221     {
   2222         RemoteNXMapTable hash_table;
   2223 
   2224         // Update the process stop ID that indicates the last time we updated the
   2225         // map, wether it was successful or not.
   2226         m_isa_to_descriptor_stop_id = process->GetStopID();
   2227 
   2228         if (!m_hash_signature.NeedsUpdate(process, this, hash_table))
   2229             return;
   2230 
   2231         m_hash_signature.UpdateSignature (hash_table);
   2232 
   2233         // Grab the dynamicly loaded objc classes from the hash table in memory
   2234         UpdateISAToDescriptorMapDynamic(hash_table);
   2235 
   2236         // Now get the objc classes that are baked into the Objective C runtime
   2237         // in the shared cache, but only once per process as this data never
   2238         // changes
   2239         if (!m_loaded_objc_opt)
   2240             UpdateISAToDescriptorMapSharedCache();
   2241     }
   2242     else
   2243     {
   2244         m_isa_to_descriptor_stop_id = UINT32_MAX;
   2245     }
   2246 }
   2247 
   2248 
   2249 // TODO: should we have a transparent_kvo parameter here to say if we
   2250 // want to replace the KVO swizzled class with the actual user-level type?
   2251 ConstString
   2252 AppleObjCRuntimeV2::GetActualTypeName(ObjCLanguageRuntime::ObjCISA isa)
   2253 {
   2254     if (isa == g_objc_Tagged_ISA)
   2255     {
   2256         static const ConstString g_objc_tagged_isa_name ("_lldb_Tagged_ObjC_ISA");
   2257         return g_objc_tagged_isa_name;
   2258     }
   2259     if (isa == g_objc_Tagged_ISA_NSAtom)
   2260     {
   2261         static const ConstString g_objc_tagged_isa_nsatom_name ("NSAtom");
   2262         return g_objc_tagged_isa_nsatom_name;
   2263     }
   2264     if (isa == g_objc_Tagged_ISA_NSNumber)
   2265     {
   2266         static const ConstString g_objc_tagged_isa_nsnumber_name ("NSNumber");
   2267         return g_objc_tagged_isa_nsnumber_name;
   2268     }
   2269     if (isa == g_objc_Tagged_ISA_NSDateTS)
   2270     {
   2271         static const ConstString g_objc_tagged_isa_nsdatets_name ("NSDateTS");
   2272         return g_objc_tagged_isa_nsdatets_name;
   2273     }
   2274     if (isa == g_objc_Tagged_ISA_NSManagedObject)
   2275     {
   2276         static const ConstString g_objc_tagged_isa_nsmanagedobject_name ("NSManagedObject");
   2277         return g_objc_tagged_isa_nsmanagedobject_name;
   2278     }
   2279     if (isa == g_objc_Tagged_ISA_NSDate)
   2280     {
   2281         static const ConstString g_objc_tagged_isa_nsdate_name ("NSDate");
   2282         return g_objc_tagged_isa_nsdate_name;
   2283     }
   2284     return ObjCLanguageRuntime::GetActualTypeName(isa);
   2285 }
   2286 
   2287 TypeVendor *
   2288 AppleObjCRuntimeV2::GetTypeVendor()
   2289 {
   2290     if (!m_type_vendor_ap.get())
   2291         m_type_vendor_ap.reset(new AppleObjCTypeVendor(*this));
   2292 
   2293     return m_type_vendor_ap.get();
   2294 }
   2295 
   2296 lldb::addr_t
   2297 AppleObjCRuntimeV2::LookupRuntimeSymbol (const ConstString &name)
   2298 {
   2299     lldb::addr_t ret = LLDB_INVALID_ADDRESS;
   2300 
   2301     const char *name_cstr = name.AsCString();
   2302 
   2303     if (name_cstr)
   2304     {
   2305         llvm::StringRef name_strref(name_cstr);
   2306 
   2307         static const llvm::StringRef ivar_prefix("OBJC_IVAR_$_");
   2308         static const llvm::StringRef class_prefix("OBJC_CLASS_$_");
   2309 
   2310         if (name_strref.startswith(ivar_prefix))
   2311         {
   2312             llvm::StringRef ivar_skipped_prefix = name_strref.substr(ivar_prefix.size());
   2313             std::pair<llvm::StringRef, llvm::StringRef> class_and_ivar = ivar_skipped_prefix.split('.');
   2314 
   2315             if (class_and_ivar.first.size() && class_and_ivar.second.size())
   2316             {
   2317                 const ConstString class_name_cs(class_and_ivar.first);
   2318                 ClassDescriptorSP descriptor = ObjCLanguageRuntime::GetClassDescriptorFromClassName(class_name_cs);
   2319 
   2320                 if (descriptor)
   2321                 {
   2322                     const ConstString ivar_name_cs(class_and_ivar.second);
   2323                     const char *ivar_name_cstr = ivar_name_cs.AsCString();
   2324 
   2325                     auto ivar_func = [&ret, ivar_name_cstr](const char *name, const char *type, lldb::addr_t offset_addr, uint64_t size) -> lldb::addr_t
   2326                     {
   2327                         if (!strcmp(name, ivar_name_cstr))
   2328                         {
   2329                             ret = offset_addr;
   2330                             return true;
   2331                         }
   2332                         return false;
   2333                     };
   2334 
   2335                     descriptor->Describe(std::function<void (ObjCISA)>(nullptr),
   2336                                          std::function<bool (const char *, const char *)>(nullptr),
   2337                                          std::function<bool (const char *, const char *)>(nullptr),
   2338                                          ivar_func);
   2339                 }
   2340             }
   2341         }
   2342         else if (name_strref.startswith(class_prefix))
   2343         {
   2344             llvm::StringRef class_skipped_prefix = name_strref.substr(class_prefix.size());
   2345             const ConstString class_name_cs(class_skipped_prefix);
   2346             ClassDescriptorSP descriptor = GetClassDescriptorFromClassName(class_name_cs);
   2347 
   2348             if (descriptor)
   2349                 ret = descriptor->GetISA();
   2350         }
   2351     }
   2352 
   2353     return ret;
   2354 }
   2355 
   2356 AppleObjCRuntimeV2::NonPointerISACache*
   2357 AppleObjCRuntimeV2::NonPointerISACache::CreateInstance (AppleObjCRuntimeV2& runtime, const lldb::ModuleSP& objc_module_sp)
   2358 {
   2359     Process* process(runtime.GetProcess());
   2360 
   2361     Error error;
   2362 
   2363     auto objc_debug_isa_magic_mask = ExtractRuntimeGlobalSymbol(process,
   2364                                                                 ConstString("objc_debug_isa_magic_mask"),
   2365                                                                 objc_module_sp,
   2366                                                                 error);
   2367     if (error.Fail())
   2368         return NULL;
   2369 
   2370     auto objc_debug_isa_magic_value = ExtractRuntimeGlobalSymbol(process,
   2371                                                                  ConstString("objc_debug_isa_magic_value"),
   2372                                                                  objc_module_sp,
   2373                                                                  error);
   2374     if (error.Fail())
   2375         return NULL;
   2376 
   2377     auto objc_debug_isa_class_mask = ExtractRuntimeGlobalSymbol(process,
   2378                                                                 ConstString("objc_debug_isa_class_mask"),
   2379                                                                 objc_module_sp,
   2380                                                                 error);
   2381     if (error.Fail())
   2382         return NULL;
   2383 
   2384     // we might want to have some rules to outlaw these other values (e.g if the mask is zero but the value is non-zero, ...)
   2385 
   2386     return new NonPointerISACache(runtime,
   2387                                   objc_debug_isa_class_mask,
   2388                                   objc_debug_isa_magic_mask,
   2389                                   objc_debug_isa_magic_value);
   2390 }
   2391 
   2392 AppleObjCRuntimeV2::TaggedPointerVendor*
   2393 AppleObjCRuntimeV2::TaggedPointerVendor::CreateInstance (AppleObjCRuntimeV2& runtime, const lldb::ModuleSP& objc_module_sp)
   2394 {
   2395     Process* process(runtime.GetProcess());
   2396 
   2397     Error error;
   2398 
   2399     auto objc_debug_taggedpointer_mask = ExtractRuntimeGlobalSymbol(process,
   2400                                                                     ConstString("objc_debug_taggedpointer_mask"),
   2401                                                                     objc_module_sp,
   2402                                                                     error);
   2403     if (error.Fail())
   2404         return new TaggedPointerVendorLegacy(runtime);
   2405 
   2406     auto objc_debug_taggedpointer_slot_shift = ExtractRuntimeGlobalSymbol(process,
   2407                                                                           ConstString("objc_debug_taggedpointer_slot_shift"),
   2408                                                                           objc_module_sp,
   2409                                                                           error,
   2410                                                                           true,
   2411                                                                           4);
   2412     if (error.Fail())
   2413         return new TaggedPointerVendorLegacy(runtime);
   2414 
   2415     auto objc_debug_taggedpointer_slot_mask = ExtractRuntimeGlobalSymbol(process,
   2416                                                                           ConstString("objc_debug_taggedpointer_slot_mask"),
   2417                                                                           objc_module_sp,
   2418                                                                           error,
   2419                                                                           true,
   2420                                                                           4);
   2421     if (error.Fail())
   2422         return new TaggedPointerVendorLegacy(runtime);
   2423 
   2424     auto objc_debug_taggedpointer_payload_lshift = ExtractRuntimeGlobalSymbol(process,
   2425                                                                               ConstString("objc_debug_taggedpointer_payload_lshift"),
   2426                                                                               objc_module_sp,
   2427                                                                               error,
   2428                                                                               true,
   2429                                                                               4);
   2430     if (error.Fail())
   2431         return new TaggedPointerVendorLegacy(runtime);
   2432 
   2433     auto objc_debug_taggedpointer_payload_rshift = ExtractRuntimeGlobalSymbol(process,
   2434                                                                               ConstString("objc_debug_taggedpointer_payload_rshift"),
   2435                                                                               objc_module_sp,
   2436                                                                               error,
   2437                                                                               true,
   2438                                                                               4);
   2439     if (error.Fail())
   2440         return new TaggedPointerVendorLegacy(runtime);
   2441 
   2442     auto objc_debug_taggedpointer_classes = ExtractRuntimeGlobalSymbol(process,
   2443                                                                        ConstString("objc_debug_taggedpointer_classes"),
   2444                                                                        objc_module_sp,
   2445                                                                        error,
   2446                                                                        false);
   2447     if (error.Fail())
   2448         return new TaggedPointerVendorLegacy(runtime);
   2449 
   2450 
   2451     // we might want to have some rules to outlaw these values (e.g if the table's address is zero)
   2452 
   2453     return new TaggedPointerVendorRuntimeAssisted(runtime,
   2454                                                   objc_debug_taggedpointer_mask,
   2455                                                   objc_debug_taggedpointer_slot_shift,
   2456                                                   objc_debug_taggedpointer_slot_mask,
   2457                                                   objc_debug_taggedpointer_payload_lshift,
   2458                                                   objc_debug_taggedpointer_payload_rshift,
   2459                                                   objc_debug_taggedpointer_classes);
   2460 }
   2461 
   2462 bool
   2463 AppleObjCRuntimeV2::TaggedPointerVendorLegacy::IsPossibleTaggedPointer (lldb::addr_t ptr)
   2464 {
   2465     return (ptr & 1);
   2466 }
   2467 
   2468 // we use the version of Foundation to make assumptions about the ObjC runtime on a target
   2469 uint32_t
   2470 AppleObjCRuntimeV2::TaggedPointerVendorLegacy::GetFoundationVersion (Target &target)
   2471 {
   2472     const ModuleList& modules = target.GetImages();
   2473     uint32_t major = UINT32_MAX;
   2474     for (uint32_t idx = 0; idx < modules.GetSize(); idx++)
   2475     {
   2476         lldb::ModuleSP module_sp = modules.GetModuleAtIndex(idx);
   2477         if (!module_sp)
   2478             continue;
   2479         if (strcmp(module_sp->GetFileSpec().GetFilename().AsCString(""),"Foundation") == 0)
   2480         {
   2481             module_sp->GetVersion(&major,1);
   2482             break;
   2483         }
   2484     }
   2485     return major;
   2486 }
   2487 
   2488 ObjCLanguageRuntime::ClassDescriptorSP
   2489 AppleObjCRuntimeV2::TaggedPointerVendorLegacy::GetClassDescriptor (lldb::addr_t ptr)
   2490 {
   2491     if (!IsPossibleTaggedPointer(ptr))
   2492         return ObjCLanguageRuntime::ClassDescriptorSP();
   2493 
   2494     Process* process(m_runtime.GetProcess());
   2495 
   2496     if (m_Foundation_version == 0)
   2497         m_Foundation_version = GetFoundationVersion(process->GetTarget());
   2498 
   2499     if (m_Foundation_version == UINT32_MAX)
   2500         return ObjCLanguageRuntime::ClassDescriptorSP();
   2501 
   2502     uint64_t class_bits = (ptr & 0xE) >> 1;
   2503     ConstString name;
   2504 
   2505     // TODO: make a table
   2506     if (m_Foundation_version >= 900)
   2507     {
   2508         switch (class_bits)
   2509         {
   2510             case 0:
   2511                 name = ConstString("NSAtom");
   2512                 break;
   2513             case 3:
   2514                 name = ConstString("NSNumber");
   2515                 break;
   2516             case 4:
   2517                 name = ConstString("NSDateTS");
   2518                 break;
   2519             case 5:
   2520                 name = ConstString("NSManagedObject");
   2521                 break;
   2522             case 6:
   2523                 name = ConstString("NSDate");
   2524                 break;
   2525             default:
   2526                 return ObjCLanguageRuntime::ClassDescriptorSP();
   2527         }
   2528     }
   2529     else
   2530     {
   2531         switch (class_bits)
   2532         {
   2533             case 1:
   2534                 name = ConstString("NSNumber");
   2535                 break;
   2536             case 5:
   2537                 name = ConstString("NSManagedObject");
   2538                 break;
   2539             case 6:
   2540                 name = ConstString("NSDate");
   2541                 break;
   2542             case 7:
   2543                 name = ConstString("NSDateTS");
   2544                 break;
   2545             default:
   2546                 return ObjCLanguageRuntime::ClassDescriptorSP();
   2547         }
   2548     }
   2549     return ClassDescriptorSP(new ClassDescriptorV2Tagged(name,ptr));
   2550 }
   2551 
   2552 AppleObjCRuntimeV2::TaggedPointerVendorRuntimeAssisted::TaggedPointerVendorRuntimeAssisted (AppleObjCRuntimeV2& runtime,
   2553                                                                                             uint64_t objc_debug_taggedpointer_mask,
   2554                                                                                             uint32_t objc_debug_taggedpointer_slot_shift,
   2555                                                                                             uint32_t objc_debug_taggedpointer_slot_mask,
   2556                                                                                             uint32_t objc_debug_taggedpointer_payload_lshift,
   2557                                                                                             uint32_t objc_debug_taggedpointer_payload_rshift,
   2558                                                                                             lldb::addr_t objc_debug_taggedpointer_classes) :
   2559 TaggedPointerVendor(runtime),
   2560 m_cache(),
   2561 m_objc_debug_taggedpointer_mask(objc_debug_taggedpointer_mask),
   2562 m_objc_debug_taggedpointer_slot_shift(objc_debug_taggedpointer_slot_shift),
   2563 m_objc_debug_taggedpointer_slot_mask(objc_debug_taggedpointer_slot_mask),
   2564 m_objc_debug_taggedpointer_payload_lshift(objc_debug_taggedpointer_payload_lshift),
   2565 m_objc_debug_taggedpointer_payload_rshift(objc_debug_taggedpointer_payload_rshift),
   2566 m_objc_debug_taggedpointer_classes(objc_debug_taggedpointer_classes)
   2567 {
   2568 }
   2569 
   2570 bool
   2571 AppleObjCRuntimeV2::TaggedPointerVendorRuntimeAssisted::IsPossibleTaggedPointer (lldb::addr_t ptr)
   2572 {
   2573     return (ptr & m_objc_debug_taggedpointer_mask) != 0;
   2574 }
   2575 
   2576 ObjCLanguageRuntime::ClassDescriptorSP
   2577 AppleObjCRuntimeV2::TaggedPointerVendorRuntimeAssisted::GetClassDescriptor (lldb::addr_t ptr)
   2578 {
   2579     ClassDescriptorSP actual_class_descriptor_sp;
   2580     uint64_t data_payload;
   2581 
   2582     if (!IsPossibleTaggedPointer(ptr))
   2583         return ObjCLanguageRuntime::ClassDescriptorSP();
   2584 
   2585     uintptr_t slot = (ptr >> m_objc_debug_taggedpointer_slot_shift) & m_objc_debug_taggedpointer_slot_mask;
   2586 
   2587     CacheIterator iterator = m_cache.find(slot),
   2588     end = m_cache.end();
   2589     if (iterator != end)
   2590     {
   2591         actual_class_descriptor_sp = iterator->second;
   2592     }
   2593     else
   2594     {
   2595         Process* process(m_runtime.GetProcess());
   2596         uintptr_t slot_ptr = slot*process->GetAddressByteSize()+m_objc_debug_taggedpointer_classes;
   2597         Error error;
   2598         uintptr_t slot_data = process->ReadPointerFromMemory(slot_ptr, error);
   2599         if (error.Fail() || slot_data == 0 || slot_data == LLDB_INVALID_ADDRESS)
   2600             return nullptr;
   2601         actual_class_descriptor_sp = m_runtime.GetClassDescriptor(slot_data);
   2602         if (!actual_class_descriptor_sp)
   2603             return ObjCLanguageRuntime::ClassDescriptorSP();
   2604         m_cache[slot] = actual_class_descriptor_sp;
   2605     }
   2606 
   2607     data_payload = (((uint64_t)ptr << m_objc_debug_taggedpointer_payload_lshift) >> m_objc_debug_taggedpointer_payload_rshift);
   2608 
   2609     return ClassDescriptorSP(new ClassDescriptorV2Tagged(actual_class_descriptor_sp,data_payload));
   2610 }
   2611 
   2612 AppleObjCRuntimeV2::NonPointerISACache::NonPointerISACache (AppleObjCRuntimeV2& runtime,
   2613                                                             uint64_t objc_debug_isa_class_mask,
   2614                                                             uint64_t objc_debug_isa_magic_mask,
   2615                                                             uint64_t objc_debug_isa_magic_value) :
   2616 m_runtime(runtime),
   2617 m_cache(),
   2618 m_objc_debug_isa_class_mask(objc_debug_isa_class_mask),
   2619 m_objc_debug_isa_magic_mask(objc_debug_isa_magic_mask),
   2620 m_objc_debug_isa_magic_value(objc_debug_isa_magic_value)
   2621 {
   2622 }
   2623 
   2624 ObjCLanguageRuntime::ClassDescriptorSP
   2625 AppleObjCRuntimeV2::NonPointerISACache::GetClassDescriptor (ObjCISA isa)
   2626 {
   2627     ObjCISA real_isa = 0;
   2628     if (EvaluateNonPointerISA(isa, real_isa) == false)
   2629         return ObjCLanguageRuntime::ClassDescriptorSP();
   2630     auto cache_iter = m_cache.find(real_isa);
   2631     if (cache_iter != m_cache.end())
   2632         return cache_iter->second;
   2633     auto descriptor_sp = m_runtime.ObjCLanguageRuntime::GetClassDescriptorFromISA(real_isa);
   2634     if (descriptor_sp) // cache only positive matches since the table might grow
   2635         m_cache[real_isa] = descriptor_sp;
   2636     return descriptor_sp;
   2637 }
   2638 
   2639 bool
   2640 AppleObjCRuntimeV2::NonPointerISACache::EvaluateNonPointerISA (ObjCISA isa, ObjCISA& ret_isa)
   2641 {
   2642     if ( (isa & ~m_objc_debug_isa_class_mask) == 0)
   2643         return false;
   2644     if ( (isa & m_objc_debug_isa_magic_mask) == m_objc_debug_isa_magic_value)
   2645     {
   2646         ret_isa = isa & m_objc_debug_isa_class_mask;
   2647         return (ret_isa != 0); // this is a pointer so 0 is not a valid value
   2648     }
   2649     return false;
   2650 }
   2651