[Lldb-commits] [lldb] r163155 - in /lldb/trunk: examples/summaries/cocoa/ include/lldb/Core/ include/lldb/Target/ lldb.xcodeproj/ source/API/ source/Core/ source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/ source/Target/ test/functionalities/data-formatter/data-formatter-objc/

Enrico Granata egranata at apple.com
Tue Sep 4 11:47:54 PDT 2012


Author: enrico
Date: Tue Sep  4 13:47:54 2012
New Revision: 163155

URL: http://llvm.org/viewvc/llvm-project?rev=163155&view=rev
Log:
<rdar://problem/11485744> Implement important data formatters in C++. Have the Objective-C language runtime plugin expose class descriptors objects akin to the objc_runtime.py Pythonic implementation. Rewrite the data formatters for some core Cocoa classes in C++ instead of Python.

Modified:
    lldb/trunk/examples/summaries/cocoa/CFArray.py
    lldb/trunk/examples/summaries/cocoa/CFDictionary.py
    lldb/trunk/examples/summaries/cocoa/NSData.py
    lldb/trunk/examples/summaries/cocoa/NSNumber.py
    lldb/trunk/include/lldb/Core/FormatClasses.h
    lldb/trunk/include/lldb/Core/Module.h
    lldb/trunk/include/lldb/Target/ObjCLanguageRuntime.h
    lldb/trunk/lldb.xcodeproj/project.pbxproj
    lldb/trunk/source/API/SBModule.cpp
    lldb/trunk/source/API/SBTypeSummary.cpp
    lldb/trunk/source/Core/FormatClasses.cpp
    lldb/trunk/source/Core/FormatManager.cpp
    lldb/trunk/source/Core/Module.cpp
    lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.h
    lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.cpp
    lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.h
    lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp
    lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.h
    lldb/trunk/source/Target/ObjCLanguageRuntime.cpp
    lldb/trunk/test/functionalities/data-formatter/data-formatter-objc/TestDataFormatterObjC.py

Modified: lldb/trunk/examples/summaries/cocoa/CFArray.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/examples/summaries/cocoa/CFArray.py?rev=163155&r1=163154&r2=163155&view=diff
==============================================================================
--- lldb/trunk/examples/summaries/cocoa/CFArray.py (original)
+++ lldb/trunk/examples/summaries/cocoa/CFArray.py Tue Sep  4 13:47:54 2012
@@ -5,7 +5,8 @@
 This file is distributed under the University of Illinois Open Source
 License. See LICENSE.TXT for details.
 """
-# synthetic children provider for NSArray
+# example summary provider for NSArray
+# the real summary is now C++ code built into LLDB
 import lldb
 import ctypes
 import lldb.runtime.objc.objc_runtime

Modified: lldb/trunk/examples/summaries/cocoa/CFDictionary.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/examples/summaries/cocoa/CFDictionary.py?rev=163155&r1=163154&r2=163155&view=diff
==============================================================================
--- lldb/trunk/examples/summaries/cocoa/CFDictionary.py (original)
+++ lldb/trunk/examples/summaries/cocoa/CFDictionary.py Tue Sep  4 13:47:54 2012
@@ -5,7 +5,8 @@
 This file is distributed under the University of Illinois Open Source
 License. See LICENSE.TXT for details.
 """
-# summary provider for NSDictionary
+# example summary provider for NSDictionary
+# the real summary is now C++ code built into LLDB
 import lldb
 import ctypes
 import lldb.runtime.objc.objc_runtime

Modified: lldb/trunk/examples/summaries/cocoa/NSData.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/examples/summaries/cocoa/NSData.py?rev=163155&r1=163154&r2=163155&view=diff
==============================================================================
--- lldb/trunk/examples/summaries/cocoa/NSData.py (original)
+++ lldb/trunk/examples/summaries/cocoa/NSData.py Tue Sep  4 13:47:54 2012
@@ -5,7 +5,8 @@
 This file is distributed under the University of Illinois Open Source
 License. See LICENSE.TXT for details.
 """
-# summary provider for NSData
+# example summary provider for NSData
+# the real summary is now C++ code built into LLDB
 import lldb
 import ctypes
 import lldb.runtime.objc.objc_runtime

Modified: lldb/trunk/examples/summaries/cocoa/NSNumber.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/examples/summaries/cocoa/NSNumber.py?rev=163155&r1=163154&r2=163155&view=diff
==============================================================================
--- lldb/trunk/examples/summaries/cocoa/NSNumber.py (original)
+++ lldb/trunk/examples/summaries/cocoa/NSNumber.py Tue Sep  4 13:47:54 2012
@@ -5,7 +5,8 @@
 This file is distributed under the University of Illinois Open Source
 License. See LICENSE.TXT for details.
 """
-# summary provider for NSNumber
+# example summary provider for NSNumber
+# the real summary is now C++ code built into LLDB
 import lldb
 import ctypes
 import lldb.runtime.objc.objc_runtime

Modified: lldb/trunk/include/lldb/Core/FormatClasses.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Core/FormatClasses.h?rev=163155&r1=163154&r2=163155&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Core/FormatClasses.h (original)
+++ lldb/trunk/include/lldb/Core/FormatClasses.h Tue Sep  4 13:47:54 2012
@@ -1091,6 +1091,14 @@
         uint32_t m_flags;
     };
     
+    typedef enum Type
+    {
+        eTypeUnknown,
+        eTypeString,
+        eTypeScript,
+        eTypeCallback
+    } Type;
+    
     TypeSummaryImpl (const TypeSummaryImpl::Flags& flags);
     
     bool
@@ -1205,6 +1213,9 @@
     virtual bool
     IsScripted() = 0;
     
+    virtual Type
+    GetType () = 0;
+    
     uint32_t&
     GetRevision ()
     {
@@ -1265,9 +1276,89 @@
     }
 
     
+    virtual Type
+    GetType ()
+    {
+        return TypeSummaryImpl::eTypeString;
+    }
+    
 private:
     DISALLOW_COPY_AND_ASSIGN(StringSummaryFormat);
 };
+
+// summaries implemented via a C++ function
+struct CXXFunctionSummaryFormat : public TypeSummaryImpl
+{
+    
+    // we should convert these to SBValue and SBStream if we ever cross
+    // the boundary towards the external world
+    typedef bool (*Callback)(ValueObject& valobj,
+                             Stream& dest);
+    
+    
+    Callback m_impl;
+    std::string m_description;
+    
+    CXXFunctionSummaryFormat(const TypeSummaryImpl::Flags& flags,
+                             Callback impl,
+                             const char* description);
+    
+    Callback
+    GetBackendFunction () const
+    {
+        return m_impl;
+    }
+    
+    const char*
+    GetTextualInfo () const
+    {
+        return m_description.c_str();
+    }
+    
+    void
+    SetBackendFunction (Callback cb_func)
+    {
+        m_impl = cb_func;
+    }
+    
+    void
+    SetTextualInfo (const char* descr)
+    {
+        if (descr)
+            m_description.assign(descr);
+        else
+            m_description.clear();
+    }
+    
+    virtual
+    ~CXXFunctionSummaryFormat()
+    {
+    }
+    
+    virtual bool
+    FormatObject(ValueObject *valobj,
+                 std::string& dest);
+    
+    virtual std::string
+    GetDescription();
+    
+    virtual bool
+    IsScripted()
+    {
+        return false;
+    }
+    
+    virtual Type
+    GetType ()
+    {
+        return TypeSummaryImpl::eTypeCallback;
+    }
+    
+    typedef STD_SHARED_PTR(CXXFunctionSummaryFormat) SharedPointer;
+
+private:
+    DISALLOW_COPY_AND_ASSIGN(CXXFunctionSummaryFormat);
+};
     
 #ifndef LLDB_DISABLE_PYTHON
 
@@ -1331,6 +1422,12 @@
         return true;
     }
     
+    virtual Type
+    GetType ()
+    {
+        return TypeSummaryImpl::eTypeScript;
+    }
+    
     typedef STD_SHARED_PTR(ScriptSummaryFormat) SharedPointer;
 
     

Modified: lldb/trunk/include/lldb/Core/Module.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Core/Module.h?rev=163155&r1=163154&r2=163155&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Core/Module.h (original)
+++ lldb/trunk/include/lldb/Core/Module.h Tue Sep  4 13:47:54 2012
@@ -571,6 +571,9 @@
     //------------------------------------------------------------------
     virtual ObjectFile *
     GetObjectFile ();
+    
+    uint32_t
+    GetVersion (uint32_t *versions, uint32_t num_versions);
 
     // Load an object file from memory.
     ObjectFile *

Modified: lldb/trunk/include/lldb/Target/ObjCLanguageRuntime.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Target/ObjCLanguageRuntime.h?rev=163155&r1=163154&r2=163155&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Target/ObjCLanguageRuntime.h (original)
+++ lldb/trunk/include/lldb/Target/ObjCLanguageRuntime.h Tue Sep  4 13:47:54 2012
@@ -29,6 +29,145 @@
     public LanguageRuntime
 {
 public:
+    
+    typedef lldb::addr_t ObjCISA;
+    
+    class ClassDescriptor;
+    typedef STD_SHARED_PTR(ClassDescriptor) ClassDescriptorSP;
+    
+    // the information that we want to support retrieving from an ObjC class
+    // this needs to be pure virtual since there are at least 2 different implementations
+    // of the runtime, and more might come
+    class ClassDescriptor
+    {
+    public:
+        
+        ClassDescriptor() :
+        m_is_kvo(eLazyBoolCalculate),
+        m_is_cf(eLazyBoolCalculate)
+        {}
+        
+        ClassDescriptor (ObjCISA isa, lldb::ProcessSP process)  :
+        m_is_kvo(eLazyBoolCalculate),
+        m_is_cf(eLazyBoolCalculate)
+        {}
+        
+        virtual ConstString
+        GetClassName () = 0;
+        
+        virtual ClassDescriptorSP
+        GetSuperclass () = 0;
+        
+        // virtual if any implementation has some other version-specific rules
+        // but for the known v1/v2 this is all that needs to be done
+        virtual bool
+        IsKVO ()
+        {
+            if (m_is_kvo == eLazyBoolCalculate)
+            {
+                const char* class_name = GetClassName().AsCString();
+                m_is_kvo = (LazyBool)(strstr(class_name,"NSKVONotifying_") == class_name);
+            }
+            return (m_is_kvo == eLazyBoolYes);
+        }
+        
+        // virtual if any implementation has some other version-specific rules
+        // but for the known v1/v2 this is all that needs to be done
+        virtual bool
+        IsCFType ()
+        {
+            if (m_is_cf == eLazyBoolCalculate)
+            {
+                const char* class_name = GetClassName().AsCString();
+                m_is_cf = (LazyBool)(strcmp(class_name,"__NSCFType") == 0 ||
+                                     strcmp(class_name,"NSCFType") == 0);
+            }
+            return (m_is_cf == eLazyBoolYes);
+        }
+        
+        virtual bool
+        IsValid () = 0;
+        
+        virtual bool
+        IsTagged () = 0;
+        
+        virtual uint64_t
+        GetInstanceSize () = 0;
+        
+        // use to implement version-specific additional constraints on pointers
+        virtual bool
+        CheckPointer (lldb::addr_t value,
+                      uint32_t ptr_size)
+        {
+            return true;
+        }
+        
+        virtual ObjCISA
+        GetISA () = 0;
+        
+        virtual
+        ~ClassDescriptor ()
+        {}
+        
+    protected:
+        bool
+        IsPointerValid (lldb::addr_t value,
+                        uint32_t ptr_size,
+                        bool allow_NULLs = false,
+                        bool allow_tagged = false,
+                        bool check_version_specific = false);
+        
+    private:
+        LazyBool m_is_kvo;
+        LazyBool m_is_cf;
+    };
+    
+    // a convenience subclass of ClassDescriptor meant to represent invalid objects
+    class ClassDescriptor_Invalid : public ClassDescriptor
+    {
+    public:
+        ClassDescriptor_Invalid() {}
+        
+        virtual ConstString
+        GetClassName () { return ConstString(""); }
+        
+        virtual ClassDescriptorSP
+        GetSuperclass () { return ClassDescriptorSP(new ClassDescriptor_Invalid()); }
+        
+        virtual bool
+        IsValid () { return false; }
+        
+        virtual bool
+        IsTagged () { return false; }
+        
+        virtual uint64_t
+        GetInstanceSize () { return 0; }
+        
+        virtual ObjCISA
+        GetISA () { return 0; }
+        
+        virtual bool
+        CheckPointer (lldb::addr_t value,
+                      uint32_t ptr_size) { return false; }
+        
+        virtual
+        ~ClassDescriptor_Invalid ()
+        {}
+        
+    };
+    
+    virtual ClassDescriptorSP
+    GetClassDescriptor (ValueObject& in_value)
+    {
+        return ClassDescriptorSP();
+    }
+    
+    virtual ClassDescriptorSP
+    GetClassDescriptor (ObjCISA isa)
+    {
+        return ClassDescriptorSP();
+    }
+    
     virtual
     ~ObjCLanguageRuntime();
     
@@ -77,8 +216,6 @@
         return eObjC_VersionUnknown;
     }
         
-    typedef lldb::addr_t ObjCISA;
-    
     virtual bool
     IsValidISA(ObjCISA isa) = 0;
     
@@ -86,10 +223,10 @@
     GetISA(ValueObject& valobj) = 0;
     
     virtual ConstString
-    GetActualTypeName(ObjCISA isa) = 0;
+    GetActualTypeName(ObjCISA isa);
     
     virtual ObjCISA
-    GetParentClass(ObjCISA isa) = 0;
+    GetParentClass(ObjCISA isa);
     
     virtual SymbolVendor *
     GetSymbolVendor()
@@ -267,6 +404,11 @@
     
     LazyBool m_has_new_literals_and_indexing;
 protected:
+    
+    typedef std::map<ObjCISA, ClassDescriptorSP> ISAToDescriptorMap;
+    typedef ISAToDescriptorMap::iterator ISAToDescriptorIterator;
+    ISAToDescriptorMap                  m_isa_to_descriptor_cache;
+    
     typedef std::map<lldb::addr_t,TypeAndOrName> ClassNameMap;
     typedef ClassNameMap::iterator ClassNameIterator;
     ClassNameMap m_class_name_cache;

Modified: lldb/trunk/lldb.xcodeproj/project.pbxproj
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/lldb.xcodeproj/project.pbxproj?rev=163155&r1=163154&r2=163155&view=diff
==============================================================================
--- lldb/trunk/lldb.xcodeproj/project.pbxproj (original)
+++ lldb/trunk/lldb.xcodeproj/project.pbxproj Tue Sep  4 13:47:54 2012
@@ -529,6 +529,7 @@
 		9475C18F14E5F858001BFC6D /* SBTypeNameSpecifier.h in Headers */ = {isa = PBXBuildFile; fileRef = 9475C18C14E5F826001BFC6D /* SBTypeNameSpecifier.h */; settings = {ATTRIBUTES = (Public, ); }; };
 		949ADF031406F648004833E1 /* ValueObjectConstResultImpl.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 949ADF021406F648004833E1 /* ValueObjectConstResultImpl.cpp */; };
 		94B6E76213D88365005F417F /* ValueObjectSyntheticFilter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 94B6E76113D88362005F417F /* ValueObjectSyntheticFilter.cpp */; };
+		94CDEB9D15F0258500DD2A7A /* CXXFormatterFunctions.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 94CDEB9C15F0258400DD2A7A /* CXXFormatterFunctions.cpp */; };
 		94EA1D5C15E6C9B400D4171A /* PythonDataObjects.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 94EA1D5B15E6C9B400D4171A /* PythonDataObjects.cpp */; };
 		94FA3DE01405D50400833217 /* ValueObjectConstResultChild.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 94FA3DDF1405D50300833217 /* ValueObjectConstResultChild.cpp */; };
 		9A19A6AF1163BBB200E0D453 /* SBValue.h in Headers */ = {isa = PBXBuildFile; fileRef = 9A19A6A51163BB7E00E0D453 /* SBValue.h */; settings = {ATTRIBUTES = (Public, ); }; };
@@ -1535,6 +1536,8 @@
 		94A9112D13D5DF210046D8A6 /* FormatClasses.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = FormatClasses.cpp; path = source/Core/FormatClasses.cpp; sourceTree = "<group>"; };
 		94B6E76013D8833C005F417F /* ValueObjectSyntheticFilter.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = ValueObjectSyntheticFilter.h; path = include/lldb/Core/ValueObjectSyntheticFilter.h; sourceTree = "<group>"; };
 		94B6E76113D88362005F417F /* ValueObjectSyntheticFilter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ValueObjectSyntheticFilter.cpp; path = source/Core/ValueObjectSyntheticFilter.cpp; sourceTree = "<group>"; };
+		94CDEB9A15F0226900DD2A7A /* CXXFormatterFunctions.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = CXXFormatterFunctions.h; path = include/lldb/Core/CXXFormatterFunctions.h; sourceTree = "<group>"; };
+		94CDEB9C15F0258400DD2A7A /* CXXFormatterFunctions.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CXXFormatterFunctions.cpp; path = source/Core/CXXFormatterFunctions.cpp; sourceTree = "<group>"; };
 		94E367CC140C4EC4001C7A5A /* modify-python-lldb.py */ = {isa = PBXFileReference; lastKnownFileType = text.script.python; path = "modify-python-lldb.py"; sourceTree = "<group>"; };
 		94E367CE140C4EEA001C7A5A /* python-typemaps.swig */ = {isa = PBXFileReference; lastKnownFileType = text; path = "python-typemaps.swig"; sourceTree = "<group>"; };
 		94EA1D5A15E6C99B00D4171A /* PythonDataObjects.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = PythonDataObjects.h; path = include/lldb/Interpreter/PythonDataObjects.h; sourceTree = "<group>"; };
@@ -2455,6 +2458,8 @@
 				266603C91345B5A8004DA8B6 /* ConnectionSharedMemory.cpp */,
 				26BC7D7C10F1B77400F91463 /* ConstString.h */,
 				26BC7E9410F1B85900F91463 /* ConstString.cpp */,
+				94CDEB9A15F0226900DD2A7A /* CXXFormatterFunctions.h */,
+				94CDEB9C15F0258400DD2A7A /* CXXFormatterFunctions.cpp */,
 				26BC7D5910F1B77400F91463 /* DataBuffer.h */,
 				26BC7D5B10F1B77400F91463 /* DataBufferHeap.h */,
 				26BC7E7210F1B85900F91463 /* DataBufferHeap.cpp */,
@@ -4111,6 +4116,7 @@
 				2697A39315E404B1003E682C /* OptionValueArch.cpp in Sources */,
 				94EA1D5C15E6C9B400D4171A /* PythonDataObjects.cpp in Sources */,
 				2698699B15E6CBD0002415FF /* OperatingSystemPython.cpp in Sources */,
+				94CDEB9D15F0258500DD2A7A /* CXXFormatterFunctions.cpp in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};

Modified: lldb/trunk/source/API/SBModule.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/API/SBModule.cpp?rev=163155&r1=163154&r2=163155&view=diff
==============================================================================
--- lldb/trunk/source/API/SBModule.cpp (original)
+++ lldb/trunk/source/API/SBModule.cpp Tue Sep  4 13:47:54 2012
@@ -542,17 +542,15 @@
 {
     ModuleSP module_sp (GetSP ());
     if (module_sp)
+        return module_sp->GetVersion(versions, num_versions);
+    else
     {
-        ObjectFile *obj_file = module_sp->GetObjectFile();
-        if (obj_file)
-            return obj_file->GetVersion (versions, num_versions);
+        if (versions && num_versions)
+        {
+            for (uint32_t i=0; i<num_versions; ++i)
+                versions[i] = UINT32_MAX;
+        }
+        return 0;
     }
-    
-    if (versions && num_versions)
-    {
-        for (uint32_t i=0; i<num_versions; ++i)
-            versions[i] = UINT32_MAX;
-    }
-    return 0;
 }
 

Modified: lldb/trunk/source/API/SBTypeSummary.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/API/SBTypeSummary.cpp?rev=163155&r1=163154&r2=163155&view=diff
==============================================================================
--- lldb/trunk/source/API/SBTypeSummary.cpp (original)
+++ lldb/trunk/source/API/SBTypeSummary.cpp Tue Sep  4 13:47:54 2012
@@ -99,6 +99,9 @@
     if (!IsValid())
         return false;
     
+    if (m_opaque_sp->GetType() == lldb_private::TypeSummaryImpl::eTypeCallback)
+        return false;
+    
     return !m_opaque_sp->IsScripted();
 }
 
@@ -107,6 +110,8 @@
 {
     if (!IsValid())
         return NULL;
+    if (m_opaque_sp->GetType() == lldb_private::TypeSummaryImpl::eTypeCallback)
+        return NULL;
     if (m_opaque_sp->IsScripted())
     {
         ScriptSummaryFormat* script_summary_ptr = (ScriptSummaryFormat*)m_opaque_sp.get();
@@ -144,7 +149,7 @@
 {
     if (!IsValid())
         return;
-    if (m_opaque_sp->IsScripted())
+    if (m_opaque_sp->IsScripted() || (m_opaque_sp->GetType() == lldb_private::TypeSummaryImpl::eTypeCallback))
         ChangeSummaryType(false);
     ((StringSummaryFormat*)m_opaque_sp.get())->SetSummaryString(data);
 }
@@ -205,6 +210,16 @@
 {
     if (IsValid() == false)
         return !rhs.IsValid();
+
+    if (m_opaque_sp->GetType() != rhs.m_opaque_sp->GetType())
+        return false;
+    
+    if (m_opaque_sp->GetType() == lldb_private::TypeSummaryImpl::eTypeCallback)
+    {
+        lldb_private::CXXFunctionSummaryFormat *self_cxx = (lldb_private::CXXFunctionSummaryFormat*)m_opaque_sp.get();
+        lldb_private::CXXFunctionSummaryFormat *other_cxx = (lldb_private::CXXFunctionSummaryFormat*)rhs.m_opaque_sp.get();
+        return (self_cxx->m_impl == other_cxx->m_impl);
+    }
     
     if (m_opaque_sp->IsScripted() != rhs.m_opaque_sp->IsScripted())
         return false;
@@ -255,12 +270,20 @@
 {
     if (!IsValid())
         return false;
+    
     if (m_opaque_sp.unique())
         return true;
     
     TypeSummaryImplSP new_sp;
     
-    if (m_opaque_sp->IsScripted())
+    if (m_opaque_sp->GetType() == lldb_private::TypeSummaryImpl::eTypeCallback)
+    {
+        CXXFunctionSummaryFormat* current_summary_ptr = (CXXFunctionSummaryFormat*)m_opaque_sp.get();
+        new_sp = TypeSummaryImplSP(new CXXFunctionSummaryFormat(GetOptions(),
+                                                                current_summary_ptr->m_impl,
+                                                                current_summary_ptr->m_description.c_str()));
+    }
+    else if (m_opaque_sp->IsScripted())
     {
         ScriptSummaryFormat* current_summary_ptr = (ScriptSummaryFormat*)m_opaque_sp.get();
         new_sp = TypeSummaryImplSP(new ScriptSummaryFormat(GetOptions(),
@@ -284,15 +307,23 @@
     if (!IsValid())
         return false;
     
-    if (want_script == m_opaque_sp->IsScripted())
-        return CopyOnWrite_Impl();
-    
     TypeSummaryImplSP new_sp;
     
-    if (want_script)
-        new_sp = TypeSummaryImplSP(new ScriptSummaryFormat(GetOptions(), "", ""));
-    else
-        new_sp = TypeSummaryImplSP(new StringSummaryFormat(GetOptions(), ""));
+    if (want_script == m_opaque_sp->IsScripted())
+    {
+        if (m_opaque_sp->GetType() == lldb_private::TypeSummaryImpl::eTypeCallback && !want_script)
+            new_sp = TypeSummaryImplSP(new StringSummaryFormat(GetOptions(), ""));
+        else
+            return CopyOnWrite_Impl();
+    }
+    
+    if (!new_sp)
+    {
+        if (want_script)
+            new_sp = TypeSummaryImplSP(new ScriptSummaryFormat(GetOptions(), "", ""));
+        else
+            new_sp = TypeSummaryImplSP(new StringSummaryFormat(GetOptions(), ""));
+    }
     
     SetSP(new_sp);
     

Modified: lldb/trunk/source/Core/FormatClasses.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/FormatClasses.cpp?rev=163155&r1=163154&r2=163155&view=diff
==============================================================================
--- lldb/trunk/source/Core/FormatClasses.cpp (original)
+++ lldb/trunk/source/Core/FormatClasses.cpp Tue Sep  4 13:47:54 2012
@@ -157,6 +157,42 @@
     return sstr.GetString();
 }
 
+CXXFunctionSummaryFormat::CXXFunctionSummaryFormat (const TypeSummaryImpl::Flags& flags,
+                                                    Callback impl,
+                                                    const char* description) :
+                                                    TypeSummaryImpl(flags),
+                                                    m_impl(impl),
+                                                    m_description(description ? description : "")
+{
+}
+    
+bool
+CXXFunctionSummaryFormat::FormatObject(ValueObject *valobj,
+                                       std::string& dest)
+{
+    dest.clear();
+    StreamString stream;
+    if (!m_impl || m_impl(*valobj,stream) == false)
+        return false;
+    dest.assign(stream.GetData());
+    return true;
+}
+
+std::string
+CXXFunctionSummaryFormat::GetDescription()
+{
+    StreamString sstr;
+    sstr.Printf ("`%s (%p) `%s%s%s%s%s%s%s",      m_description.c_str(),m_impl,
+                 Cascades() ? "" : " (not cascading)",
+                 !DoesPrintChildren() ? "" : " (show children)",
+                 !DoesPrintValue() ? " (hide value)" : "",
+                 IsOneliner() ? " (one-line printout)" : "",
+                 SkipsPointers() ? " (skip pointers)" : "",
+                 SkipsReferences() ? " (skip references)" : "",
+                 HideNames() ? " (hide member names)" : "");
+    return sstr.GetString();
+}
+
 #ifndef LLDB_DISABLE_PYTHON
 
 

Modified: lldb/trunk/source/Core/FormatManager.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/FormatManager.cpp?rev=163155&r1=163154&r2=163155&view=diff
==============================================================================
--- lldb/trunk/source/Core/FormatManager.cpp (original)
+++ lldb/trunk/source/Core/FormatManager.cpp Tue Sep  4 13:47:54 2012
@@ -14,6 +14,7 @@
 // Other libraries and framework includes
 // Project includes
 
+#include "lldb/Core/CXXFormatterFunctions.h"
 #include "lldb/Core/Debugger.h"
 
 using namespace lldb;
@@ -896,6 +897,18 @@
 }
 #endif
 
+static void
+AddCXXSummary (TypeCategoryImpl::SharedPointer category_sp,
+               CXXFunctionSummaryFormat::Callback funct,
+               const char* description,
+               ConstString type_name,
+               TypeSummaryImpl::Flags flags)
+{
+    lldb::TypeSummaryImplSP summary_sp(new CXXFunctionSummaryFormat(flags,funct,description));
+    category_sp->GetSummaryNavigator()->Add(type_name,
+                                            summary_sp);
+}
+
 #ifndef LLDB_DISABLE_PYTHON
 void
 FormatManager::LoadObjCFormatters()
@@ -1025,12 +1038,13 @@
     .SetShowMembersOneLiner(false)
     .SetHideItemNames(false);
 
-    AddScriptSummary(appkit_category_sp, "lldb.formatters.objc.CFArray.CFArray_SummaryProvider", ConstString("NSArray"), appkit_flags);
-    AddScriptSummary(appkit_category_sp, "lldb.formatters.objc.CFArray.CFArray_SummaryProvider", ConstString("__NSArrayI"), appkit_flags);
-    AddScriptSummary(appkit_category_sp, "lldb.formatters.objc.CFArray.CFArray_SummaryProvider", ConstString("__NSArrayM"), appkit_flags);
-    AddScriptSummary(appkit_category_sp, "lldb.formatters.objc.CFArray.CFArray_SummaryProvider", ConstString("__NSCFArray"), appkit_flags);
-    AddScriptSummary(appkit_category_sp, "lldb.formatters.objc.CFArray.CFArray_SummaryProvider", ConstString("CFArrayRef"), appkit_flags);
-    AddScriptSummary(appkit_category_sp, "lldb.formatters.objc.CFArray.CFArray_SummaryProvider", ConstString("CFMutableArrayRef"), appkit_flags);
+    AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSArray_SummaryProvider, "NSArray summary provider", ConstString("NSArray"), appkit_flags);
+    AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSArray_SummaryProvider, "NSArray summary provider", ConstString("NSMutableArray"), appkit_flags);
+    AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSArray_SummaryProvider, "NSArray summary provider", ConstString("__NSArrayI"), appkit_flags);
+    AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSArray_SummaryProvider, "NSArray summary provider", ConstString("__NSArrayM"), appkit_flags);
+    AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSArray_SummaryProvider, "NSArray summary provider", ConstString("__NSCFArray"), appkit_flags);
+    AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSArray_SummaryProvider, "NSArray summary provider", ConstString("CFArrayRef"), appkit_flags);
+    AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSArray_SummaryProvider, "NSArray summary provider", ConstString("CFMutableArrayRef"), appkit_flags);
 
     AddScriptSummary(appkit_category_sp, "lldb.formatters.objc.CFBag.CFBag_SummaryProvider", ConstString("CFBagRef"), appkit_flags);
     AddScriptSummary(appkit_category_sp, "lldb.formatters.objc.CFBag.CFBag_SummaryProvider", ConstString("__CFBag"), appkit_flags);
@@ -1040,31 +1054,32 @@
     AddScriptSummary(appkit_category_sp, "lldb.formatters.objc.CFBinaryHeap.CFBinaryHeap_SummaryProvider", ConstString("CFBinaryHeapRef"), appkit_flags);
     AddScriptSummary(appkit_category_sp, "lldb.formatters.objc.CFBinaryHeap.CFBinaryHeap_SummaryProvider", ConstString("__CFBinaryHeap"), appkit_flags);
 
-    AddScriptSummary(appkit_category_sp, "lldb.formatters.objc.CFDictionary.CFDictionary_SummaryProvider", ConstString("NSDictionary"), appkit_flags);
-    AddScriptSummary(appkit_category_sp, "lldb.formatters.objc.CFDictionary.CFDictionary_SummaryProvider2", ConstString("CFDictionaryRef"), appkit_flags);
-    AddScriptSummary(appkit_category_sp, "lldb.formatters.objc.CFDictionary.CFDictionary_SummaryProvider2", ConstString("CFMutableDictionaryRef"), appkit_flags);
-    AddScriptSummary(appkit_category_sp, "lldb.formatters.objc.CFDictionary.CFDictionary_SummaryProvider", ConstString("__NSCFDictionary"), appkit_flags);
-    AddScriptSummary(appkit_category_sp, "lldb.formatters.objc.CFDictionary.CFDictionary_SummaryProvider", ConstString("__NSDictionaryI"), appkit_flags);
-    AddScriptSummary(appkit_category_sp, "lldb.formatters.objc.CFDictionary.CFDictionary_SummaryProvider", ConstString("__NSDictionaryM"), appkit_flags);
-
-    AddScriptSummary(appkit_category_sp, "lldb.formatters.objc.CFString.CFString_SummaryProvider", ConstString("NSString"), appkit_flags);
-    AddScriptSummary(appkit_category_sp, "lldb.formatters.objc.CFString.CFString_SummaryProvider", ConstString("CFStringRef"), appkit_flags);
-    AddScriptSummary(appkit_category_sp, "lldb.formatters.objc.CFString.CFString_SummaryProvider", ConstString("CFMutableStringRef"), appkit_flags);
+    AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSDictionary_SummaryProvider<false>, "NSDictionary summary provider", ConstString("NSDictionary"), appkit_flags);
+    AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSDictionary_SummaryProvider<false>, "NSDictionary summary provider", ConstString("__NSCFDictionary"), appkit_flags);
+    AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSDictionary_SummaryProvider<false>, "NSDictionary summary provider", ConstString("__NSDictionaryI"), appkit_flags);
+    AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSDictionary_SummaryProvider<false>, "NSDictionary summary provider", ConstString("__NSDictionaryM"), appkit_flags);
+    AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSDictionary_SummaryProvider<true>, "NSDictionary summary provider", ConstString("CFDictionaryRef"), appkit_flags);
+    AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSDictionary_SummaryProvider<true>, "NSDictionary summary provider", ConstString("CFMutableDictionaryRef"), appkit_flags);
+
+    AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSString_SummaryProvider, "NSString summary provider", ConstString("NSString"), appkit_flags);
+    AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSString_SummaryProvider, "NSString summary provider", ConstString("CFStringRef"), appkit_flags);
+    AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSString_SummaryProvider, "NSString summary provider", ConstString("CFMutableStringRef"), appkit_flags);
+    AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSString_SummaryProvider, "NSString summary provider", ConstString("__NSCFConstantString"), appkit_flags);
+    AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSString_SummaryProvider, "NSString summary provider", ConstString("__NSCFString"), appkit_flags);
+    AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSString_SummaryProvider, "NSString summary provider", ConstString("NSCFConstantString"), appkit_flags);
+    AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSString_SummaryProvider, "NSString summary provider", ConstString("NSCFString"), appkit_flags);
+    AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSString_SummaryProvider, "NSString summary provider", ConstString("NSPathStore2"), appkit_flags);
+    
     AddScriptSummary(appkit_category_sp, "lldb.formatters.objc.CFString.CFAttributedString_SummaryProvider", ConstString("NSAttributedString"), appkit_flags);
-    AddScriptSummary(appkit_category_sp, "lldb.formatters.objc.CFString.CFString_SummaryProvider", ConstString("__NSCFConstantString"), appkit_flags);
-    AddScriptSummary(appkit_category_sp, "lldb.formatters.objc.CFString.CFString_SummaryProvider", ConstString("__NSCFString"), appkit_flags);
-    AddScriptSummary(appkit_category_sp, "lldb.formatters.objc.CFString.CFString_SummaryProvider", ConstString("NSCFConstantString"), appkit_flags);
-    AddScriptSummary(appkit_category_sp, "lldb.formatters.objc.CFString.CFString_SummaryProvider", ConstString("NSCFString"), appkit_flags);
-    AddScriptSummary(appkit_category_sp, "lldb.formatters.objc.CFString.CFString_SummaryProvider", ConstString("NSPathStore2"), appkit_flags);
     
     AddScriptSummary(appkit_category_sp, "lldb.formatters.objc.NSBundle.NSBundle_SummaryProvider", ConstString("NSBundle"), appkit_flags);
     
-    AddScriptSummary(appkit_category_sp, "lldb.formatters.objc.NSData.NSData_SummaryProvider", ConstString("NSData"), appkit_flags);
-    AddScriptSummary(appkit_category_sp, "lldb.formatters.objc.NSData.NSData_SummaryProvider2", ConstString("CFDataRef"), appkit_flags);
-    AddScriptSummary(appkit_category_sp, "lldb.formatters.objc.NSData.NSData_SummaryProvider2", ConstString("CFMutableDataRef"), appkit_flags);
-    AddScriptSummary(appkit_category_sp, "lldb.formatters.objc.NSData.NSData_SummaryProvider", ConstString("NSConcreteData"), appkit_flags);
-    AddScriptSummary(appkit_category_sp, "lldb.formatters.objc.NSData.NSData_SummaryProvider", ConstString("NSConcreteMutableData"), appkit_flags);
-    AddScriptSummary(appkit_category_sp, "lldb.formatters.objc.NSData.NSData_SummaryProvider", ConstString("__NSCFData"), appkit_flags);
+    AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSData_SummaryProvider<false>, "NSData summary provider", ConstString("NSData"), appkit_flags);
+    AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSData_SummaryProvider<false>, "NSData summary provider", ConstString("NSConcreteData"), appkit_flags);
+    AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSData_SummaryProvider<false>, "NSData summary provider", ConstString("NSConcreteMutableData"), appkit_flags);
+    AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSData_SummaryProvider<false>, "NSData summary provider", ConstString("__NSCFData"), appkit_flags);
+    AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSData_SummaryProvider<true>, "NSData summary provider", ConstString("CFDataRef"), appkit_flags);
+    AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSData_SummaryProvider<true>, "NSData summary provider", ConstString("CFMutableDataRef"), appkit_flags);
 
     AddScriptSummary(appkit_category_sp, "lldb.formatters.objc.NSException.NSException_SummaryProvider", ConstString("NSException"), appkit_flags);
 
@@ -1073,11 +1088,11 @@
     AddScriptSummary(appkit_category_sp, "lldb.formatters.objc.NSNotification.NSNotification_SummaryProvider", ConstString("NSNotification"), appkit_flags);
     AddScriptSummary(appkit_category_sp, "lldb.formatters.objc.NSNotification.NSNotification_SummaryProvider", ConstString("NSConcreteNotification"), appkit_flags);
 
-    AddScriptSummary(appkit_category_sp, "lldb.formatters.objc.NSNumber.NSNumber_SummaryProvider", ConstString("NSNumber"), appkit_flags);
-    AddScriptSummary(appkit_category_sp, "lldb.formatters.objc.NSNumber.NSNumber_SummaryProvider", ConstString("__NSCFBoolean"), appkit_flags);
-    AddScriptSummary(appkit_category_sp, "lldb.formatters.objc.NSNumber.NSNumber_SummaryProvider", ConstString("__NSCFNumber"), appkit_flags);
-    AddScriptSummary(appkit_category_sp, "lldb.formatters.objc.NSNumber.NSNumber_SummaryProvider", ConstString("NSCFBoolean"), appkit_flags);
-    AddScriptSummary(appkit_category_sp, "lldb.formatters.objc.NSNumber.NSNumber_SummaryProvider", ConstString("NSCFNumber"), appkit_flags);
+    AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSNumber_SummaryProvider, "NSNumber summary provider", ConstString("NSNumber"), appkit_flags);
+    AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSNumber_SummaryProvider, "NSNumber summary provider", ConstString("__NSCFBoolean"), appkit_flags);
+    AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSNumber_SummaryProvider, "NSNumber summary provider", ConstString("__NSCFNumber"), appkit_flags);
+    AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSNumber_SummaryProvider, "NSNumber summary provider", ConstString("NSCFBoolean"), appkit_flags);
+    AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSNumber_SummaryProvider, "NSNumber summary provider", ConstString("NSCFNumber"), appkit_flags);
 
     AddScriptSummary(appkit_category_sp, "lldb.formatters.objc.NSSet.NSSet_SummaryProvider", ConstString("NSSet"), appkit_flags);
     AddScriptSummary(appkit_category_sp, "lldb.formatters.objc.NSSet.NSSet_SummaryProvider2", ConstString("CFSetRef"), appkit_flags);

Modified: lldb/trunk/source/Core/Module.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/Module.cpp?rev=163155&r1=163154&r2=163155&view=diff
==============================================================================
--- lldb/trunk/source/Core/Module.cpp (original)
+++ lldb/trunk/source/Core/Module.cpp Tue Sep  4 13:47:54 2012
@@ -1205,3 +1205,17 @@
     return m_source_mappings.RemapPath(path, new_path);
 }
 
+uint32_t
+Module::GetVersion (uint32_t *versions, uint32_t num_versions)
+{
+    ObjectFile *obj_file = GetObjectFile();
+    if (obj_file)
+        return obj_file->GetVersion (versions, num_versions);
+        
+    if (versions && num_versions)
+    {
+        for (uint32_t i=0; i<num_versions; ++i)
+            versions[i] = UINT32_MAX;
+    }
+    return 0;
+}

Modified: lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.h?rev=163155&r1=163154&r2=163155&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.h (original)
+++ lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.h Tue Sep  4 13:47:54 2012
@@ -75,18 +75,6 @@
         return 0;
     }
     
-    virtual ConstString
-    GetActualTypeName(ObjCISA isa)
-    {
-        return ConstString(NULL);
-    }
-    
-    virtual ObjCISA
-    GetParentClass(ObjCISA isa)
-    {
-        return 0;
-    }
-    
     //------------------------------------------------------------------
     // Static Functions
     //------------------------------------------------------------------

Modified: lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.cpp?rev=163155&r1=163154&r2=163155&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.cpp (original)
+++ lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.cpp Tue Sep  4 13:47:54 2012
@@ -152,3 +152,169 @@
 
     return new ClangUtilityFunction(buf->contents, name);
 }
+
+// this code relies on the assumption that an Objective-C object always starts
+// with an ISA at offset 0.
+ObjCLanguageRuntime::ObjCISA
+AppleObjCRuntimeV1::GetISA(ValueObject& valobj)
+{
+    if (ClangASTType::GetMinimumLanguage(valobj.GetClangAST(),valobj.GetClangType()) != 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;
+    
+    addr_t isa_pointer = valobj.GetPointerValue();
+    
+    ExecutionContext exe_ctx (valobj.GetExecutionContextRef());
+    
+    Process *process = exe_ctx.GetProcessPtr();
+    if (process)
+    {
+        uint8_t pointer_size = process->GetAddressByteSize();
+        
+        Error error;
+        return process->ReadUnsignedIntegerFromMemory (isa_pointer,
+                                                       pointer_size,
+                                                       0,
+                                                       error);
+    }
+    return 0;
+}
+
+AppleObjCRuntimeV1::ClassDescriptorV1::ClassDescriptorV1 (ValueObject &isa_pointer)
+{
+    ObjCISA ptr_value = isa_pointer.GetValueAsUnsigned(0);
+
+    lldb::ProcessSP process_sp = isa_pointer.GetProcessSP();
+
+    Initialize (ptr_value,process_sp);
+}
+
+AppleObjCRuntimeV1::ClassDescriptorV1::ClassDescriptorV1 (ObjCISA isa, lldb::ProcessSP process_sp)
+{
+    Initialize (isa, process_sp);
+}
+
+void
+AppleObjCRuntimeV1::ClassDescriptorV1::Initialize (ObjCISA isa, lldb::ProcessSP process_sp)
+{
+    if (!isa || !process_sp)
+    {
+        m_valid = false;
+        return;
+    }
+    
+    m_valid = true;
+    
+    Error error;
+    
+    m_isa = process_sp->ReadPointerFromMemory(isa, error);
+    
+    if (error.Fail())
+    {
+        m_valid = false;
+        return;
+    }
+    
+    uint32_t ptr_size = process_sp->GetAddressByteSize();
+    
+    if (!IsPointerValid(m_isa,ptr_size))
+    {
+        m_valid = false;
+        return;
+    }
+
+    m_parent_isa = process_sp->ReadPointerFromMemory(m_isa + ptr_size,error);
+    
+    if (error.Fail())
+    {
+        m_valid = false;
+        return;
+    }
+    
+    if (!IsPointerValid(m_parent_isa,ptr_size,true))
+    {
+        m_valid = false;
+        return;
+    }
+    
+    lldb::addr_t name_ptr = process_sp->ReadPointerFromMemory(m_isa + 2 * ptr_size,error);
+    
+    if (error.Fail())
+    {
+        m_valid = false;
+        return;
+    }
+    
+    lldb::DataBufferSP buffer_sp(new DataBufferHeap(1024, 0));
+    
+    size_t count = process_sp->ReadCStringFromMemory(name_ptr, (char*)buffer_sp->GetBytes(), 1024, error);
+    
+    if (error.Fail())
+    {
+        m_valid = false;
+        return;
+    }
+    
+    if (count)
+        m_name = ConstString((char*)buffer_sp->GetBytes());
+    else
+        m_name = ConstString();
+    
+    m_instance_size = process_sp->ReadUnsignedIntegerFromMemory(m_isa + 5 * ptr_size, ptr_size, 0, error);
+    
+    if (error.Fail())
+    {
+        m_valid = false;
+        return;
+    }
+    
+    m_process_wp = lldb::ProcessWP(process_sp);
+}
+
+AppleObjCRuntime::ClassDescriptorSP
+AppleObjCRuntimeV1::ClassDescriptorV1::GetSuperclass ()
+{
+    if (!m_valid)
+        return NULL;
+    ProcessSP process_sp = m_process_wp.lock();
+    if (!process_sp)
+        return NULL;
+    return ObjCLanguageRuntime::ClassDescriptorSP(new AppleObjCRuntimeV1::ClassDescriptorV1(m_parent_isa,process_sp));
+}
+
+ObjCLanguageRuntime::ClassDescriptorSP
+AppleObjCRuntimeV1::GetClassDescriptor (ValueObject& in_value)
+{
+    ObjCISA isa = GetISA(in_value);
+    
+    ObjCLanguageRuntime::ISAToDescriptorIterator found = m_isa_to_descriptor_cache.find(isa);
+    ObjCLanguageRuntime::ISAToDescriptorIterator end = m_isa_to_descriptor_cache.end();
+    
+    if (found != end && found->second)
+        return found->second;
+    
+    ClassDescriptorSP descriptor = ClassDescriptorSP(new ClassDescriptorV1(in_value));
+    if (descriptor && descriptor->IsValid())
+        m_isa_to_descriptor_cache[descriptor->GetISA()] = descriptor;
+    return descriptor;
+}
+
+ObjCLanguageRuntime::ClassDescriptorSP
+AppleObjCRuntimeV1::GetClassDescriptor (ObjCISA isa)
+{
+    ObjCLanguageRuntime::ISAToDescriptorIterator found = m_isa_to_descriptor_cache.find(isa);
+    ObjCLanguageRuntime::ISAToDescriptorIterator end = m_isa_to_descriptor_cache.end();
+    
+    if (found != end && found->second)
+        return found->second;
+    
+    ClassDescriptorSP descriptor = ClassDescriptorSP(new ClassDescriptorV1(isa,m_process->CalculateProcess()));
+    if (descriptor && descriptor->IsValid())
+        m_isa_to_descriptor_cache[descriptor->GetISA()] = descriptor;
+    return descriptor;
+}

Modified: lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.h?rev=163155&r1=163154&r2=163155&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.h (original)
+++ lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.h Tue Sep  4 13:47:54 2012
@@ -24,6 +24,63 @@
         public AppleObjCRuntime
 {
 public:
+    
+    class ClassDescriptorV1 : public ObjCLanguageRuntime::ClassDescriptor
+    {
+    public:
+        ClassDescriptorV1 (ValueObject &isa_pointer);
+        ClassDescriptorV1 (ObjCISA isa, lldb::ProcessSP process_sp);
+        
+        virtual ConstString
+        GetClassName ()
+        {
+            return m_name;
+        }
+        
+        virtual ClassDescriptorSP
+        GetSuperclass ();
+        
+        virtual bool
+        IsValid ()
+        {
+            return m_valid;
+        }
+        
+        virtual bool
+        IsTagged ()
+        {
+            return false;   // v1 runtime does not support tagged pointers
+        }
+        
+        virtual uint64_t
+        GetInstanceSize ()
+        {
+            return m_instance_size;
+        }
+        
+        virtual ObjCISA
+        GetISA ()
+        {
+            return m_isa;
+        }
+        
+        virtual
+        ~ClassDescriptorV1 ()
+        {}
+        
+    protected:
+        void
+        Initialize (ObjCISA isa, lldb::ProcessSP process_sp);
+        
+    private:
+        ConstString m_name;
+        ObjCISA m_isa;
+        ObjCISA m_parent_isa;
+        bool m_valid;
+        lldb::ProcessWP m_process_wp;
+        uint64_t m_instance_size;
+    };
+    
     virtual ~AppleObjCRuntimeV1() { }
     
     // These are generic runtime functions:
@@ -69,26 +126,17 @@
     virtual bool
     IsValidISA(ObjCISA isa)
     {
-        return false;
+        return (isa != 0) && ( (isa % 2) == 0);
     }
     
     virtual ObjCISA
-    GetISA(ValueObject& valobj)
-    {
-        return 0;
-    }
+    GetISA(ValueObject& valobj);
     
-    virtual ConstString
-    GetActualTypeName(ObjCISA isa)
-    {
-        return ConstString(NULL);
-    }
+    virtual ClassDescriptorSP
+    GetClassDescriptor (ValueObject& in_value);
     
-    virtual ObjCISA
-    GetParentClass(ObjCISA isa)
-    {
-        return 0;
-    }
+    virtual ClassDescriptorSP
+    GetClassDescriptor (ObjCISA isa);
 
 protected:
     virtual lldb::BreakpointResolverSP

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=163155&r1=163154&r2=163155&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp (original)
+++ lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp Tue Sep  4 13:47:54 2012
@@ -104,9 +104,7 @@
                                         const ModuleSP &objc_module_sp) : 
     AppleObjCRuntime (process),
     m_get_class_name_args(LLDB_INVALID_ADDRESS),
-    m_get_class_name_args_mutex(Mutex::eMutexTypeNormal),
-    m_isa_to_name_cache(),
-    m_isa_to_parent_cache()
+    m_get_class_name_args_mutex(Mutex::eMutexTypeNormal)
 {
     static const ConstString g_gdb_object_getClass("gdb_object_getClass");
     m_has_object_getClass = (objc_module_sp->FindFirstSymbolWithNameAndType(g_gdb_object_getClass, eSymbolTypeCode) != NULL);
@@ -587,6 +585,46 @@
     return (ptr & 0x01);
 }
 
+ObjCLanguageRuntime::ClassDescriptorSP
+AppleObjCRuntimeV2::GetClassDescriptor (ObjCISA isa)
+{
+    ObjCLanguageRuntime::ISAToDescriptorIterator found = m_isa_to_descriptor_cache.find(isa);
+    ObjCLanguageRuntime::ISAToDescriptorIterator end = m_isa_to_descriptor_cache.end();
+    
+    if (found != end && found->second)
+        return found->second;
+    
+    ClassDescriptorSP descriptor = ClassDescriptorSP(new ClassDescriptorV2(isa,m_process->CalculateProcess()));
+    if (descriptor && descriptor->IsValid())
+        m_isa_to_descriptor_cache[descriptor->GetISA()] = descriptor;
+    return descriptor;
+}
+
+ObjCLanguageRuntime::ClassDescriptorSP
+AppleObjCRuntimeV2::GetClassDescriptor (ValueObject& in_value)
+{
+    uint64_t ptr_value = in_value.GetValueAsUnsigned(0);
+    if (ptr_value == 0)
+        return NULL;
+    
+    ObjCISA isa = GetISA(in_value);
+    
+    ObjCLanguageRuntime::ISAToDescriptorIterator found = m_isa_to_descriptor_cache.find(isa);
+    ObjCLanguageRuntime::ISAToDescriptorIterator end = m_isa_to_descriptor_cache.end();
+    
+    if (found != end && found->second)
+        return found->second;
+    
+    ClassDescriptorSP descriptor;
+    
+    if (ptr_value & 1)
+        return ClassDescriptorSP(new ClassDescriptorV2Tagged(in_value)); // do not save tagged pointers
+    descriptor = ClassDescriptorSP(new ClassDescriptorV2(in_value));
+    
+    if (descriptor && descriptor->IsValid())
+        m_isa_to_descriptor_cache[descriptor->GetISA()] = descriptor;
+    return descriptor;
+}
 
 // this code relies on the assumption that an Objective-C object always starts
 // with an ISA at offset 0. an ISA is effectively a pointer to an instance of
@@ -641,142 +679,283 @@
         return g_objc_tagged_isa_name;
     }
     
-    ISAToNameIterator found = m_isa_to_name_cache.find(isa);
-    ISAToNameIterator end = m_isa_to_name_cache.end();
+    ISAToDescriptorIterator found = m_isa_to_descriptor_cache.find(isa);
+    ISAToDescriptorIterator end = m_isa_to_descriptor_cache.end();
     
-    if (found != end)
-        return found->second;
+    if (found != end && found->second)
+        return found->second->GetClassName();
+    
+    ClassDescriptorSP descriptor(GetClassDescriptor(isa));
+    if (!descriptor.get() || !descriptor->IsValid())
+        return ConstString();
+    ConstString class_name = descriptor->GetClassName();
+    if (descriptor->IsKVO())
+    {
+        ClassDescriptorSP superclass(descriptor->GetSuperclass());
+        if (!superclass.get() || !superclass->IsValid())
+            return ConstString();
+        descriptor = superclass;
+    }
+    m_isa_to_descriptor_cache[isa] = descriptor;
+    return descriptor->GetClassName();
+}
+
+SymbolVendor *
+AppleObjCRuntimeV2::GetSymbolVendor()
+{
+    if (!m_symbol_vendor_ap.get())
+        m_symbol_vendor_ap.reset(new AppleObjCSymbolVendor(m_process));
+    
+    return m_symbol_vendor_ap.get();
+}
+
+AppleObjCRuntimeV2::ClassDescriptorV2::ClassDescriptorV2 (ValueObject &isa_pointer)
+{
+    ObjCISA ptr_value = isa_pointer.GetValueAsUnsigned(0);
+    
+    lldb::ProcessSP process_sp = isa_pointer.GetProcessSP();
+    
+    Initialize (ptr_value,process_sp);
+}
+
+AppleObjCRuntimeV2::ClassDescriptorV2::ClassDescriptorV2 (ObjCISA isa, lldb::ProcessSP process_sp)
+{
+    Initialize (isa, process_sp);
+}
+
+void
+AppleObjCRuntimeV2::ClassDescriptorV2::Initialize (ObjCISA isa, lldb::ProcessSP process_sp)
+{
+    if (!isa || !process_sp)
+    {
+        m_valid = false;
+        return;
+    }
+    
+    m_valid = true;
     
-    uint8_t pointer_size = m_process->GetAddressByteSize();
     Error error;
     
-    /*
-     struct class_t *isa;
-     struct class_t *superclass;
-     Cache cache;
-     IMP *vtable;
--->     class_rw_t data;
-     */
-    
-    addr_t rw_pointer = isa + (4 * pointer_size);
-    //printf("rw_pointer: %llx\n", rw_pointer);
-    uint64_t data_pointer =  m_process->ReadUnsignedIntegerFromMemory(rw_pointer,
-                                                                      pointer_size,
-                                                                      0,
-                                                                      error);
+    m_isa = process_sp->ReadPointerFromMemory(isa, error);
+    
     if (error.Fail())
     {
-        return g_unknown;
-
+        m_valid = false;
+        return;
     }
     
-    /*
-     uint32_t flags;
-     uint32_t version;
-     
--->     const class_ro_t *ro;
-     */
-    data_pointer += 8;
-    //printf("data_pointer: %llx\n", data_pointer);
-    uint64_t ro_pointer = m_process->ReadUnsignedIntegerFromMemory(data_pointer,
-                                                                   pointer_size,
-                                                                   0,
-                                                                   error);
+    uint32_t ptr_size = process_sp->GetAddressByteSize();
+    
+    if (!IsPointerValid(m_isa,ptr_size,false,false,true))
+    {
+        m_valid = false;
+        return;
+    }
+    
+    lldb::addr_t data_ptr = process_sp->ReadPointerFromMemory(m_isa + 4 * ptr_size, error);
+    
     if (error.Fail())
-        return g_unknown;
+    {
+        m_valid = false;
+        return;
+    }
+    
+    if (!IsPointerValid(data_ptr,ptr_size,false,false,true))
+    {
+        m_valid = false;
+        return;
+    }
+    
+    m_parent_isa = process_sp->ReadPointerFromMemory(isa + ptr_size,error);
     
-    /*
-     uint32_t flags;
-     uint32_t instanceStart;
-     uint32_t instanceSize;
-     #ifdef __LP64__
-     uint32_t reserved;
-     #endif
-     
-     const uint8_t * ivarLayout;
-     
--->     const char * name;
-     */
-    ro_pointer += 12;
-    if (pointer_size == 8)
-        ro_pointer += 4;
-    ro_pointer += pointer_size;
-    //printf("ro_pointer: %llx\n", ro_pointer);
-    uint64_t name_pointer = m_process->ReadUnsignedIntegerFromMemory(ro_pointer,
-                                                                     pointer_size,
-                                                                     0,
-                                                                     error);
     if (error.Fail())
-        return g_unknown;
+    {
+        m_valid = false;
+        return;
+    }
     
-    //printf("name_pointer: %llx\n", name_pointer);
-    char cstr[512];
-    if (m_process->ReadCStringFromMemory(name_pointer, cstr, sizeof(cstr), error) > 0)
+    // sanity checks
+    lldb::addr_t cache_ptr = process_sp->ReadPointerFromMemory(m_isa + 2*ptr_size, error);
+    if (error.Fail())
     {
-        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
-            ConstString class_name = GetActualTypeName(GetParentClass(isa));
-            m_isa_to_name_cache[isa] = class_name;
-            return class_name;
-        }
-        else
-        {
-            ConstString class_name = ConstString(cstr);
-            m_isa_to_name_cache[isa] = class_name;
-            return class_name;
-        }
+        m_valid = false;
+        return;
+    }
+    if (!IsPointerValid(cache_ptr,ptr_size,true,false,true))
+    {
+        m_valid = false;
+        return;
+    }
+    lldb::addr_t vtable_ptr = process_sp->ReadPointerFromMemory(m_isa + 3*ptr_size, error);
+    if (error.Fail())
+    {
+        m_valid = false;
+        return;
+    }
+    if (!IsPointerValid(vtable_ptr,ptr_size,true,false,true))
+    {
+        m_valid = false;
+        return;
     }
-    else
-        return g_unknown;
-}
 
-ObjCLanguageRuntime::ObjCISA
-AppleObjCRuntimeV2::GetParentClass(ObjCLanguageRuntime::ObjCISA isa)
-{
-    if (!IsValidISA(isa))
-        return 0;
+    // now construct the data object
     
-    if (isa == g_objc_Tagged_ISA)
-        return 0;
+    lldb::addr_t rot_pointer = process_sp->ReadPointerFromMemory(data_ptr + 8, error);
     
-    ISAToParentIterator found = m_isa_to_parent_cache.find(isa);
-    ISAToParentIterator end = m_isa_to_parent_cache.end();
+    if (error.Fail())
+    {
+        m_valid = false;
+        return;
+    }
     
-    if (found != end)
-        return found->second;
+    if (!IsPointerValid(rot_pointer,ptr_size))
+    {
+        m_valid = false;
+        return;
+    }
+    
+    // now read from the rot
+    
+    lldb::addr_t name_ptr = process_sp->ReadPointerFromMemory(rot_pointer + (ptr_size == 8 ? 24 : 16) ,error);
     
-    uint8_t pointer_size = m_process->GetAddressByteSize();
-    Error error;
-    /*
-     struct class_t *isa;
--->     struct class_t *superclass;
-     */
-    addr_t parent_pointer = isa + pointer_size;
-    //printf("rw_pointer: %llx\n", rw_pointer);
-    
-    uint64_t parent_isa =  m_process->ReadUnsignedIntegerFromMemory(parent_pointer,
-                                                                    pointer_size,
-                                                                    0,
-                                                                    error);
     if (error.Fail())
-        return 0;
+    {
+        m_valid = false;
+        return;
+    }
     
-    m_isa_to_parent_cache[isa] = parent_isa;
+    lldb::DataBufferSP buffer_sp(new DataBufferHeap(1024, 0));
     
-    return parent_isa;
+    size_t count = process_sp->ReadCStringFromMemory(name_ptr, (char*)buffer_sp->GetBytes(), 1024, error);
+    
+    if (error.Fail())
+    {
+        m_valid = false;
+        return;
+    }
+    
+    if (count)
+        m_name = ConstString((char*)buffer_sp->GetBytes());
+    else
+        m_name = ConstString();
+
+    m_instance_size = process_sp->ReadUnsignedIntegerFromMemory(rot_pointer + 8, ptr_size, 0, error);
+    
+    m_process_wp = lldb::ProcessWP(process_sp);
 }
 
-SymbolVendor *
-AppleObjCRuntimeV2::GetSymbolVendor()
+AppleObjCRuntime::ClassDescriptorSP
+AppleObjCRuntimeV2::ClassDescriptorV2::GetSuperclass ()
 {
-    if (!m_symbol_vendor_ap.get())
-        m_symbol_vendor_ap.reset(new AppleObjCSymbolVendor(m_process));
+    if (!m_valid)
+        return NULL;
+    ProcessSP process_sp = m_process_wp.lock();
+    if (!process_sp)
+        return NULL;
+    return AppleObjCRuntime::ClassDescriptorSP(new AppleObjCRuntimeV2::ClassDescriptorV2(m_parent_isa,process_sp));
+}
+
+AppleObjCRuntimeV2::ClassDescriptorV2Tagged::ClassDescriptorV2Tagged (ValueObject &isa_pointer)
+{
+    m_valid = false;
+    uint64_t value = isa_pointer.GetValueAsUnsigned(0);
+    lldb::ProcessSP process_sp = isa_pointer.GetProcessSP();
+    if (process_sp)
+        m_pointer_size = process_sp->GetAddressByteSize();
+    else
+    {
+        m_name = ConstString("");
+        m_pointer_size = 0;
+        return;
+    }
     
-    return m_symbol_vendor_ap.get();
+    m_valid = true;
+    m_class_bits = (value & 0xE) >> 1;
+    lldb::TargetSP target_sp = isa_pointer.GetTargetSP();
+    
+    LazyBool is_lion = IsLion(target_sp);
+    
+    // TODO: check for OSX version - for now assume Mtn Lion
+    if (is_lion == eLazyBoolCalculate)
+    {
+        // if we can't determine the matching table (e.g. we have no Foundation),
+        // assume this is not a valid tagged pointer
+        m_valid = false;
+    }
+    else if (is_lion == eLazyBoolNo)
+    {
+        switch (m_class_bits)
+        {
+            case 0:
+                m_name = ConstString("NSAtom");
+                break;
+            case 3:
+                m_name = ConstString("NSNumber");
+                break;
+            case 4:
+                m_name = ConstString("NSDateTS");
+                break;
+            case 5:
+                m_name = ConstString("NSManagedObject");
+                break;
+            case 6:
+                m_name = ConstString("NSDate");
+                break;
+            default:
+                m_valid = false;
+                break;
+        }
+    }
+    else
+    {
+        switch (m_class_bits)
+        {
+            case 1:
+                m_name = ConstString("NSNumber");
+                break;
+            case 5:
+                m_name = ConstString("NSManagedObject");
+                break;
+            case 6:
+                m_name = ConstString("NSDate");
+                break;
+            case 7:
+                m_name = ConstString("NSDateTS");
+                break;
+            default:
+                m_valid = false;
+                break;
+        }
+    }
+    if (!m_valid)
+        m_name = ConstString("");
+    else
+    {
+        m_info_bits = (value & 0xF0ULL) >> 4;
+        m_value_bits = (value & ~0x0000000000000000FFULL) >> 8;
+    }
+}
+
+LazyBool
+AppleObjCRuntimeV2::ClassDescriptorV2Tagged::IsLion (lldb::TargetSP &target_sp)
+{
+    if (!target_sp)
+        return eLazyBoolCalculate;
+    ModuleList& modules = target_sp->GetImages();
+    for (uint32_t idx = 0; idx < modules.GetSize(); idx++)
+    {
+        lldb::ModuleSP module_sp = modules.GetModuleAtIndex(idx);
+        if (!module_sp)
+            continue;
+        if (strcmp(module_sp->GetFileSpec().GetFilename().AsCString(""),"Foundation") == 0)
+        {
+            uint32_t major = UINT32_MAX;
+            module_sp->GetVersion(&major,1);
+            if (major == UINT32_MAX)
+                return eLazyBoolCalculate;
+            
+            return (major > 900 ? eLazyBoolNo : eLazyBoolYes);
+        }
+    }
+    return eLazyBoolCalculate;
 }

Modified: lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.h?rev=163155&r1=163154&r2=163155&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.h (original)
+++ lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.h Tue Sep  4 13:47:54 2012
@@ -27,6 +27,165 @@
         public AppleObjCRuntime
 {
 public:
+    
+    class ClassDescriptorV2 : public ObjCLanguageRuntime::ClassDescriptor
+    {
+    public:
+        ClassDescriptorV2 (ValueObject &isa_pointer);
+        ClassDescriptorV2 (ObjCISA isa, lldb::ProcessSP process);
+        
+        virtual ConstString
+        GetClassName ()
+        {
+            return m_name;
+        }
+        
+        virtual ClassDescriptorSP
+        GetSuperclass ();
+        
+        virtual bool
+        IsValid ()
+        {
+            return m_valid;
+        }
+        
+        virtual bool
+        IsTagged ()
+        {
+            return false;   // we use a special class for tagged descriptors
+        }
+        
+        virtual uint64_t
+        GetInstanceSize ()
+        {
+            return m_instance_size;
+        }
+        
+        virtual ObjCISA
+        GetISA ()
+        {
+            return m_isa;
+        }
+        
+        virtual
+        ~ClassDescriptorV2 ()
+        {}
+        
+    protected:
+        virtual bool
+        CheckPointer (lldb::addr_t value,
+                      uint32_t ptr_size)
+        {
+            if (ptr_size != 8)
+                return true;
+            return ((value & 0xFFFF800000000000) == 0);
+        }
+        
+        void
+        Initialize (ObjCISA isa, lldb::ProcessSP process_sp);
+        
+    private:
+        ConstString m_name;
+        ObjCISA m_isa;
+        ObjCISA m_parent_isa;
+        bool m_valid;
+        lldb::ProcessWP m_process_wp;
+        uint64_t m_instance_size;
+    };
+    
+    class ClassDescriptorV2Tagged : public ObjCLanguageRuntime::ClassDescriptor
+    {
+    public:
+        ClassDescriptorV2Tagged (ValueObject &isa_pointer);
+        
+        virtual ConstString
+        GetClassName ()
+        {
+            return m_name;
+        }
+        
+        virtual ClassDescriptorSP
+        GetSuperclass ()
+        {
+            // tagged pointers can represent a class that has a superclass, but since that information is not
+            // stored in the object itself, we would have to query the runtime to discover the hierarchy
+            // for the time being, we skip this step in the interest of static discovery
+            return ClassDescriptorSP(new ObjCLanguageRuntime::ClassDescriptor_Invalid());
+        }
+        
+        virtual bool
+        IsValid ()
+        {
+            return m_valid;
+        }
+        
+        virtual bool
+        IsKVO ()
+        {
+            return false; // tagged pointers are not KVO'ed
+        }
+        
+        virtual bool
+        IsCFType ()
+        {
+            return false; // tagged pointers are not CF objects
+        }
+        
+        virtual bool
+        IsTagged ()
+        {
+            return true;   // we use this class to describe tagged pointers
+        }
+        
+        virtual uint64_t
+        GetInstanceSize ()
+        {
+            return (IsValid() ? m_pointer_size : 0);
+        }
+        
+        virtual ObjCISA
+        GetISA ()
+        {
+            return 0; // tagged pointers have no ISA
+        }
+
+        virtual uint64_t
+        GetClassBits ()
+        {
+            return (IsValid() ? m_class_bits : 0);
+        }
+        
+        // these calls are not part of any formal tagged pointers specification
+        virtual uint64_t
+        GetValueBits ()
+        {
+            return (IsValid() ? m_value_bits : 0);
+        }
+        
+        virtual uint64_t
+        GetInfoBits ()
+        {
+            return (IsValid() ? m_info_bits : 0);
+        }
+        
+        virtual
+        ~ClassDescriptorV2Tagged ()
+        {}
+        
+    protected:
+        // TODO make this into a smarter OS version detector
+        LazyBool
+        IsLion (lldb::TargetSP &target_sp);
+        
+    private:
+        ConstString m_name;
+        uint8_t m_pointer_size;
+        bool m_valid;
+        uint64_t m_class_bits;
+        uint64_t m_info_bits;
+        uint64_t m_value_bits;
+    };
+    
     virtual ~AppleObjCRuntimeV2() { }
     
     // These are generic runtime functions:
@@ -90,8 +249,11 @@
     virtual ConstString
     GetActualTypeName(ObjCLanguageRuntime::ObjCISA isa);
     
-    virtual ObjCLanguageRuntime::ObjCISA
-    GetParentClass(ObjCLanguageRuntime::ObjCISA isa);
+    virtual ClassDescriptorSP
+    GetClassDescriptor (ValueObject& in_value);
+    
+    virtual ClassDescriptorSP
+    GetClassDescriptor (ObjCISA isa);
     
     virtual SymbolVendor *
     GetSymbolVendor();
@@ -102,13 +264,7 @@
 
 private:
     
-    typedef std::map<ObjCLanguageRuntime::ObjCISA, ConstString> ISAToNameCache;
-    typedef std::map<ObjCLanguageRuntime::ObjCISA, ObjCLanguageRuntime::ObjCISA> ISAToParentCache;
-    
-    typedef ISAToNameCache::iterator ISAToNameIterator;
-    typedef ISAToParentCache::iterator ISAToParentIterator;
-    
-    AppleObjCRuntimeV2 (Process *process, 
+    AppleObjCRuntimeV2 (Process *process,
                         const lldb::ModuleSP &objc_module_sp);
     
     bool
@@ -122,9 +278,6 @@
     lldb::addr_t                        m_get_class_name_args;
     Mutex                               m_get_class_name_args_mutex;
     
-    ISAToNameCache                      m_isa_to_name_cache;
-    ISAToParentCache                    m_isa_to_parent_cache;
-    
     std::auto_ptr<SymbolVendor>         m_symbol_vendor_ap;
     
     static const char *g_find_class_name_function_name;

Modified: lldb/trunk/source/Target/ObjCLanguageRuntime.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/ObjCLanguageRuntime.cpp?rev=163155&r1=163154&r2=163155&view=diff
==============================================================================
--- lldb/trunk/source/Target/ObjCLanguageRuntime.cpp (original)
+++ lldb/trunk/source/Target/ObjCLanguageRuntime.cpp Tue Sep  4 13:47:54 2012
@@ -262,3 +262,85 @@
     }
     return result;
 }
+
+bool
+ObjCLanguageRuntime::ClassDescriptor::IsPointerValid (lldb::addr_t value,
+                                                      uint32_t ptr_size,
+                                                      bool allow_NULLs,
+                                                      bool allow_tagged,
+                                                      bool check_version_specific)
+{
+    if (!value)
+        return allow_NULLs;
+    if ( (value % 2) == 1  && allow_tagged)
+        return true;
+    if ((value % ptr_size) == 0)
+        return (check_version_specific ? CheckPointer(value,ptr_size) : true);
+    else
+        return false;
+}
+
+ObjCLanguageRuntime::ObjCISA
+ObjCLanguageRuntime::GetParentClass(ObjCLanguageRuntime::ObjCISA isa)
+{
+    if (!IsValidISA(isa))
+        return 0;
+    
+    ISAToDescriptorIterator found = m_isa_to_descriptor_cache.find(isa);
+    ISAToDescriptorIterator end = m_isa_to_descriptor_cache.end();
+    
+    if (found != end && found->second)
+    {
+        ClassDescriptorSP superclass = found->second->GetSuperclass();
+        if (!superclass || !superclass->IsValid())
+            return 0;
+        else
+        {
+            ObjCISA parent_isa = superclass->GetISA();
+            m_isa_to_descriptor_cache[parent_isa] = superclass;
+            return parent_isa;
+        }
+    }
+    
+    ClassDescriptorSP descriptor(GetClassDescriptor(isa));
+    if (!descriptor.get() || !descriptor->IsValid())
+        return 0;
+    m_isa_to_descriptor_cache[isa] = descriptor;
+    ClassDescriptorSP superclass(descriptor->GetSuperclass());
+    if (!superclass.get() || !superclass->IsValid())
+        return 0;
+    ObjCISA parent_isa = superclass->GetISA();
+    m_isa_to_descriptor_cache[parent_isa] = superclass;
+    return parent_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
+ObjCLanguageRuntime::GetActualTypeName(ObjCLanguageRuntime::ObjCISA isa)
+{
+    static const ConstString g_unknown ("unknown");
+    
+    if (!IsValidISA(isa))
+        return ConstString();
+    
+    ISAToDescriptorIterator found = m_isa_to_descriptor_cache.find(isa);
+    ISAToDescriptorIterator end = m_isa_to_descriptor_cache.end();
+    
+    if (found != end && found->second)
+        return found->second->GetClassName();
+    
+    ClassDescriptorSP descriptor(GetClassDescriptor(isa));
+    if (!descriptor.get() || !descriptor->IsValid())
+        return ConstString();
+    ConstString class_name = descriptor->GetClassName();
+    if (descriptor->IsKVO())
+    {
+        ClassDescriptorSP superclass(descriptor->GetSuperclass());
+        if (!superclass.get() || !superclass->IsValid())
+            return ConstString();
+        descriptor = superclass;
+    }
+    m_isa_to_descriptor_cache[isa] = descriptor;
+    return descriptor->GetClassName();
+}

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=163155&r1=163154&r2=163155&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 Sep  4 13:47:54 2012
@@ -84,7 +84,6 @@
         self.rdar11106605_commands()
 
     @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin")
-    @expectedFailurei386
     @dsym_test
     def test_expr_with_dsym_and_run_command(self):
         """Test common cases of expression parser <--> formatters interaction."""
@@ -92,7 +91,6 @@
         self.expr_objc_data_formatter_commands()
 
     @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin")
-    @expectedFailurei386
     @dwarf_test
     def test_expr_with_dwarf_and_run_command(self):
         """Test common cases of expression parser <--> formatters interaction."""





More information about the lldb-commits mailing list