[Lldb-commits] [lldb] 0eba9de - [lldb/Dataformatter] Add support to CF{Dictionary, Set}Ref types

Med Ismail Bennani via lldb-commits lldb-commits at lists.llvm.org
Fri May 15 13:14:54 PDT 2020


Author: Med Ismail Bennani
Date: 2020-05-15T22:14:39+02:00
New Revision: 0eba9de71e2add37dce165f3f3c9447772c3f65a

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

LOG: [lldb/Dataformatter] Add support to CF{Dictionary,Set}Ref types

This patch improves data formatting for CFDictionaryRef and CFSetRef.
It uses the same data-formatter as NSCFDictionaries and NSCFSets introduced
previously but did require some adjustments in Core::ValueObject.

Since the "Ref" types are opaque pointers to the actual CF containers, if the
value object has a synthetic value, lldb will use the opaque pointer's pointee
type to create the new ValueObjectChild needed to dereference the ValueObject.
This allows the "Ref" types to behaves the same as CF containers when used with
the `frame variable` command, the SBAPI or in Xcode's variable inspector.

This patch also adds support for incomplete types in ValueObject.

rdar://53104287

Differential Revision: https://reviews.llvm.org/D79554

Signed-off-by: Med Ismail Bennani <medismail.bennani at gmail.com>

Added: 
    

Modified: 
    lldb/source/Core/ValueObject.cpp
    lldb/source/Core/ValueObjectSyntheticFilter.cpp
    lldb/source/Plugins/Language/ObjC/NSDictionary.cpp
    lldb/source/Plugins/Language/ObjC/NSSet.cpp
    lldb/source/Plugins/Language/ObjC/ObjCLanguage.cpp
    lldb/test/API/functionalities/data-formatter/data-formatter-objc/TestDataFormatterObjCNSContainer.py
    lldb/test/API/functionalities/data-formatter/data-formatter-objc/main.m

Removed: 
    


################################################################################
diff  --git a/lldb/source/Core/ValueObject.cpp b/lldb/source/Core/ValueObject.cpp
index 59bd0c0209b6..3a6ca522f308 100644
--- a/lldb/source/Core/ValueObject.cpp
+++ b/lldb/source/Core/ValueObject.cpp
@@ -687,6 +687,11 @@ ValueObject *ValueObject::CreateChildAtIndex(size_t idx,
         language_flags);
   }
 
+  if (!valobj && synthetic_array_member)
+    valobj = GetSyntheticValue()
+                 ->GetChildAtIndex(synthetic_index, synthetic_array_member)
+                 .get();
+
   return valobj;
 }
 
@@ -2824,6 +2829,27 @@ ValueObjectSP ValueObject::Dereference(Status &error) {
           child_is_base_class, child_is_deref_of_parent, eAddressTypeInvalid,
           language_flags);
     }
+
+    // In case of incomplete child compiler type, use the pointee type and try
+    // to recreate a new ValueObjectChild using it.
+    if (!m_deref_valobj) {
+      if (HasSyntheticValue()) {
+        child_compiler_type = compiler_type.GetPointeeType();
+
+        if (child_compiler_type) {
+          ConstString child_name;
+          if (!child_name_str.empty())
+            child_name.SetCString(child_name_str.c_str());
+
+          m_deref_valobj = new ValueObjectChild(
+              *this, child_compiler_type, child_name, child_byte_size,
+              child_byte_offset, child_bitfield_bit_size,
+              child_bitfield_bit_offset, child_is_base_class,
+              child_is_deref_of_parent, eAddressTypeInvalid, language_flags);
+        }
+      }
+    }
+
   } else if (HasSyntheticValue()) {
     m_deref_valobj =
         GetSyntheticValue()

diff  --git a/lldb/source/Core/ValueObjectSyntheticFilter.cpp b/lldb/source/Core/ValueObjectSyntheticFilter.cpp
index 9ca9513aa583..32d1e6ab8368 100644
--- a/lldb/source/Core/ValueObjectSyntheticFilter.cpp
+++ b/lldb/source/Core/ValueObjectSyntheticFilter.cpp
@@ -53,7 +53,9 @@ ValueObjectSynthetic::ValueObjectSynthetic(ValueObject &parent,
       m_might_have_children(eLazyBoolCalculate),
       m_provides_value(eLazyBoolCalculate) {
   SetName(parent.GetName());
-  CopyValueData(m_parent);
+  // Copying the data of an incomplete type won't work as it has no byte size.
+  if (m_parent->GetCompilerType().IsCompleteType())
+    CopyValueData(m_parent);
   CreateSynthFilter();
 }
 
@@ -219,7 +221,9 @@ bool ValueObjectSynthetic::UpdateValue() {
               GetName().AsCString());
 
     m_provides_value = eLazyBoolNo;
-    CopyValueData(m_parent);
+    // Copying the data of an incomplete type won't work as it has no byte size.
+    if (m_parent->GetCompilerType().IsCompleteType())
+      CopyValueData(m_parent);
   }
 
   SetValueIsValid(true);

diff  --git a/lldb/source/Plugins/Language/ObjC/NSDictionary.cpp b/lldb/source/Plugins/Language/ObjC/NSDictionary.cpp
index 998c72e429e7..e4e51de9ddfc 100644
--- a/lldb/source/Plugins/Language/ObjC/NSDictionary.cpp
+++ b/lldb/source/Plugins/Language/ObjC/NSDictionary.cpp
@@ -408,7 +408,8 @@ bool lldb_private::formatters::NSDictionarySummaryProvider(
   static const ConstString g_DictionaryMImmutable("__NSDictionaryM_Immutable");
   static const ConstString g_Dictionary1("__NSSingleEntryDictionaryI");
   static const ConstString g_Dictionary0("__NSDictionary0");
-  static const ConstString g_DictionaryCF("__NSCFDictionary");
+  static const ConstString g_DictionaryCF("__CFDictionary");
+  static const ConstString g_DictionaryNSCF("__NSCFDictionary");
   static const ConstString g_DictionaryCFRef("CFDictionaryRef");
 
   if (class_name.IsEmpty())
@@ -420,6 +421,7 @@ bool lldb_private::formatters::NSDictionarySummaryProvider(
                                                       ptr_size, 0, error);
     if (error.Fail())
       return false;
+
     value &= (is_64bit ? ~0xFC00000000000000UL : ~0xFC000000U);
   } else if (class_name == g_DictionaryM || class_name == g_DictionaryMLegacy) {
     AppleObjCRuntime *apple_runtime =
@@ -439,7 +441,9 @@ bool lldb_private::formatters::NSDictionarySummaryProvider(
     value = 1;
   } else if (class_name == g_Dictionary0) {
     value = 0;
-  } else if (class_name == g_DictionaryCF || class_name == g_DictionaryCFRef) {
+  } else if (class_name == g_DictionaryCF ||
+             class_name == g_DictionaryNSCF ||
+             class_name == g_DictionaryCFRef) {
     ExecutionContext exe_ctx(process_sp);
     CFBasicHash cfbh;
     if (!cfbh.Update(valobj_addr, exe_ctx))
@@ -503,7 +507,8 @@ lldb_private::formatters::NSDictionarySyntheticFrontEndCreator(
   static const ConstString g_DictionaryImmutable("__NSDictionaryM_Immutable");
   static const ConstString g_DictionaryMLegacy("__NSDictionaryM_Legacy");
   static const ConstString g_Dictionary0("__NSDictionary0");
-  static const ConstString g_DictionaryCF("__NSCFDictionary");
+  static const ConstString g_DictionaryCF("__CFDictionary");
+  static const ConstString g_DictionaryNSCF("__NSCFDictionary");
   static const ConstString g_DictionaryCFRef("CFDictionaryRef");
 
   if (class_name.IsEmpty())
@@ -523,7 +528,9 @@ lldb_private::formatters::NSDictionarySyntheticFrontEndCreator(
       return (new Foundation1100::NSDictionaryMSyntheticFrontEnd(valobj_sp));
   } else if (class_name == g_Dictionary1) {
     return (new NSDictionary1SyntheticFrontEnd(valobj_sp));
-  } else if (class_name == g_DictionaryCF || class_name == g_DictionaryCFRef) {
+  } else if (class_name == g_DictionaryCF ||
+             class_name == g_DictionaryNSCF ||
+             class_name == g_DictionaryCFRef) {
     return (new NSCFDictionarySyntheticFrontEnd(valobj_sp));
   } else {
     auto &map(NSDictionary_Additionals::GetAdditionalSynthetics());

diff  --git a/lldb/source/Plugins/Language/ObjC/NSSet.cpp b/lldb/source/Plugins/Language/ObjC/NSSet.cpp
index 543a1c5978e0..4dbbe6fbddff 100644
--- a/lldb/source/Plugins/Language/ObjC/NSSet.cpp
+++ b/lldb/source/Plugins/Language/ObjC/NSSet.cpp
@@ -282,6 +282,7 @@ bool lldb_private::formatters::NSSetSummaryProvider(
   static const ConstString g_OrderedSetI("__NSOrderedSetI");
   static const ConstString g_SetM("__NSSetM");
   static const ConstString g_SetCF("__NSCFSet");
+  static const ConstString g_SetCFRef("CFSetRef");
 
   if (class_name.IsEmpty())
     return false;
@@ -306,7 +307,7 @@ bool lldb_private::formatters::NSSetSummaryProvider(
     }
     if (error.Fail())
       return false;
-  } else if (class_name == g_SetCF) {
+  } else if (class_name == g_SetCF || class_name == g_SetCFRef) {
     ExecutionContext exe_ctx(process_sp);
     CFBasicHash cfbh;
     if (!cfbh.Update(valobj_addr, exe_ctx))
@@ -367,6 +368,7 @@ lldb_private::formatters::NSSetSyntheticFrontEndCreator(
   static const ConstString g_OrderedSetI("__NSOrderedSetI");
   static const ConstString g_SetM("__NSSetM");
   static const ConstString g_SetCF("__NSCFSet");
+  static const ConstString g_SetCFRef("CFSetRef");
 
   if (class_name.IsEmpty())
     return nullptr;
@@ -386,7 +388,7 @@ lldb_private::formatters::NSSetSyntheticFrontEndCreator(
     } else {
       return (new Foundation1300::NSSetMSyntheticFrontEnd(valobj_sp));
     }
-  } else if (class_name == g_SetCF) {
+  } else if (class_name == g_SetCF || class_name == g_SetCFRef) {
     return (new NSCFSetSyntheticFrontEnd(valobj_sp));
   } else {
     auto &map(NSSet_Additionals::GetAdditionalSynthetics());

diff  --git a/lldb/source/Plugins/Language/ObjC/ObjCLanguage.cpp b/lldb/source/Plugins/Language/ObjC/ObjCLanguage.cpp
index 4acb4c0d216a..29391daaab93 100644
--- a/lldb/source/Plugins/Language/ObjC/ObjCLanguage.cpp
+++ b/lldb/source/Plugins/Language/ObjC/ObjCLanguage.cpp
@@ -446,6 +446,10 @@ static void LoadObjCFormatters(TypeCategoryImplSP objc_category_sp) {
                 lldb_private::formatters::NSDictionarySummaryProvider<true>,
                 "NSDictionary summary provider", ConstString("CFDictionaryRef"),
                 appkit_flags);
+  AddCXXSummary(objc_category_sp,
+                lldb_private::formatters::NSDictionarySummaryProvider<true>,
+                "NSDictionary summary provider", ConstString("__CFDictionary"),
+                appkit_flags);
   AddCXXSummary(objc_category_sp,
                 lldb_private::formatters::NSDictionarySummaryProvider<true>,
                 "NSDictionary summary provider",
@@ -466,6 +470,9 @@ static void LoadObjCFormatters(TypeCategoryImplSP objc_category_sp) {
   AddCXXSummary(objc_category_sp,
                 lldb_private::formatters::NSSetSummaryProvider<false>,
                 "__NSCFSet summary", ConstString("__NSCFSet"), appkit_flags);
+  AddCXXSummary(objc_category_sp,
+                lldb_private::formatters::NSSetSummaryProvider<false>,
+                "__CFSet summary", ConstString("__CFSet"), appkit_flags);
   AddCXXSummary(objc_category_sp,
                 lldb_private::formatters::NSSetSummaryProvider<false>,
                 "__NSSetI summary", ConstString("__NSSetI"), appkit_flags);
@@ -584,6 +591,11 @@ static void LoadObjCFormatters(TypeCategoryImplSP objc_category_sp) {
       lldb_private::formatters::NSDictionarySyntheticFrontEndCreator,
       "NSDictionary synthetic children", ConstString("CFMutableDictionaryRef"),
       ScriptedSyntheticChildren::Flags());
+  AddCXXSynthetic(
+      objc_category_sp,
+      lldb_private::formatters::NSDictionarySyntheticFrontEndCreator,
+      "NSDictionary synthetic children", ConstString("__CFDictionary"),
+      ScriptedSyntheticChildren::Flags());
 
   AddCXXSynthetic(objc_category_sp,
                   lldb_private::formatters::NSErrorSyntheticFrontEndCreator,
@@ -610,6 +622,10 @@ static void LoadObjCFormatters(TypeCategoryImplSP objc_category_sp) {
                   lldb_private::formatters::NSSetSyntheticFrontEndCreator,
                   "__NSCFSet synthetic children", ConstString("__NSCFSet"),
                   ScriptedSyntheticChildren::Flags());
+  AddCXXSynthetic(objc_category_sp,
+                  lldb_private::formatters::NSSetSyntheticFrontEndCreator,
+                  "CFSetRef synthetic children", ConstString("CFSetRef"),
+                  ScriptedSyntheticChildren::Flags());
 
   AddCXXSynthetic(
       objc_category_sp, lldb_private::formatters::NSSetSyntheticFrontEndCreator,
@@ -627,6 +643,10 @@ static void LoadObjCFormatters(TypeCategoryImplSP objc_category_sp) {
       objc_category_sp, lldb_private::formatters::NSSetSyntheticFrontEndCreator,
       "__NSOrderedSetM synthetic children", ConstString("__NSOrderedSetM"),
       ScriptedSyntheticChildren::Flags());
+  AddCXXSynthetic(objc_category_sp,
+                  lldb_private::formatters::NSSetSyntheticFrontEndCreator,
+                  "__CFSet synthetic children", ConstString("__CFSet"),
+                  ScriptedSyntheticChildren::Flags());
 
   AddCXXSynthetic(objc_category_sp,
                   lldb_private::formatters::NSIndexPathSyntheticFrontEndCreator,

diff  --git a/lldb/test/API/functionalities/data-formatter/data-formatter-objc/TestDataFormatterObjCNSContainer.py b/lldb/test/API/functionalities/data-formatter/data-formatter-objc/TestDataFormatterObjCNSContainer.py
index 67a5dff6c2d5..d13d5d5df1d5 100644
--- a/lldb/test/API/functionalities/data-formatter/data-formatter-objc/TestDataFormatterObjCNSContainer.py
+++ b/lldb/test/API/functionalities/data-formatter/data-formatter-objc/TestDataFormatterObjCNSContainer.py
@@ -32,7 +32,7 @@ def nscontainers_data_formatter_commands(self):
                 '(NSDictionary *) nscfDictionary = ',
                 ' 4 key/value pairs',
                 '(CFDictionaryRef) cfDictionaryRef = ',
-                ' 3 key/value pairs',
+                ' 2 key/value pairs',
                 '(NSDictionary *) newMutableDictionary = ',
                 ' 21 key/value pairs',
                 '(CFArrayRef) cfarray_ref = ',
@@ -57,10 +57,23 @@ def nscontainers_data_formatter_commands(self):
 
 
         self.expect(
-          'frame var nscfSet',
+            'frame variable -d run-target *cfDictionaryRef',
+            patterns=[
+                '\(const __CFDictionary\) \*cfDictionaryRef =',
+                'key = 0x.* @"foo"',
+                'value = 0x.* @"foo"',
+                'key = 0x.* @"bar"',
+                'value = 0x.* @"bar"',
+                ])
+
+
+        self.expect(
+          'frame var nscfSet cfSetRef',
           substrs=[
           '(NSSet *) nscfSet = ',
           '2 elements',
+          '(CFSetRef) cfSetRef = ',
+          '2 elements',
           ])
 
         self.expect(
@@ -71,6 +84,14 @@ def nscontainers_data_formatter_commands(self):
               '\[1\] = 0x.* @".*"',
                     ])
 
+        self.expect(
+          'frame variable -d run-target *cfSetRef',
+          patterns=[
+              '\(const __CFSet\) \*cfSetRef =',
+              '\[0\] = 0x.* @".*"',
+              '\[1\] = 0x.* @".*"',
+                    ])
+
         self.expect(
             'frame variable iset1 iset2 imset',
             substrs=['4 indexes', '512 indexes', '10 indexes'])

diff  --git a/lldb/test/API/functionalities/data-formatter/data-formatter-objc/main.m b/lldb/test/API/functionalities/data-formatter/data-formatter-objc/main.m
index 3637fbc795de..df96a5e59b5b 100644
--- a/lldb/test/API/functionalities/data-formatter/data-formatter-objc/main.m
+++ b/lldb/test/API/functionalities/data-formatter/data-formatter-objc/main.m
@@ -482,8 +482,7 @@ int main(int argc, const char *argv[]) {
       CFDictionaryCreate(nil, (void *)cfKeys, (void *)cfValues, 2, nil, nil));
   NSDictionary *nscfDictionary = CFBridgingRelease(
       CFDictionaryCreate(nil, (void *)cfKeys, (void *)cfValues, 4, nil, nil));
-  CFDictionaryRef cfDictionaryRef =
-      CFDictionaryCreate(nil, (void *)cfKeys, (void *)cfValues, 3, nil, nil);
+  CFDictionaryRef cfDictionaryRef = (__bridge CFDictionaryRef)nsDictionary;
 
   NSAttributedString *attrString =
       [[NSAttributedString alloc] initWithString:@"hello world from foo"
@@ -542,6 +541,7 @@ int main(int argc, const char *argv[]) {
   [nsmutableset addObject:str4];
   NSSet *nscfSet =
       CFBridgingRelease(CFSetCreate(nil, (void *)cfValues, 2, nil));
+  CFSetRef cfSetRef = (__bridge CFSetRef)nscfSet;
 
   CFDataRef data_ref =
       CFDataCreate(kCFAllocatorDefault, [immutableData bytes], 5);


        


More information about the lldb-commits mailing list