[Lldb-commits] [lldb] fc71a5c - [lldb] Support new objective-c hash table layout

Jonas Devlieghere via lldb-commits lldb-commits at lists.llvm.org
Fri Jun 11 10:26:21 PDT 2021


Author: Jonas Devlieghere
Date: 2021-06-11T10:26:16-07:00
New Revision: fc71a5c6e8e8bd28e43cf58faabad6e7e2fcc652

URL: https://github.com/llvm/llvm-project/commit/fc71a5c6e8e8bd28e43cf58faabad6e7e2fcc652
DIFF: https://github.com/llvm/llvm-project/commit/fc71a5c6e8e8bd28e43cf58faabad6e7e2fcc652.diff

LOG: [lldb] Support new objective-c hash table layout

Update LLDB for thew new Objective-C hash table layout in the dyld
shared cache found in macOS Monterey.

rdar://72863911

Added: 
    

Modified: 
    lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCClassDescriptorV2.cpp
    lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCClassDescriptorV2.h
    lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp
    lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.h

Removed: 
    


################################################################################
diff  --git a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCClassDescriptorV2.cpp b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCClassDescriptorV2.cpp
index c1082100f2746..405b8a6f16b77 100644
--- a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCClassDescriptorV2.cpp
+++ b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCClassDescriptorV2.cpp
@@ -252,6 +252,7 @@ bool ClassDescriptorV2::method_list_t::Read(Process *process,
 }
 
 bool ClassDescriptorV2::method_t::Read(Process *process, lldb::addr_t addr,
+                                       lldb::addr_t relative_selector_base_addr,
                                        bool is_small, bool has_direct_sel) {
   size_t ptr_size = process->GetAddressByteSize();
   size_t size = GetSize(process, is_small);
@@ -281,6 +282,8 @@ bool ClassDescriptorV2::method_t::Read(Process *process, lldb::addr_t addr,
                                                           0, error);
       if (!error.Success())
         return false;
+    } else if (relative_selector_base_addr != LLDB_INVALID_ADDRESS) {
+      m_name_ptr = relative_selector_base_addr + nameref_offset;
     }
     m_types_ptr = addr + 4 + types_offset;
     m_imp_ptr = addr + 8 + imp_offset;
@@ -389,14 +392,14 @@ bool ClassDescriptorV2::Describe(
     if (base_method_list->m_entsize != method_t::GetSize(process, is_small))
       return false;
 
-    std::unique_ptr<method_t> method;
-    method = std::make_unique<method_t>();
-
+    std::unique_ptr<method_t> method = std::make_unique<method_t>();
+    lldb::addr_t relative_selector_base_addr =
+        m_runtime.GetRelativeSelectorBaseAddr();
     for (uint32_t i = 0, e = base_method_list->m_count; i < e; ++i) {
       method->Read(process,
                    base_method_list->m_first_ptr +
                        (i * base_method_list->m_entsize),
-                   is_small, has_direct_selector);
+                   relative_selector_base_addr, is_small, has_direct_selector);
 
       if (instance_method_func(method->m_name.c_str(), method->m_types.c_str()))
         break;

diff  --git a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCClassDescriptorV2.h b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCClassDescriptorV2.h
index 16e94f6790841..60374498c8965 100644
--- a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCClassDescriptorV2.h
+++ b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCClassDescriptorV2.h
@@ -166,7 +166,8 @@ class ClassDescriptorV2 : public ObjCLanguageRuntime::ClassDescriptor {
              + field_size; // IMP imp;
     }
 
-    bool Read(Process *process, lldb::addr_t addr, bool, bool);
+    bool Read(Process *process, lldb::addr_t addr,
+              lldb::addr_t relative_method_lists_base_addr, bool, bool);
   };
 
   struct ivar_list_t {

diff  --git a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp
index 83f4356c3fb37..069368c8e058b 100644
--- a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp
+++ b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp
@@ -263,6 +263,12 @@ struct objc_classheader_t {
     int32_t hiOffset;
 };
 
+struct objc_classheader_v16_t {
+    uint64_t isDuplicate       : 1,
+             objectCacheOffset : 47, // Offset from the shared cache base
+             dylibObjCIndex    : 16;
+};
+
 struct objc_clsopt_t {
     uint32_t capacity;
     uint32_t occupied;
@@ -280,6 +286,22 @@ struct objc_clsopt_t {
     //  objc_classheader_t duplicateOffsets[duplicateCount];
 };
 
+struct objc_clsopt_v16_t {
+   uint32_t version;
+   uint32_t capacity;
+   uint32_t occupied;
+   uint32_t shift;
+   uint32_t mask;
+   uint64_t salt;
+   uint32_t scramble[256];
+   uint8_t  tab[0]; // tab[mask+1]
+   //  uint8_t checkbytes[capacity];
+   //  int32_t offset[capacity];
+   //  objc_classheader_t clsOffsets[capacity];
+   //  uint32_t duplicateCount;
+   //  objc_classheader_t duplicateOffsets[duplicateCount];
+};
+
 struct objc_opt_t {
     uint32_t version;
     int32_t selopt_offset;
@@ -295,6 +317,20 @@ struct objc_opt_v14_t {
     int32_t clsopt_offset;
 };
 
+struct objc_opt_v16_t {
+    uint32_t version;
+    uint32_t flags;
+    int32_t selopt_offset;
+    int32_t headeropt_ro_offset;
+    int32_t unused_clsopt_offset;
+    int32_t unused_protocolopt_offset;
+    int32_t headeropt_rw_offset;
+    int32_t unused_protocolopt2_offset;
+    int32_t largeSharedCachesClassOffset;
+    int32_t largeSharedCachesProtocolOffset;
+    uint64_t relativeMethodSelectorBaseAddressCacheOffset;
+};
+
 struct ClassInfo
 {
     Class isa;
@@ -303,19 +339,33 @@ struct ClassInfo
 
 uint32_t
 __lldb_apple_objc_v2_get_shared_cache_class_info (void *objc_opt_ro_ptr,
+                                                  void *shared_cache_base_ptr,
                                                   void *class_infos_ptr,
+                                                  uint64_t *relative_selector_offset,
                                                   uint32_t class_infos_byte_size,
                                                   uint32_t should_log)
 {
+    *relative_selector_offset = 0;
     uint32_t idx = 0;
     DEBUG_PRINTF ("objc_opt_ro_ptr = %p\n", objc_opt_ro_ptr);
+    DEBUG_PRINTF ("shared_cache_base_ptr = %p\n", shared_cache_base_ptr);
     DEBUG_PRINTF ("class_infos_ptr = %p\n", class_infos_ptr);
     DEBUG_PRINTF ("class_infos_byte_size = %u (%llu class infos)\n", class_infos_byte_size, (uint64_t)(class_infos_byte_size/sizeof(ClassInfo)));
     if (objc_opt_ro_ptr)
     {
         const objc_opt_t *objc_opt = (objc_opt_t *)objc_opt_ro_ptr;
         const objc_opt_v14_t* objc_opt_v14 = (objc_opt_v14_t*)objc_opt_ro_ptr;
-        if (objc_opt->version >= 14)
+        const objc_opt_v16_t* objc_opt_v16 = (objc_opt_v16_t*)objc_opt_ro_ptr;
+        if (objc_opt->version >= 16)
+        {
+            *relative_selector_offset = objc_opt_v16->relativeMethodSelectorBaseAddressCacheOffset;
+            DEBUG_PRINTF ("objc_opt->version = %u\n", objc_opt_v16->version);
+            DEBUG_PRINTF ("objc_opt->flags = %u\n", objc_opt_v16->flags);
+            DEBUG_PRINTF ("objc_opt->selopt_offset = %d\n", objc_opt_v16->selopt_offset);
+            DEBUG_PRINTF ("objc_opt->headeropt_ro_offset = %d\n", objc_opt_v16->headeropt_ro_offset);
+            DEBUG_PRINTF ("objc_opt->relativeMethodSelectorBaseAddressCacheOffset = %d\n", *relative_selector_offset);
+        }
+        else if (objc_opt->version >= 14)
         {
             DEBUG_PRINTF ("objc_opt->version = %u\n", objc_opt_v14->version);
             DEBUG_PRINTF ("objc_opt->flags = %u\n", objc_opt_v14->flags);
@@ -330,7 +380,123 @@ __lldb_apple_objc_v2_get_shared_cache_class_info (void *objc_opt_ro_ptr,
             DEBUG_PRINTF ("objc_opt->headeropt_offset = %d\n", objc_opt->headeropt_offset);
             DEBUG_PRINTF ("objc_opt->clsopt_offset = %d\n", objc_opt->clsopt_offset);
         }
-        if (objc_opt->version == 12 || objc_opt->version == 13 || objc_opt->version == 14 || objc_opt->version == 15)
+
+        if (objc_opt->version == 16)
+        {
+            const objc_clsopt_v16_t* clsopt = (const objc_clsopt_v16_t*)((uint8_t *)objc_opt + objc_opt_v16->largeSharedCachesClassOffset);
+            const size_t max_class_infos = class_infos_byte_size/sizeof(ClassInfo);
+
+            DEBUG_PRINTF("max_class_infos = %llu\n", (uint64_t)max_class_infos);
+
+            ClassInfo *class_infos = (ClassInfo *)class_infos_ptr;
+
+            const uint8_t *checkbytes = &clsopt->tab[clsopt->mask+1];
+            const int32_t *offsets = (const int32_t *)(checkbytes + clsopt->capacity);
+            const objc_classheader_v16_t *classOffsets = (const objc_classheader_v16_t *)(offsets + clsopt->capacity);
+
+            DEBUG_PRINTF ("clsopt->capacity = %u\n", clsopt->capacity);
+            DEBUG_PRINTF ("clsopt->mask = 0x%8.8x\n", clsopt->mask);
+            DEBUG_PRINTF ("classOffsets = %p\n", classOffsets);
+
+            for (uint32_t i=0; i<clsopt->capacity; ++i)
+            {
+                const uint64_t objectCacheOffset = classOffsets[i].objectCacheOffset;
+                DEBUG_PRINTF("objectCacheOffset[%u] = %u\n", i, objectCacheOffset);
+
+                if (classOffsets[i].isDuplicate) {
+                    DEBUG_PRINTF("isDuplicate = true\n");
+                    continue; // duplicate
+                }
+
+                if (objectCacheOffset == 0) {
+                    DEBUG_PRINTF("objectCacheOffset == invalidEntryOffset\n");
+                    continue; // invalid offset
+                }
+
+                if (class_infos && idx < max_class_infos)
+                {
+                    class_infos[idx].isa = (Class)((uint8_t *)shared_cache_base_ptr + objectCacheOffset);
+
+                    // Lookup the class name.
+                    const char *name = class_name_lookup_func(class_infos[idx].isa);
+                    DEBUG_PRINTF("[%u] isa = %8p %s\n", idx, class_infos[idx].isa, name);
+
+                    // Hash the class name so we don't have to read it.
+                    const char *s = name;
+                    uint32_t h = 5381;
+                    for (unsigned char c = *s; c; c = *++s)
+                    {
+                        // class_getName demangles swift names and the hash must
+                        // be calculated on the mangled name.  hash==0 means lldb
+                        // will fetch the mangled name and compute the hash in
+                        // ParseClassInfoArray.
+                        if (c == '.')
+                        {
+                            h = 0;
+                            break;
+                        }
+                        h = ((h << 5) + h) + c;
+                    }
+                    class_infos[idx].hash = h;
+                }
+                else
+                {
+                    DEBUG_PRINTF("not(class_infos && idx < max_class_infos)\n");
+                }
+                ++idx;
+            }
+
+            const uint32_t *duplicate_count_ptr = (uint32_t *)&classOffsets[clsopt->capacity];
+            const uint32_t duplicate_count = *duplicate_count_ptr;
+            const objc_classheader_v16_t *duplicateClassOffsets = (const objc_classheader_v16_t *)(&duplicate_count_ptr[1]);
+
+            DEBUG_PRINTF ("duplicate_count = %u\n", duplicate_count);
+            DEBUG_PRINTF ("duplicateClassOffsets = %p\n", duplicateClassOffsets);
+
+            for (uint32_t i=0; i<duplicate_count; ++i)
+            {
+                const uint64_t objectCacheOffset = classOffsets[i].objectCacheOffset;
+                DEBUG_PRINTF("objectCacheOffset[%u] = %u\n", i, objectCacheOffset);
+
+                if (classOffsets[i].isDuplicate) {
+                    DEBUG_PRINTF("isDuplicate = true\n");
+                    continue; // duplicate
+                }
+
+                if (objectCacheOffset == 0) {
+                    DEBUG_PRINTF("objectCacheOffset == invalidEntryOffset\n");
+                    continue; // invalid offset
+                }
+
+                if (class_infos && idx < max_class_infos)
+                {
+                    class_infos[idx].isa = (Class)((uint8_t *)shared_cache_base_ptr + objectCacheOffset);
+
+                    // Lookup the class name.
+                    const char *name = class_name_lookup_func(class_infos[idx].isa);
+                    DEBUG_PRINTF("[%u] isa = %8p %s\n", idx, class_infos[idx].isa, name);
+
+                    // Hash the class name so we don't have to read it.
+                    const char *s = name;
+                    uint32_t h = 5381;
+                    for (unsigned char c = *s; c; c = *++s)
+                    {
+                        // class_getName demangles swift names and the hash must
+                        // be calculated on the mangled name.  hash==0 means lldb
+                        // will fetch the mangled name and compute the hash in
+                        // ParseClassInfoArray.
+                        if (c == '.')
+                        {
+                            h = 0;
+                            break;
+                        }
+                        h = ((h << 5) + h) + c;
+                    }
+                    class_infos[idx].hash = h;
+                }
+            }
+        }
+        else if (objc_opt->version >= 12 && objc_opt->version <= 15)
         {
             const objc_clsopt_t* clsopt = NULL;
             if (objc_opt->version >= 14)
@@ -491,7 +657,8 @@ AppleObjCRuntimeV2::AppleObjCRuntimeV2(Process *process,
       m_dynamic_class_info_extractor(*this),
       m_shared_cache_class_info_extractor(*this), m_decl_vendor_up(),
       m_tagged_pointer_obfuscator(LLDB_INVALID_ADDRESS),
-      m_isa_hash_table_ptr(LLDB_INVALID_ADDRESS), m_hash_signature(),
+      m_isa_hash_table_ptr(LLDB_INVALID_ADDRESS),
+      m_relative_selector_base(LLDB_INVALID_ADDRESS), m_hash_signature(),
       m_has_object_getClass(false), m_has_objc_copyRealizedClassList(false),
       m_loaded_objc_opt(false), m_non_pointer_isa_cache_up(),
       m_tagged_pointer_vendor_up(
@@ -1515,6 +1682,9 @@ AppleObjCRuntimeV2::SharedCacheClassInfoExtractor::
       ast->GetBuiltinTypeForEncodingAndBitSize(eEncodingUint, 32);
   CompilerType clang_void_pointer_type =
       ast->GetBasicType(eBasicTypeVoid).GetPointerType();
+  CompilerType clang_uint64_t_pointer_type =
+      ast->GetBuiltinTypeForEncodingAndBitSize(eEncodingUint, 64)
+          .GetPointerType();
 
   // Next make the function caller for our implementation utility function.
   ValueList arguments;
@@ -1523,6 +1693,11 @@ AppleObjCRuntimeV2::SharedCacheClassInfoExtractor::
   value.SetCompilerType(clang_void_pointer_type);
   arguments.PushValue(value);
   arguments.PushValue(value);
+  arguments.PushValue(value);
+
+  value.SetValueType(Value::ValueType::Scalar);
+  value.SetCompilerType(clang_uint64_t_pointer_type);
+  arguments.PushValue(value);
 
   value.SetValueType(Value::ValueType::Scalar);
   value.SetCompilerType(clang_uint32_t_type);
@@ -1816,8 +1991,11 @@ AppleObjCRuntimeV2::SharedCacheClassInfoExtractor::UpdateISAToDescriptorMap() {
   uint32_t num_class_infos = 0;
 
   const lldb::addr_t objc_opt_ptr = m_runtime.GetSharedCacheReadOnlyAddress();
+  const lldb::addr_t shared_cache_base_addr =
+      m_runtime.GetSharedCacheBaseAddress();
 
-  if (objc_opt_ptr == LLDB_INVALID_ADDRESS)
+  if (objc_opt_ptr == LLDB_INVALID_ADDRESS ||
+      shared_cache_base_addr == LLDB_INVALID_ADDRESS)
     return DescriptorMapUpdateResult::Fail();
 
   const uint32_t num_classes = 128 * 1024;
@@ -1840,6 +2018,10 @@ AppleObjCRuntimeV2::SharedCacheClassInfoExtractor::UpdateISAToDescriptorMap() {
   const uint32_t class_infos_byte_size = num_classes * class_info_byte_size;
   lldb::addr_t class_infos_addr = process->AllocateMemory(
       class_infos_byte_size, ePermissionsReadable | ePermissionsWritable, err);
+  const uint32_t relative_selector_offset_addr_size = 64;
+  lldb::addr_t relative_selector_offset_addr =
+      process->AllocateMemory(relative_selector_offset_addr_size,
+                              ePermissionsReadable | ePermissionsWritable, err);
 
   if (class_infos_addr == LLDB_INVALID_ADDRESS) {
     LLDB_LOGF(log,
@@ -1853,14 +2035,16 @@ AppleObjCRuntimeV2::SharedCacheClassInfoExtractor::UpdateISAToDescriptorMap() {
 
   // Fill in our function argument values
   arguments.GetValueAtIndex(0)->GetScalar() = objc_opt_ptr;
-  arguments.GetValueAtIndex(1)->GetScalar() = class_infos_addr;
-  arguments.GetValueAtIndex(2)->GetScalar() = class_infos_byte_size;
+  arguments.GetValueAtIndex(1)->GetScalar() = shared_cache_base_addr;
+  arguments.GetValueAtIndex(2)->GetScalar() = class_infos_addr;
+  arguments.GetValueAtIndex(3)->GetScalar() = relative_selector_offset_addr;
+  arguments.GetValueAtIndex(4)->GetScalar() = class_infos_byte_size;
   // Only dump the runtime classes from the expression evaluation if the log is
   // verbose:
   Log *type_log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_TYPES);
   bool dump_log = type_log && type_log->GetVerbose();
 
-  arguments.GetValueAtIndex(3)->GetScalar() = dump_log ? 1 : 0;
+  arguments.GetValueAtIndex(5)->GetScalar() = dump_log ? 1 : 0;
 
   bool success = false;
 
@@ -1907,13 +2091,35 @@ AppleObjCRuntimeV2::SharedCacheClassInfoExtractor::UpdateISAToDescriptorMap() {
           success = true;
         }
 
+        // Read the relative selector offset.
+        DataBufferHeap relative_selector_offset_buffer(64, 0);
+        if (process->ReadMemory(relative_selector_offset_addr,
+                                relative_selector_offset_buffer.GetBytes(),
+                                relative_selector_offset_buffer.GetByteSize(),
+                                err) ==
+            relative_selector_offset_buffer.GetByteSize()) {
+          DataExtractor relative_selector_offset_data(
+              relative_selector_offset_buffer.GetBytes(),
+              relative_selector_offset_buffer.GetByteSize(),
+              process->GetByteOrder(), addr_size);
+          lldb::offset_t offset = 0;
+          uint64_t relative_selector_offset =
+              relative_selector_offset_data.GetU64(&offset);
+          if (relative_selector_offset > 0) {
+            // The offset is relative to the objc_opt struct.
+            m_runtime.SetRelativeSelectorBaseAddr(objc_opt_ptr +
+                                                  relative_selector_offset);
+          }
+        }
+
         // Read the ClassInfo structures
-        DataBufferHeap buffer(num_class_infos * class_info_byte_size, 0);
-        if (process->ReadMemory(class_infos_addr, buffer.GetBytes(),
-                                buffer.GetByteSize(),
-                                err) == buffer.GetByteSize()) {
-          DataExtractor class_infos_data(buffer.GetBytes(),
-                                         buffer.GetByteSize(),
+        DataBufferHeap class_infos_buffer(
+            num_class_infos * class_info_byte_size, 0);
+        if (process->ReadMemory(class_infos_addr, class_infos_buffer.GetBytes(),
+                                class_infos_buffer.GetByteSize(),
+                                err) == class_infos_buffer.GetByteSize()) {
+          DataExtractor class_infos_data(class_infos_buffer.GetBytes(),
+                                         class_infos_buffer.GetByteSize(),
                                          process->GetByteOrder(), addr_size);
 
           m_runtime.ParseClassInfoArray(class_infos_data, num_class_infos);
@@ -1973,6 +2179,19 @@ lldb::addr_t AppleObjCRuntimeV2::GetSharedCacheReadOnlyAddress() {
   return LLDB_INVALID_ADDRESS;
 }
 
+lldb::addr_t AppleObjCRuntimeV2::GetSharedCacheBaseAddress() {
+  StructuredData::ObjectSP info = m_process->GetSharedCacheInfo();
+  if (!info)
+    return LLDB_INVALID_ADDRESS;
+
+  StructuredData::Dictionary *info_dict = info->GetAsDictionary();
+  if (!info_dict)
+    return LLDB_INVALID_ADDRESS;
+
+  return info_dict->GetValueForKey("shared_cache_base_address")
+      ->GetIntegerValue(LLDB_INVALID_ADDRESS);
+}
+
 void AppleObjCRuntimeV2::UpdateISAToDescriptorMapIfNeeded() {
   LLDB_SCOPED_TIMER();
 

diff  --git a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.h b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.h
index 2da1670a3a0c0..d0caa2969115a 100644
--- a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.h
+++ b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.h
@@ -85,6 +85,15 @@ class AppleObjCRuntimeV2 : public AppleObjCRuntime {
 
   lldb::addr_t GetTaggedPointerObfuscator();
 
+  /// Returns the base address for relative method list selector strings.
+  lldb::addr_t GetRelativeSelectorBaseAddr() {
+    return m_relative_selector_base;
+  }
+
+  void SetRelativeSelectorBaseAddr(lldb::addr_t relative_selector_base) {
+    m_relative_selector_base = relative_selector_base;
+  }
+
   void GetValuesForGlobalCFBooleans(lldb::addr_t &cf_true,
                                     lldb::addr_t &cf_false) override;
 
@@ -394,6 +403,7 @@ class AppleObjCRuntimeV2 : public AppleObjCRuntime {
   void WarnIfNoClassesCached(SharedCacheWarningReason reason);
 
   lldb::addr_t GetSharedCacheReadOnlyAddress();
+  lldb::addr_t GetSharedCacheBaseAddress();
 
   bool GetCFBooleanValuesIfNeeded();
 
@@ -416,6 +426,7 @@ class AppleObjCRuntimeV2 : public AppleObjCRuntime {
   std::unique_ptr<DeclVendor> m_decl_vendor_up;
   lldb::addr_t m_tagged_pointer_obfuscator;
   lldb::addr_t m_isa_hash_table_ptr;
+  lldb::addr_t m_relative_selector_base;
   HashTableSignature m_hash_signature;
   bool m_has_object_getClass;
   bool m_has_objc_copyRealizedClassList;


        


More information about the lldb-commits mailing list