[Lldb-commits] [lldb] r306180 - Updated the NSArray and NSDictionary formatters to support new storage formats.

Sean Callanan via lldb-commits lldb-commits at lists.llvm.org
Fri Jun 23 16:15:04 PDT 2017


Author: spyffe
Date: Fri Jun 23 18:15:03 2017
New Revision: 306180

URL: http://llvm.org/viewvc/llvm-project?rev=306180&view=rev
Log:
Updated the NSArray and NSDictionary formatters to support new storage formats.

Also un-xfailed a testcase that was affected by this.  Thanks to Jason Molenda for the patch.

<rdar://problem/32827216>

Modified:
    lldb/trunk/packages/Python/lldbsuite/test/lang/objc/objc-new-syntax/TestObjCNewSyntax.py
    lldb/trunk/source/Plugins/Language/ObjC/NSArray.cpp
    lldb/trunk/source/Plugins/Language/ObjC/NSDictionary.cpp

Modified: lldb/trunk/packages/Python/lldbsuite/test/lang/objc/objc-new-syntax/TestObjCNewSyntax.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/packages/Python/lldbsuite/test/lang/objc/objc-new-syntax/TestObjCNewSyntax.py?rev=306180&r1=306179&r2=306180&view=diff
==============================================================================
--- lldb/trunk/packages/Python/lldbsuite/test/lang/objc/objc-new-syntax/TestObjCNewSyntax.py (original)
+++ lldb/trunk/packages/Python/lldbsuite/test/lang/objc/objc-new-syntax/TestObjCNewSyntax.py Fri Jun 23 18:15:03 2017
@@ -121,8 +121,6 @@ class ObjCNewSyntaxTestCase(TestBase):
             '7.0.0'])
     @skipIf(macos_version=["<", "10.12"])
     @expectedFailureAll(archs=["i[3-6]86"])
-    @expectedFailureAll(
-        bugnumber="rdar://32777981")
     def test_update_dictionary(self):
         self.runToBreakpoint()
 
@@ -165,8 +163,6 @@ class ObjCNewSyntaxTestCase(TestBase):
             '7.0.0'])
     @skipIf(macos_version=["<", "10.12"])
     @expectedFailureAll(archs=["i[3-6]86"])
-    @expectedFailureAll(
-        bugnumber="rdar://32777981")
     def test_dictionary_literal(self):
         self.runToBreakpoint()
 

Modified: lldb/trunk/source/Plugins/Language/ObjC/NSArray.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Language/ObjC/NSArray.cpp?rev=306180&r1=306179&r2=306180&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Language/ObjC/NSArray.cpp (original)
+++ lldb/trunk/source/Plugins/Language/ObjC/NSArray.cpp Fri Jun 23 18:15:03 2017
@@ -160,11 +160,47 @@ private:
   DataDescriptor_64 *m_data_64;
 };
 
-class NSArrayISyntheticFrontEnd : public SyntheticChildrenFrontEnd {
+class NSArrayMSyntheticFrontEnd_1400 : public NSArrayMSyntheticFrontEnd {
 public:
-  NSArrayISyntheticFrontEnd(lldb::ValueObjectSP valobj_sp);
+  NSArrayMSyntheticFrontEnd_1400(lldb::ValueObjectSP valobj_sp);
 
-  ~NSArrayISyntheticFrontEnd() override = default;
+  ~NSArrayMSyntheticFrontEnd_1400() override;
+
+  bool Update() override;
+
+protected:
+  lldb::addr_t GetDataAddress() override;
+
+  uint64_t GetUsedCount() override;
+
+  uint64_t GetOffset() override;
+
+  uint64_t GetSize() override;
+
+private:
+  struct DataDescriptor_32 {
+    uint32_t used;
+    uint32_t offset;
+    uint32_t size;
+    uint32_t list;
+  };
+
+  struct DataDescriptor_64 {
+    uint64_t used;
+    uint64_t offset;
+    uint64_t size;
+    uint64_t list;
+  };
+
+  DataDescriptor_32 *m_data_32;
+  DataDescriptor_64 *m_data_64;
+};
+
+class NSArrayISyntheticFrontEnd_1300 : public SyntheticChildrenFrontEnd {
+public:
+  NSArrayISyntheticFrontEnd_1300(lldb::ValueObjectSP valobj_sp);
+
+  ~NSArrayISyntheticFrontEnd_1300() override = default;
 
   size_t CalculateNumChildren() override;
 
@@ -184,6 +220,45 @@ private:
   CompilerType m_id_type;
 };
 
+class NSArrayISyntheticFrontEnd_1400 : public SyntheticChildrenFrontEnd {
+public:
+  NSArrayISyntheticFrontEnd_1400(lldb::ValueObjectSP valobj_sp);
+
+  ~NSArrayISyntheticFrontEnd_1400() override;
+
+  size_t CalculateNumChildren() override;
+
+  lldb::ValueObjectSP GetChildAtIndex(size_t idx) override;
+
+  bool Update() override;
+
+  bool MightHaveChildren() override;
+
+  size_t GetIndexOfChildWithName(const ConstString &name) override;
+
+private:
+  ExecutionContextRef m_exe_ctx_ref;
+  uint8_t m_ptr_size;
+
+  struct DataDescriptor_32 {
+    uint32_t used;
+    uint32_t offset;
+    uint32_t size;
+    uint32_t list;
+  };
+
+  struct DataDescriptor_64 {
+    uint64_t used;
+    uint64_t offset;
+    uint64_t size;
+    uint64_t list;
+  };
+
+  DataDescriptor_32 *m_data_32;
+  DataDescriptor_64 *m_data_64;
+  CompilerType m_id_type;
+};
+
 class NSArray0SyntheticFrontEnd : public SyntheticChildrenFrontEnd {
 public:
   NSArray0SyntheticFrontEnd(lldb::ValueObjectSP valobj_sp);
@@ -257,6 +332,8 @@ bool lldb_private::formatters::NSArraySu
   static const ConstString g_NSArray0("__NSArray0");
   static const ConstString g_NSArray1("__NSSingleObjectArrayI");
   static const ConstString g_NSArrayCF("__NSCFArray");
+  static const ConstString g_NSArrayMLegacy("__NSArrayM_Legacy");
+  static const ConstString g_NSArrayMImmutable("__NSArrayM_Immutable");
 
   if (class_name.IsEmpty())
     return false;
@@ -273,6 +350,18 @@ bool lldb_private::formatters::NSArraySu
                                                       ptr_size, 0, error);
     if (error.Fail())
       return false;
+  } else if (class_name == g_NSArrayMLegacy) {
+    Status error;
+    value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size,
+                                                      ptr_size, 0, error);
+    if (error.Fail())
+      return false;
+  } else if (class_name == g_NSArrayMImmutable) {
+    Status error;
+    value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size,
+                                                      ptr_size, 0, error);
+    if (error.Fail())
+      return false;
   } else if (class_name == g_NSArray0) {
     value = 0;
   } else if (class_name == g_NSArray1) {
@@ -332,6 +421,11 @@ lldb_private::formatters::NSArrayMSynthe
     : NSArrayMSyntheticFrontEnd(valobj_sp), m_data_32(nullptr),
       m_data_64(nullptr) {}
 
+lldb_private::formatters::NSArrayMSyntheticFrontEnd_1400::
+    NSArrayMSyntheticFrontEnd_1400(lldb::ValueObjectSP valobj_sp)
+    : NSArrayMSyntheticFrontEnd(valobj_sp), m_data_32(nullptr),
+      m_data_64(nullptr) {}
+
 size_t
 lldb_private::formatters::NSArrayMSyntheticFrontEnd::CalculateNumChildren() {
   return GetUsedCount();
@@ -416,6 +510,37 @@ bool lldb_private::formatters::NSArrayMS
   return false;
 }
 
+bool lldb_private::formatters::NSArrayMSyntheticFrontEnd_1400::Update() {
+  ValueObjectSP valobj_sp = m_backend.GetSP();
+  m_ptr_size = 0;
+  delete m_data_32;
+  m_data_32 = nullptr;
+  delete m_data_64;
+  m_data_64 = nullptr;
+  if (!valobj_sp)
+    return false;
+  m_exe_ctx_ref = valobj_sp->GetExecutionContextRef();
+  Status error;
+  error.Clear();
+  lldb::ProcessSP process_sp(valobj_sp->GetProcessSP());
+  if (!process_sp)
+    return false;
+  m_ptr_size = process_sp->GetAddressByteSize();
+  uint64_t data_location = valobj_sp->GetValueAsUnsigned(0) + m_ptr_size;
+  if (m_ptr_size == 4) {
+    m_data_32 = new DataDescriptor_32();
+    process_sp->ReadMemory(data_location, m_data_32, sizeof(DataDescriptor_32),
+                           error);
+  } else {
+    m_data_64 = new DataDescriptor_64();
+    process_sp->ReadMemory(data_location, m_data_64, sizeof(DataDescriptor_64),
+                           error);
+  }
+  if (error.Fail())
+    return false;
+  return false;
+}
+
 bool lldb_private::formatters::NSArrayMSyntheticFrontEnd::MightHaveChildren() {
   return true;
 }
@@ -498,7 +623,42 @@ uint64_t lldb_private::formatters::NSArr
   return m_data_32 ? m_data_32->_size : m_data_64->_size;
 }
 
-lldb_private::formatters::NSArrayISyntheticFrontEnd::NSArrayISyntheticFrontEnd(
+lldb_private::formatters::NSArrayMSyntheticFrontEnd_1400::
+    ~NSArrayMSyntheticFrontEnd_1400() {
+  delete m_data_32;
+  m_data_32 = nullptr;
+  delete m_data_64;
+  m_data_64 = nullptr;
+}
+
+lldb::addr_t
+lldb_private::formatters::NSArrayMSyntheticFrontEnd_1400::GetDataAddress() {
+  if (!m_data_32 && !m_data_64)
+    return LLDB_INVALID_ADDRESS;
+  return m_data_32 ? m_data_32->list : m_data_64->list;
+}
+
+uint64_t
+lldb_private::formatters::NSArrayMSyntheticFrontEnd_1400::GetUsedCount() {
+  if (!m_data_32 && !m_data_64)
+    return 0;
+  return m_data_32 ? m_data_32->used : m_data_64->used;
+}
+
+uint64_t lldb_private::formatters::NSArrayMSyntheticFrontEnd_1400::GetOffset() {
+  if (!m_data_32 && !m_data_64)
+    return 0;
+  return m_data_32 ? m_data_32->offset : m_data_64->offset;
+}
+
+uint64_t lldb_private::formatters::NSArrayMSyntheticFrontEnd_1400::GetSize() {
+  if (!m_data_32 && !m_data_64)
+    return 0;
+  return m_data_32 ? m_data_32->size : m_data_64->size;
+}
+
+
+lldb_private::formatters::NSArrayISyntheticFrontEnd_1300::NSArrayISyntheticFrontEnd_1300(
     lldb::ValueObjectSP valobj_sp)
     : SyntheticChildrenFrontEnd(*valobj_sp), m_exe_ctx_ref(), m_ptr_size(8),
       m_items(0), m_data_ptr(0) {
@@ -516,7 +676,7 @@ lldb_private::formatters::NSArrayISynthe
 }
 
 size_t
-lldb_private::formatters::NSArrayISyntheticFrontEnd::GetIndexOfChildWithName(
+lldb_private::formatters::NSArrayISyntheticFrontEnd_1300::GetIndexOfChildWithName(
     const ConstString &name) {
   const char *item_name = name.GetCString();
   uint32_t idx = ExtractIndexFromString(item_name);
@@ -526,11 +686,11 @@ lldb_private::formatters::NSArrayISynthe
 }
 
 size_t
-lldb_private::formatters::NSArrayISyntheticFrontEnd::CalculateNumChildren() {
+lldb_private::formatters::NSArrayISyntheticFrontEnd_1300::CalculateNumChildren() {
   return m_items;
 }
 
-bool lldb_private::formatters::NSArrayISyntheticFrontEnd::Update() {
+bool lldb_private::formatters::NSArrayISyntheticFrontEnd_1300::Update() {
   m_ptr_size = 0;
   m_items = 0;
   m_data_ptr = 0;
@@ -552,12 +712,12 @@ bool lldb_private::formatters::NSArrayIS
   return false;
 }
 
-bool lldb_private::formatters::NSArrayISyntheticFrontEnd::MightHaveChildren() {
+bool lldb_private::formatters::NSArrayISyntheticFrontEnd_1300::MightHaveChildren() {
   return true;
 }
 
 lldb::ValueObjectSP
-lldb_private::formatters::NSArrayISyntheticFrontEnd::GetChildAtIndex(
+lldb_private::formatters::NSArrayISyntheticFrontEnd_1300::GetChildAtIndex(
     size_t idx) {
   if (idx >= CalculateNumChildren())
     return lldb::ValueObjectSP();
@@ -575,6 +735,99 @@ lldb_private::formatters::NSArrayISynthe
                                       m_exe_ctx_ref, m_id_type);
 }
 
+lldb_private::formatters::NSArrayISyntheticFrontEnd_1400::NSArrayISyntheticFrontEnd_1400(
+    lldb::ValueObjectSP valobj_sp)
+    : SyntheticChildrenFrontEnd(*valobj_sp), m_exe_ctx_ref(), m_ptr_size(8),
+      m_data_32(nullptr), m_data_64(nullptr) {
+  if (valobj_sp) {
+    CompilerType type = valobj_sp->GetCompilerType();
+    if (type) {
+      ClangASTContext *ast = valobj_sp->GetExecutionContextRef()
+                                 .GetTargetSP()
+                                 ->GetScratchClangASTContext();
+      if (ast)
+        m_id_type = CompilerType(ast->getASTContext(),
+                                 ast->getASTContext()->ObjCBuiltinIdTy);
+    }
+  }
+}
+
+lldb_private::formatters::NSArrayISyntheticFrontEnd_1400::~NSArrayISyntheticFrontEnd_1400() {
+  delete m_data_32;
+  m_data_32 = nullptr;
+  delete m_data_64;
+  m_data_64 = nullptr;
+}
+
+size_t
+lldb_private::formatters::NSArrayISyntheticFrontEnd_1400::GetIndexOfChildWithName(
+    const ConstString &name) {
+  const char *item_name = name.GetCString();
+  uint32_t idx = ExtractIndexFromString(item_name);
+  if (idx < UINT32_MAX && idx >= CalculateNumChildren())
+    return UINT32_MAX;
+  return idx;
+}
+
+size_t
+lldb_private::formatters::NSArrayISyntheticFrontEnd_1400::CalculateNumChildren() {
+  return m_data_32 ? m_data_32->used : m_data_64->used;
+}
+
+bool lldb_private::formatters::NSArrayISyntheticFrontEnd_1400::Update() {
+  ValueObjectSP valobj_sp = m_backend.GetSP();
+  m_ptr_size = 0;
+  delete m_data_32;
+  m_data_32 = nullptr;
+  delete m_data_64;
+  m_data_64 = nullptr;
+  if (!valobj_sp)
+    return false;
+  m_exe_ctx_ref = valobj_sp->GetExecutionContextRef();
+  Status error;
+  error.Clear();
+  lldb::ProcessSP process_sp(valobj_sp->GetProcessSP());
+  if (!process_sp)
+    return false;
+  m_ptr_size = process_sp->GetAddressByteSize();
+  uint64_t data_location = valobj_sp->GetValueAsUnsigned(0) + m_ptr_size;
+  if (m_ptr_size == 4) {
+    m_data_32 = new DataDescriptor_32();
+    process_sp->ReadMemory(data_location, m_data_32, sizeof(DataDescriptor_32),
+                           error);
+  } else {
+    m_data_64 = new DataDescriptor_64();
+    process_sp->ReadMemory(data_location, m_data_64, sizeof(DataDescriptor_64),
+                           error);
+  }
+  if (error.Fail())
+    return false;
+  return false;
+}
+
+bool lldb_private::formatters::NSArrayISyntheticFrontEnd_1400::MightHaveChildren() {
+  return true;
+}
+
+lldb::ValueObjectSP
+lldb_private::formatters::NSArrayISyntheticFrontEnd_1400::GetChildAtIndex(
+    size_t idx) {
+  if (idx >= CalculateNumChildren())
+    return lldb::ValueObjectSP();
+  lldb::addr_t object_at_idx = m_data_32 ? m_data_32->list : m_data_64->list;
+  object_at_idx += (idx * m_ptr_size);
+  ProcessSP process_sp = m_exe_ctx_ref.GetProcessSP();
+  if (!process_sp)
+    return lldb::ValueObjectSP();
+  Status error;
+  if (error.Fail())
+    return lldb::ValueObjectSP();
+  StreamString idx_name;
+  idx_name.Printf("[%" PRIu64 "]", (uint64_t)idx);
+  return CreateValueObjectFromAddress(idx_name.GetString(), object_at_idx,
+                                      m_exe_ctx_ref, m_id_type);
+}
+
 lldb_private::formatters::NSArray0SyntheticFrontEnd::NSArray0SyntheticFrontEnd(
     lldb::ValueObjectSP valobj_sp)
     : SyntheticChildrenFrontEnd(*valobj_sp) {}
@@ -683,17 +936,24 @@ lldb_private::formatters::NSArraySynthet
   static const ConstString g_NSArrayM("__NSArrayM");
   static const ConstString g_NSArray0("__NSArray0");
   static const ConstString g_NSArray1("__NSSingleObjectArrayI");
+  static const ConstString g_NSArrayMLegacy("__NSArrayM_Legacy");
+  static const ConstString g_NSArrayMImmutable("__NSArrayM_Immutable");
 
   if (class_name.IsEmpty())
     return nullptr;
 
   if (class_name == g_NSArrayI) {
-    return (new NSArrayISyntheticFrontEnd(valobj_sp));
+      if (runtime->GetFoundationVersion() >= 1400)
+        return (new NSArrayISyntheticFrontEnd_1400(valobj_sp));
+      else
+        return (new NSArrayISyntheticFrontEnd_1300(valobj_sp));
   } else if (class_name == g_NSArray0) {
     return (new NSArray0SyntheticFrontEnd(valobj_sp));
   } else if (class_name == g_NSArray1) {
     return (new NSArray1SyntheticFrontEnd(valobj_sp));
   } else if (class_name == g_NSArrayM) {
+    if (runtime->GetFoundationVersion() >= 1400)
+      return (new NSArrayMSyntheticFrontEnd_1400(valobj_sp));
     if (runtime->GetFoundationVersion() >= 1100)
       return (new NSArrayMSyntheticFrontEnd_1010(valobj_sp));
     else

Modified: lldb/trunk/source/Plugins/Language/ObjC/NSDictionary.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Language/ObjC/NSDictionary.cpp?rev=306180&r1=306179&r2=306180&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Language/ObjC/NSDictionary.cpp (original)
+++ lldb/trunk/source/Plugins/Language/ObjC/NSDictionary.cpp Fri Jun 23 18:15:03 2017
@@ -17,6 +17,8 @@
 // Project includes
 #include "NSDictionary.h"
 
+#include "Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.h"
+
 #include "lldb/Core/ValueObject.h"
 #include "lldb/Core/ValueObjectConstResult.h"
 #include "lldb/DataFormatters/FormattersHelpers.h"
@@ -181,6 +183,52 @@ public:
 
 private:
   struct DataDescriptor_32 {
+    uint32_t used : 26;
+    uint32_t kvo : 1;
+    uint32_t size;
+    uint32_t buffer;
+  };
+
+  struct DataDescriptor_64 {
+    uint64_t used : 58;
+    uint32_t kvo : 1;
+    uint64_t size;
+    uint64_t buffer;
+  };
+
+  struct DictionaryItemDescriptor {
+    lldb::addr_t key_ptr;
+    lldb::addr_t val_ptr;
+    lldb::ValueObjectSP valobj_sp;
+  };
+
+  ExecutionContextRef m_exe_ctx_ref;
+  uint8_t m_ptr_size;
+  lldb::ByteOrder m_order;
+  DataDescriptor_32 *m_data_32;
+  DataDescriptor_64 *m_data_64;
+  CompilerType m_pair_type;
+  std::vector<DictionaryItemDescriptor> m_children;
+};
+
+class NSDictionaryMLegacySyntheticFrontEnd : public SyntheticChildrenFrontEnd {
+public:
+  NSDictionaryMLegacySyntheticFrontEnd(lldb::ValueObjectSP valobj_sp);
+
+  ~NSDictionaryMLegacySyntheticFrontEnd() override;
+
+  size_t CalculateNumChildren() override;
+
+  lldb::ValueObjectSP GetChildAtIndex(size_t idx) override;
+
+  bool Update() override;
+
+  bool MightHaveChildren() override;
+
+  size_t GetIndexOfChildWithName(const ConstString &name) override;
+
+private:
+  struct DataDescriptor_32 {
     uint32_t _used : 26;
     uint32_t _kvo : 1;
     uint32_t _size;
@@ -250,19 +298,21 @@ bool lldb_private::formatters::NSDiction
 
   static const ConstString g_DictionaryI("__NSDictionaryI");
   static const ConstString g_DictionaryM("__NSDictionaryM");
+  static const ConstString g_DictionaryMLegacy("__NSDictionaryM_Legacy");
+  static const ConstString g_DictionaryMImmutable("__NSDictionaryM_Immutable");
   static const ConstString g_Dictionary1("__NSSingleEntryDictionaryI");
 
   if (class_name.IsEmpty())
     return false;
 
-  if (class_name == g_DictionaryI) {
+  if (class_name == g_DictionaryI || class_name == g_DictionaryMImmutable) {
     Status error;
     value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size,
                                                       ptr_size, 0, error);
     if (error.Fail())
       return false;
     value &= (is_64bit ? ~0xFC00000000000000UL : ~0xFC000000U);
-  } else if (class_name == g_DictionaryM) {
+  } else if (class_name == g_DictionaryM || class_name == g_DictionaryMLegacy) {
     Status error;
     value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size,
                                                       ptr_size, 0, error);
@@ -311,9 +361,8 @@ lldb_private::formatters::NSDictionarySy
   lldb::ProcessSP process_sp(valobj_sp->GetProcessSP());
   if (!process_sp)
     return nullptr;
-  ObjCLanguageRuntime *runtime =
-      (ObjCLanguageRuntime *)process_sp->GetLanguageRuntime(
-          lldb::eLanguageTypeObjC);
+  AppleObjCRuntime *runtime =
+      llvm::dyn_cast_or_null<AppleObjCRuntime>(process_sp->GetObjCLanguageRuntime());
   if (!runtime)
     return nullptr;
 
@@ -338,6 +387,8 @@ lldb_private::formatters::NSDictionarySy
   static const ConstString g_DictionaryI("__NSDictionaryI");
   static const ConstString g_DictionaryM("__NSDictionaryM");
   static const ConstString g_Dictionary1("__NSSingleEntryDictionaryI");
+  static const ConstString g_DictionaryImmutable("__NSDictionaryM_Immutable");
+  static const ConstString g_DictionaryMLegacy("__NSDictionaryM_Legacy");
 
   if (class_name.IsEmpty())
     return nullptr;
@@ -345,7 +396,13 @@ lldb_private::formatters::NSDictionarySy
   if (class_name == g_DictionaryI) {
     return (new NSDictionaryISyntheticFrontEnd(valobj_sp));
   } else if (class_name == g_DictionaryM) {
-    return (new NSDictionaryMSyntheticFrontEnd(valobj_sp));
+    if (runtime->GetFoundationVersion() > 1400) {
+      return (new NSDictionaryMSyntheticFrontEnd(valobj_sp));
+    } else {
+      return (new NSDictionaryMLegacySyntheticFrontEnd(valobj_sp));
+    }
+  } else if (class_name == g_DictionaryMLegacy) {
+      return (new NSDictionaryMLegacySyntheticFrontEnd(valobj_sp));
   } else if (class_name == g_Dictionary1) {
     return (new NSDictionary1SyntheticFrontEnd(valobj_sp));
   } else {
@@ -611,7 +668,7 @@ size_t lldb_private::formatters::NSDicti
     CalculateNumChildren() {
   if (!m_data_32 && !m_data_64)
     return 0;
-  return (m_data_32 ? m_data_32->_used : m_data_64->_used);
+  return (m_data_32 ? m_data_32->used : m_data_64->used);
 }
 
 bool lldb_private::formatters::NSDictionaryMSyntheticFrontEnd::Update() {
@@ -655,6 +712,165 @@ bool lldb_private::formatters::NSDiction
 lldb::ValueObjectSP
 lldb_private::formatters::NSDictionaryMSyntheticFrontEnd::GetChildAtIndex(
     size_t idx) {
+  lldb::addr_t m_keys_ptr;
+  lldb::addr_t m_values_ptr;
+  if (m_data_32) {
+    uint32_t size = m_data_32->size;
+    m_keys_ptr = m_data_32->buffer;
+    m_values_ptr = m_data_32->buffer + (m_ptr_size * size);
+  } else {
+    uint32_t size = m_data_64->size;
+    m_keys_ptr = m_data_64->buffer;
+    m_values_ptr = m_data_64->buffer + (m_ptr_size * size);
+  }
+
+  uint32_t num_children = CalculateNumChildren();
+
+  if (idx >= num_children)
+    return lldb::ValueObjectSP();
+
+  if (m_children.empty()) {
+    // do the scan phase
+    lldb::addr_t key_at_idx = 0, val_at_idx = 0;
+
+    uint32_t tries = 0;
+    uint32_t test_idx = 0;
+
+    while (tries < num_children) {
+      key_at_idx = m_keys_ptr + (test_idx * m_ptr_size);
+      val_at_idx = m_values_ptr + (test_idx * m_ptr_size);
+      ;
+      ProcessSP process_sp = m_exe_ctx_ref.GetProcessSP();
+      if (!process_sp)
+        return lldb::ValueObjectSP();
+      Status error;
+      key_at_idx = process_sp->ReadPointerFromMemory(key_at_idx, error);
+      if (error.Fail())
+        return lldb::ValueObjectSP();
+      val_at_idx = process_sp->ReadPointerFromMemory(val_at_idx, error);
+      if (error.Fail())
+        return lldb::ValueObjectSP();
+
+      test_idx++;
+
+      if (!key_at_idx || !val_at_idx)
+        continue;
+      tries++;
+
+      DictionaryItemDescriptor descriptor = {key_at_idx, val_at_idx,
+                                             lldb::ValueObjectSP()};
+
+      m_children.push_back(descriptor);
+    }
+  }
+
+  if (idx >= m_children.size()) // should never happen
+    return lldb::ValueObjectSP();
+
+  DictionaryItemDescriptor &dict_item = m_children[idx];
+  if (!dict_item.valobj_sp) {
+    if (!m_pair_type.IsValid()) {
+      TargetSP target_sp(m_backend.GetTargetSP());
+      if (!target_sp)
+        return ValueObjectSP();
+      m_pair_type = GetLLDBNSPairType(target_sp);
+    }
+    if (!m_pair_type.IsValid())
+      return ValueObjectSP();
+
+    DataBufferSP buffer_sp(new DataBufferHeap(2 * m_ptr_size, 0));
+
+    if (m_ptr_size == 8) {
+      uint64_t *data_ptr = (uint64_t *)buffer_sp->GetBytes();
+      *data_ptr = dict_item.key_ptr;
+      *(data_ptr + 1) = dict_item.val_ptr;
+    } else {
+      uint32_t *data_ptr = (uint32_t *)buffer_sp->GetBytes();
+      *data_ptr = dict_item.key_ptr;
+      *(data_ptr + 1) = dict_item.val_ptr;
+    }
+
+    StreamString idx_name;
+    idx_name.Printf("[%" PRIu64 "]", (uint64_t)idx);
+    DataExtractor data(buffer_sp, m_order, m_ptr_size);
+    dict_item.valobj_sp = CreateValueObjectFromData(idx_name.GetString(), data,
+                                                    m_exe_ctx_ref, m_pair_type);
+  }
+  return dict_item.valobj_sp;
+}
+
+
+lldb_private::formatters::NSDictionaryMLegacySyntheticFrontEnd::
+    NSDictionaryMLegacySyntheticFrontEnd(lldb::ValueObjectSP valobj_sp)
+    : SyntheticChildrenFrontEnd(*valobj_sp), m_exe_ctx_ref(), m_ptr_size(8),
+      m_order(lldb::eByteOrderInvalid), m_data_32(nullptr), m_data_64(nullptr),
+      m_pair_type() {}
+
+lldb_private::formatters::NSDictionaryMLegacySyntheticFrontEnd::
+    ~NSDictionaryMLegacySyntheticFrontEnd() {
+  delete m_data_32;
+  m_data_32 = nullptr;
+  delete m_data_64;
+  m_data_64 = nullptr;
+}
+
+size_t lldb_private::formatters::NSDictionaryMLegacySyntheticFrontEnd::
+    GetIndexOfChildWithName(const ConstString &name) {
+  const char *item_name = name.GetCString();
+  uint32_t idx = ExtractIndexFromString(item_name);
+  if (idx < UINT32_MAX && idx >= CalculateNumChildren())
+    return UINT32_MAX;
+  return idx;
+}
+
+size_t lldb_private::formatters::NSDictionaryMLegacySyntheticFrontEnd::
+    CalculateNumChildren() {
+  if (!m_data_32 && !m_data_64)
+    return 0;
+  return (m_data_32 ? m_data_32->_used : m_data_64->_used);
+}
+
+bool lldb_private::formatters::NSDictionaryMLegacySyntheticFrontEnd::Update() {
+  m_children.clear();
+  ValueObjectSP valobj_sp = m_backend.GetSP();
+  m_ptr_size = 0;
+  delete m_data_32;
+  m_data_32 = nullptr;
+  delete m_data_64;
+  m_data_64 = nullptr;
+  if (!valobj_sp)
+    return false;
+  m_exe_ctx_ref = valobj_sp->GetExecutionContextRef();
+  Status error;
+  error.Clear();
+  lldb::ProcessSP process_sp(valobj_sp->GetProcessSP());
+  if (!process_sp)
+    return false;
+  m_ptr_size = process_sp->GetAddressByteSize();
+  m_order = process_sp->GetByteOrder();
+  uint64_t data_location = valobj_sp->GetValueAsUnsigned(0) + m_ptr_size;
+  if (m_ptr_size == 4) {
+    m_data_32 = new DataDescriptor_32();
+    process_sp->ReadMemory(data_location, m_data_32, sizeof(DataDescriptor_32),
+                           error);
+  } else {
+    m_data_64 = new DataDescriptor_64();
+    process_sp->ReadMemory(data_location, m_data_64, sizeof(DataDescriptor_64),
+                           error);
+  }
+  if (error.Fail())
+    return false;
+  return false;
+}
+
+bool lldb_private::formatters::NSDictionaryMLegacySyntheticFrontEnd::
+    MightHaveChildren() {
+  return true;
+}
+
+lldb::ValueObjectSP
+lldb_private::formatters::NSDictionaryMLegacySyntheticFrontEnd::GetChildAtIndex(
+    size_t idx) {
   lldb::addr_t m_keys_ptr =
       (m_data_32 ? m_data_32->_keys_addr : m_data_64->_keys_addr);
   lldb::addr_t m_values_ptr =




More information about the lldb-commits mailing list