[Lldb-commits] [lldb] 61d22ef - [lldb/ObjCRuntime] Implement support for small method lists

Fred Riss via lldb-commits lldb-commits at lists.llvm.org
Wed Jul 1 20:30:45 PDT 2020


Author: Fred Riss
Date: 2020-07-01T20:27:37-07:00
New Revision: 61d22ef236206f17d7abcdcdf9da3c99074432d5

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

LOG: [lldb/ObjCRuntime] Implement support for small method lists

On macOS 11 (and other aligned Apple OSs), the Objective-C runtime
has a new optimization which saves memory by making the method
lists smaller.
This patch adds support for this new method list encoding (while
also keeping backward compatibility). This is implicitely covered
by some existing Objective-C tests.

Added: 
    

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

Removed: 
    


################################################################################
diff  --git a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCClassDescriptorV2.cpp b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCClassDescriptorV2.cpp
index 06aa861d5f69..ff9c86608b8a 100644
--- a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCClassDescriptorV2.cpp
+++ b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCClassDescriptorV2.cpp
@@ -241,15 +241,19 @@ bool ClassDescriptorV2::method_list_t::Read(Process *process,
 
   lldb::offset_t cursor = 0;
 
-  m_entsize = extractor.GetU32_unchecked(&cursor) & ~(uint32_t)3;
+  uint32_t entsize = extractor.GetU32_unchecked(&cursor);
+  m_is_small = (entsize & 0x80000000) != 0;
+  m_entsize = entsize & 0xfffc;
   m_count = extractor.GetU32_unchecked(&cursor);
   m_first_ptr = addr + cursor;
 
   return true;
 }
 
-bool ClassDescriptorV2::method_t::Read(Process *process, lldb::addr_t addr) {
-  size_t size = GetSize(process);
+bool ClassDescriptorV2::method_t::Read(Process *process, lldb::addr_t addr,
+                                       bool is_small) {
+  size_t ptr_size = process->GetAddressByteSize();
+  size_t size = GetSize(process, is_small);
 
   DataBufferHeap buffer(size, '\0');
   Status error;
@@ -260,13 +264,27 @@ bool ClassDescriptorV2::method_t::Read(Process *process, lldb::addr_t addr) {
   }
 
   DataExtractor extractor(buffer.GetBytes(), size, process->GetByteOrder(),
-                          process->GetAddressByteSize());
-
+                          ptr_size);
   lldb::offset_t cursor = 0;
 
-  m_name_ptr = extractor.GetAddress_unchecked(&cursor);
-  m_types_ptr = extractor.GetAddress_unchecked(&cursor);
-  m_imp_ptr = extractor.GetAddress_unchecked(&cursor);
+  if (is_small) {
+    uint32_t nameref_offset = extractor.GetU32_unchecked(&cursor);
+    uint32_t types_offset = extractor.GetU32_unchecked(&cursor);
+    uint32_t imp_offset = extractor.GetU32_unchecked(&cursor);
+
+    // The SEL offset points to a SELRef. We need to dereference twice.
+    lldb::addr_t selref_addr = addr + nameref_offset;
+    m_name_ptr =
+        process->ReadUnsignedIntegerFromMemory(selref_addr, ptr_size, 0, error);
+    if (!error.Success())
+      return false;
+    m_types_ptr = addr + 4 + types_offset;
+    m_imp_ptr = addr + 8 + imp_offset;
+  } else {
+    m_name_ptr = extractor.GetAddress_unchecked(&cursor);
+    m_types_ptr = extractor.GetAddress_unchecked(&cursor);
+    m_imp_ptr = extractor.GetAddress_unchecked(&cursor);
+  }
 
   process->ReadCStringFromMemory(m_name_ptr, m_name, error);
   if (error.Fail()) {
@@ -361,15 +379,18 @@ bool ClassDescriptorV2::Describe(
     if (!base_method_list->Read(process, class_ro->m_baseMethods_ptr))
       return false;
 
-    if (base_method_list->m_entsize != method_t::GetSize(process))
+    bool is_small = base_method_list->m_is_small;
+    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>();
 
     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));
+      method->Read(process,
+                   base_method_list->m_first_ptr +
+                       (i * base_method_list->m_entsize),
+                   is_small);
 
       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 56728cff5b3f..a8db060c5b56 100644
--- a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCClassDescriptorV2.h
+++ b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCClassDescriptorV2.h
@@ -133,7 +133,8 @@ class ClassDescriptorV2 : public ObjCLanguageRuntime::ClassDescriptor {
   };
 
   struct method_list_t {
-    uint32_t m_entsize;
+    uint16_t m_entsize;
+    bool m_is_small;
     uint32_t m_count;
     lldb::addr_t m_first_ptr;
 
@@ -148,15 +149,19 @@ class ClassDescriptorV2 : public ObjCLanguageRuntime::ClassDescriptor {
     std::string m_name;
     std::string m_types;
 
-    static size_t GetSize(Process *process) {
-      size_t ptr_size = process->GetAddressByteSize();
+    static size_t GetSize(Process *process, bool is_small) {
+      size_t field_size;
+      if (is_small)
+        field_size = 4; // uint32_t relative indirect fields
+      else
+        field_size = process->GetAddressByteSize();
 
-      return ptr_size    // SEL name;
-             + ptr_size  // const char *types;
-             + ptr_size; // IMP imp;
+      return field_size    // SEL name;
+             + field_size  // const char *types;
+             + field_size; // IMP imp;
     }
 
-    bool Read(Process *process, lldb::addr_t addr);
+    bool Read(Process *process, lldb::addr_t addr, bool);
   };
 
   struct ivar_list_t {


        


More information about the lldb-commits mailing list