[Lldb-commits] [lldb] r136763 - in /lldb/trunk: include/lldb/Core/FormatManager.h source/Core/ValueObject.cpp source/Core/ValueObjectDynamicValue.cpp source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp test/functionalities/data-formatter/data-formatter-objc/TestDataFormatterObjC.py test/lang/objc/objc-dynamic-value/TestObjCDynamicValue.py

Enrico Granata granata.enrico at gmail.com
Tue Aug 2 19:18:51 PDT 2011


Author: enrico
Date: Tue Aug  2 21:18:51 2011
New Revision: 136763

URL: http://llvm.org/viewvc/llvm-project?rev=136763&view=rev
Log:
Fixed an issue where the KVO swizzled type would be returned as the dynamic type instead of the actual user-level type
 - see the test case in lang/objc/objc-dynamic-value for an example
Objective-C dynamic type lookup now works for every Objective-C type
 - previously, true dynamic lookup was only performed for type id

Modified:
    lldb/trunk/include/lldb/Core/FormatManager.h
    lldb/trunk/source/Core/ValueObject.cpp
    lldb/trunk/source/Core/ValueObjectDynamicValue.cpp
    lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp
    lldb/trunk/test/functionalities/data-formatter/data-formatter-objc/TestDataFormatterObjC.py
    lldb/trunk/test/lang/objc/objc-dynamic-value/TestObjCDynamicValue.py

Modified: lldb/trunk/include/lldb/Core/FormatManager.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Core/FormatManager.h?rev=136763&r1=136762&r2=136763&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Core/FormatManager.h (original)
+++ lldb/trunk/include/lldb/Core/FormatManager.h Tue Aug  2 21:18:51 2011
@@ -360,12 +360,13 @@
             if (log)
                 log->Printf("appended bitfield info, final result is %s", name.GetCString());
         }
+        const char* typeName = name.GetCString();
         if (log)
             log->Printf("trying to get %s for VO name %s of type %s",
                         m_name.c_str(),
                         vobj.GetName().AsCString(),
-                        name.AsCString());
-        if (Get(name.GetCString(), entry))
+                        typeName);
+        if (Get(typeName, entry))
         {
             if (log)
                 log->Printf("direct match found, returning");
@@ -385,7 +386,8 @@
             }
         }
         if (use_dynamic != lldb::eNoDynamicValues &&
-            typePtr == vobj.GetClangAST()->ObjCBuiltinIdTy.getTypePtr())
+            (/*strstr(typeName, "id") == typeName ||*/
+             ClangASTType::GetMinimumLanguage(vobj.GetClangAST(), vobj.GetClangType()) == lldb::eLanguageTypeObjC))
         {
             if (log)
                 log->Printf("this is an ObjC 'id', let's do dynamic search");

Modified: lldb/trunk/source/Core/ValueObject.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/ValueObject.cpp?rev=136763&r1=136762&r2=136763&view=diff
==============================================================================
--- lldb/trunk/source/Core/ValueObject.cpp (original)
+++ lldb/trunk/source/Core/ValueObject.cpp Tue Aug  2 21:18:51 2011
@@ -93,7 +93,7 @@
     m_is_bitfield_for_scalar(false),
     m_is_expression_path_child(false),
     m_is_child_at_offset(false),
-    m_is_expression_result(false),
+    m_is_expression_result(parent.m_is_expression_result),
     m_dump_printable_counter(0)
 {
     m_manager->ManageObject(this);
@@ -240,7 +240,7 @@
 
         m_synthetic_value = NULL;
         
-        Debugger::Formatting::ValueFormats::Get(*this, use_dynamic, m_last_value_format);
+        Debugger::Formatting::ValueFormats::Get(*this, lldb::eNoDynamicValues, m_last_value_format);
         Debugger::Formatting::GetSummaryFormat(*this, use_dynamic, m_last_summary_format);
         Debugger::Formatting::GetSyntheticFilter(*this, use_dynamic, m_last_synthetic_filter);
 
@@ -2599,23 +2599,26 @@
             // Always show the type for the top level items.
             if (show_types || (curr_depth == 0 && !flat_output))
             {
-                s.Printf("(%s", valobj->GetTypeName().AsCString("<invalid type>"));
-                if (use_dynamic != lldb::eNoDynamicValues &&
-                    strcmp(valobj->GetTypeName().AsCString("NULL"), "id") == 0)
+                const char* typeName = valobj->GetTypeName().AsCString("<invalid type>");
+                s.Printf("(%s", typeName);
+                // only show dynamic types if the user really wants to see types
+                if (show_types && use_dynamic != lldb::eNoDynamicValues &&
+                    (/*strstr(typeName, "id") == typeName ||*/
+                     ClangASTType::GetMinimumLanguage(valobj->GetClangAST(), valobj->GetClangType()) == lldb::eLanguageTypeObjC))
                 {
                     Process* process = valobj->GetUpdatePoint().GetProcessSP().get();
                     if (process == NULL)
-                        s.Printf(") ");
+                        s.Printf(", dynamic type: unknown) ");
                     else
                     {
                         ObjCLanguageRuntime *runtime = process->GetObjCLanguageRuntime();
                         if (runtime == NULL)
-                            s.Printf(") ");
+                            s.Printf(", dynamic type: unknown) ");
                         else
                         {
                             ObjCLanguageRuntime::ObjCISA isa = runtime->GetISA(*valobj);
                             if (!runtime->IsValidISA(isa))
-                                s.Printf(") ");
+                                s.Printf(", dynamic type: unknown) ");
                             else
                                 s.Printf(", dynamic type: %s) ",
                                          runtime->GetActualTypeName(isa).GetCString());

Modified: lldb/trunk/source/Core/ValueObjectDynamicValue.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/ValueObjectDynamicValue.cpp?rev=136763&r1=136762&r2=136763&view=diff
==============================================================================
--- lldb/trunk/source/Core/ValueObjectDynamicValue.cpp (original)
+++ lldb/trunk/source/Core/ValueObjectDynamicValue.cpp Tue Aug  2 21:18:51 2011
@@ -160,7 +160,7 @@
         {
             LanguageRuntime *objc_runtime = process->GetLanguageRuntime (lldb::eLanguageTypeObjC);
             if (objc_runtime)
-                found_dynamic_type = cpp_runtime->GetDynamicTypeAndAddress (*m_parent, m_use_dynamic, class_type_or_name, dynamic_address);
+                found_dynamic_type = objc_runtime->GetDynamicTypeAndAddress (*m_parent, m_use_dynamic, class_type_or_name, dynamic_address);
         }
     }
     

Modified: lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp?rev=136763&r1=136762&r2=136763&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp (original)
+++ lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp Tue Aug  2 21:18:51 2011
@@ -26,6 +26,7 @@
 #include "lldb/Core/PluginManager.h"
 #include "lldb/Core/Scalar.h"
 #include "lldb/Core/StreamString.h"
+#include "lldb/Core/ValueObjectConstResult.h"
 #include "lldb/Expression/ClangFunction.h"
 #include "lldb/Expression/ClangUtilityFunction.h"
 #include "lldb/Symbol/ClangASTContext.h"
@@ -566,9 +567,35 @@
 lldb_private::ObjCLanguageRuntime::ObjCISA
 AppleObjCRuntimeV2::GetISA(ValueObject& valobj)
 {
+    
+    if (valobj.GetIsExpressionResult() &&
+        valobj.GetValue().GetValueType() == Value::eValueTypeHostAddress)
+    {
+        // when using the expression parser, an additional layer of "frozen data"
+        // can be created, which is basically a byte-exact copy of the data returned
+        // by the expression, but in host memory. because Python code might need to read
+        // into the object memory in non-obvious ways, we need to hand it the target version
+        // of the expression output
+        lldb::addr_t tgt_address = valobj.GetValueAsUnsigned();
+        ValueObjectSP target_object = ValueObjectConstResult::Create (valobj.GetExecutionContextScope(),
+                                                                      valobj.GetClangAST(),
+                                                                      valobj.GetClangType(),
+                                                                      valobj.GetName(),
+                                                                      tgt_address,
+                                                                      eAddressTypeLoad,
+                                                                      valobj.GetUpdatePoint().GetProcessSP()->GetAddressByteSize());
+        return GetISA(*target_object);
+    }
+    
     if (ClangASTType::GetMinimumLanguage(valobj.GetClangAST(),valobj.GetClangType()) != lldb::eLanguageTypeObjC)
         return 0;
     
+    // if we get an invalid VO (which might still happen when playing around
+    // with pointers returned by the expression parser, don't consider this
+    // a valid ObjC object)
+    if (valobj.GetValue().GetContextType() == Value::eContextTypeInvalid)
+        return 0;
+    
     uint32_t offset = 0;
     uint64_t isa_pointer = valobj.GetDataExtractor().GetPointer(&offset);
     
@@ -583,6 +610,8 @@
     return isa;
 }
 
+// TODO: should we have a transparent_kvo parameter here to say if we 
+// want to replace the KVO swizzled class with the actual user-level type?
 ConstString
 AppleObjCRuntimeV2::GetActualTypeName(lldb_private::ObjCLanguageRuntime::ObjCISA isa)
 {
@@ -625,7 +654,20 @@
     //printf("name_pointer: %llx\n", name_pointer);
     char* cstr = new char[512];
     if (m_process->ReadCStringFromMemory(name_pointer, cstr, 512) > 0)
-        return ConstString(cstr);
+    {
+        if (::strstr(cstr, "NSKVONotify") == cstr)
+        {
+            // the ObjC runtime implements KVO by replacing the isa with a special
+            // NSKVONotifying_className that overrides the relevant methods
+            // the side effect on us is that getting the typename for a KVO-ed object
+            // will return the swizzled class instead of the actual one
+            // this swizzled class is a descendant of the real class, so just
+            // return the parent type and all should be fine
+            return GetActualTypeName(GetParentClass(isa));
+        }
+        else
+            return ConstString(cstr);
+    }
     else
         return ConstString("unknown");
 }

Modified: lldb/trunk/test/functionalities/data-formatter/data-formatter-objc/TestDataFormatterObjC.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/functionalities/data-formatter/data-formatter-objc/TestDataFormatterObjC.py?rev=136763&r1=136762&r2=136763&view=diff
==============================================================================
--- lldb/trunk/test/functionalities/data-formatter/data-formatter-objc/TestDataFormatterObjC.py (original)
+++ lldb/trunk/test/functionalities/data-formatter/data-formatter-objc/TestDataFormatterObjC.py Tue Aug  2 21:18:51 2011
@@ -226,9 +226,12 @@
                     substrs = ['Process Name:  a.out Process Id:'])
         self.expect('frame variable dyn_test', matching=False,
                     substrs = ['Process Name:  a.out Process Id:'])
-        self.expect('frame variable dyn_test -d run-target',
+        self.expect('frame variable dyn_test -d run-target -T',
                     substrs = ['(id, dynamic type:',
                                'Process Name:  a.out Process Id:'])
+        self.expect('frame variable dyn_test -d run-target',
+                    substrs = ['(id)',
+                               'Process Name:  a.out Process Id:'])
 
             
         # check that we can format stuff out of the expression parser

Modified: lldb/trunk/test/lang/objc/objc-dynamic-value/TestObjCDynamicValue.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/lang/objc/objc-dynamic-value/TestObjCDynamicValue.py?rev=136763&r1=136762&r2=136763&view=diff
==============================================================================
--- lldb/trunk/test/lang/objc/objc-dynamic-value/TestObjCDynamicValue.py (original)
+++ lldb/trunk/test/lang/objc/objc-dynamic-value/TestObjCDynamicValue.py Tue Aug  2 21:18:51 2011
@@ -93,6 +93,14 @@
 
         self.expect('frame var -d run-target myObserver->_source', 'frame var finds its way into a child member',
             patterns = ['\(SourceDerived \*\)'])
+        
+        # check that our ObjC GetISA() does a good job at hiding KVO swizzled classes
+        
+        self.expect('frame var -d run-target myObserver->_source -T', 'the KVO-ed class is hidden',
+                    substrs = ['dynamic type: SourceDerived'])
+
+        self.expect('frame var -d run-target myObserver->_source -T', 'the KVO-ed class is hidden', matching = False,
+                    substrs = ['dynamic type: NSKVONotify'])
 
         # This test is not entirely related to the main thrust of this test case, but since we're here,
         # try stepping into setProperty, and make sure we get into the version in Source:





More information about the lldb-commits mailing list