[Lldb-commits] [lldb] r180199 - Changes to the ObjC runtime

Enrico Granata egranata at apple.com
Wed Apr 24 10:49:09 PDT 2013


Author: enrico
Date: Wed Apr 24 12:49:08 2013
New Revision: 180199

URL: http://llvm.org/viewvc/llvm-project?rev=180199&view=rev
Log:
Changes to the ObjC runtime


Modified:
    lldb/trunk/include/lldb/Target/ObjCLanguageRuntime.h
    lldb/trunk/source/DataFormatters/Cocoa.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

Modified: lldb/trunk/include/lldb/Target/ObjCLanguageRuntime.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Target/ObjCLanguageRuntime.h?rev=180199&r1=180198&r2=180199&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Target/ObjCLanguageRuntime.h (original)
+++ lldb/trunk/include/lldb/Target/ObjCLanguageRuntime.h Wed Apr 24 12:49:08 2013
@@ -199,7 +199,8 @@ public:
         
         virtual bool
         GetTaggedPointerInfo (uint64_t* info_bits = NULL,
-                              uint64_t* value_bits = NULL) = 0;
+                              uint64_t* value_bits = NULL,
+                              uint64_t* payload = NULL) = 0;
         
         virtual uint64_t
         GetInstanceSize () = 0;

Modified: lldb/trunk/source/DataFormatters/Cocoa.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/DataFormatters/Cocoa.cpp?rev=180199&r1=180198&r2=180199&view=diff
==============================================================================
--- lldb/trunk/source/DataFormatters/Cocoa.cpp (original)
+++ lldb/trunk/source/DataFormatters/Cocoa.cpp Wed Apr 24 12:49:08 2013
@@ -330,17 +330,20 @@ lldb_private::formatters::NSNumberSummar
                 case 0:
                     stream.Printf("(char)%hhd",(char)value);
                     break;
+                case 1:
                 case 4:
                     stream.Printf("(short)%hd",(short)value);
                     break;
+                case 2:
                 case 8:
                     stream.Printf("(int)%d",(int)value);
                     break;
+                case 3:
                 case 12:
                     stream.Printf("(long)%" PRId64,value);
                     break;
                 default:
-                    stream.Printf("unexpected value:(info=%" PRIu64 ", value=%" PRIu64 ")",i_bits,value);
+                    stream.Printf("unexpected value:(info=%" PRIu64 ", value=%" PRIu64,i_bits,value);
                     break;
             }
             return true;

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=180199&r1=180198&r2=180199&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.h (original)
+++ lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.h Wed Apr 24 12:49:08 2013
@@ -49,7 +49,8 @@ public:
         // v1 does not support tagged pointers
         virtual bool
         GetTaggedPointerInfo (uint64_t* info_bits = NULL,
-                              uint64_t* value_bits = NULL)
+                              uint64_t* value_bits = NULL,
+                              uint64_t* payload = NULL)
         {
             return false;
         }

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=180199&r1=180198&r2=180199&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp (original)
+++ lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp Wed Apr 24 12:49:08 2013
@@ -27,12 +27,14 @@
 #include "lldb/Core/Section.h"
 #include "lldb/Core/StreamString.h"
 #include "lldb/Core/Timer.h"
+#include "lldb/Core/ValueObjectVariable.h"
 #include "lldb/Expression/ClangFunction.h"
 #include "lldb/Expression/ClangUtilityFunction.h"
 #include "lldb/Symbol/ClangASTContext.h"
 #include "lldb/Symbol/ObjectFile.h"
 #include "lldb/Symbol/Symbol.h"
 #include "lldb/Symbol/TypeList.h"
+#include "lldb/Symbol/VariableList.h"
 #include "lldb/Target/ExecutionContext.h"
 #include "lldb/Target/Process.h"
 #include "lldb/Target/RegisterContext.h"
@@ -286,6 +288,52 @@ __lldb_apple_objc_v2_get_shared_cache_cl
 
 )";
 
+static uint64_t
+ExtractRuntimeGlobalSymbol (Process* process,
+                            ConstString name,
+                            const ModuleSP &module_sp,
+                            Error& error,
+                            bool read_value = true,
+                            uint8_t byte_size = 0,
+                            uint64_t default_value = LLDB_INVALID_ADDRESS,
+                            SymbolType sym_type = lldb::eSymbolTypeData)
+{
+    if (!process)
+    {
+        error.SetErrorString("no process");
+        return default_value;
+    }
+    if (!module_sp)
+    {
+        error.SetErrorString("no module");
+        return default_value;
+    }
+    if (!byte_size)
+        byte_size = process->GetAddressByteSize();
+    const Symbol *symbol = module_sp->FindFirstSymbolWithNameAndType(name, lldb::eSymbolTypeData);
+    if (symbol)
+    {
+        lldb::addr_t symbol_load_addr = symbol->GetAddress().GetLoadAddress(&process->GetTarget());
+        if (symbol_load_addr != LLDB_INVALID_ADDRESS)
+        {
+            if (read_value)
+                return process->ReadUnsignedIntegerFromMemory(symbol_load_addr, byte_size, default_value, error);
+            else
+                return symbol_load_addr;
+        }
+        else
+        {
+            error.SetErrorString("symbol address invalid");
+            return default_value;
+        }
+    }
+    else
+    {
+        error.SetErrorString("no symbol");
+        return default_value;
+    }
+
+}
 
 AppleObjCRuntimeV2::AppleObjCRuntimeV2 (Process *process,
                                         const ModuleSP &objc_module_sp) :
@@ -302,7 +350,9 @@ AppleObjCRuntimeV2::AppleObjCRuntimeV2 (
     m_isa_hash_table_ptr (LLDB_INVALID_ADDRESS),
     m_hash_signature (),
     m_has_object_getClass (false),
-    m_loaded_objc_opt (false)
+    m_loaded_objc_opt (false),
+    m_non_pointer_isa_cache_ap(NonPointerISACache::CreateInstance(*this,objc_module_sp)),
+    m_tagged_pointer_vendor_ap(TaggedPointerVendor::CreateInstance(*this,objc_module_sp))
 {
     static const ConstString g_gdb_object_getClass("gdb_object_getClass");
     m_has_object_getClass = (objc_module_sp->FindFirstSymbolWithNameAndType(g_gdb_object_getClass, eSymbolTypeCode) != NULL);
@@ -313,7 +363,7 @@ AppleObjCRuntimeV2::~AppleObjCRuntimeV2(
 }
 
 bool
-AppleObjCRuntimeV2::GetDynamicTypeAndAddress (ValueObject &in_value, 
+AppleObjCRuntimeV2::GetDynamicTypeAndAddress (ValueObject &in_value,
                                               DynamicValueType use_dynamic, 
                                               TypeAndOrName &class_type_or_name, 
                                               Address &address)
@@ -522,15 +572,16 @@ AppleObjCRuntimeV2::GetByteOffsetForIvar
     return ivar_offset;
 }
 
-// tagged pointers are marked by having their least-significant bit
-// set. this makes them "invalid" as pointers because they violate
-// the alignment requirements. of course, this detection algorithm
-// is not accurate (it might become better by incorporating further
-// knowledge about the internals of tagged pointers)
+
+// tagged pointers are special not-a-real-pointer values that contain both type and value information
+// this routine attempts to check with as little computational effort as possible whether something
+// could possibly be a tagged pointer - false positives are possible but false negatives shouldn't
 bool
 AppleObjCRuntimeV2::IsTaggedPointer(addr_t ptr)
 {
-    return (ptr & 1);
+    if (!m_tagged_pointer_vendor_ap)
+        return false;
+    return m_tagged_pointer_vendor_ap->IsPossibleTaggedPointer(ptr);
 }
 
 class RemoteNXMapTable
@@ -860,7 +911,8 @@ public:
     // a custom descriptor is used for tagged pointers
     virtual bool
     GetTaggedPointerInfo (uint64_t* info_bits = NULL,
-                          uint64_t* value_bits = NULL)
+                          uint64_t* value_bits = NULL,
+                          uint64_t* payload = NULL)
     {
         return false;
     }
@@ -1414,88 +1466,43 @@ private:
     ConstString         m_name;             // May be NULL
 };
 
+// tagged pointer descriptor
 class ClassDescriptorV2Tagged : public ObjCLanguageRuntime::ClassDescriptor
 {
 public:
-    ClassDescriptorV2Tagged (ValueObject &isa_pointer)
+    ClassDescriptorV2Tagged (ConstString class_name,
+                             uint64_t payload)
     {
-        m_valid = false;
-        uint64_t value = isa_pointer.GetValueAsUnsigned(0);
-        ProcessSP process_sp = isa_pointer.GetProcessSP();
-        if (process_sp)
-            m_pointer_size = process_sp->GetAddressByteSize();
-        else
+        m_name = class_name;
+        if (!m_name)
         {
-            m_name = ConstString("");
-            m_pointer_size = 0;
+            m_valid = false;
             return;
         }
-        
         m_valid = true;
-        m_class_bits = (value & 0xE) >> 1;
-        lldb::TargetSP target_sp = isa_pointer.GetTargetSP();
-        
-        uint32_t foundation_version = GetFoundationVersion(target_sp);
-        
-        // TODO: check for OSX version - for now assume Mtn Lion
-        if (foundation_version == UINT32_MAX)
+        m_payload = payload;
+        m_info_bits = (m_payload & 0xF0ULL) >> 4;
+        m_value_bits = (m_payload & ~0x0000000000000000FFULL) >> 8;
+    }
+    
+    ClassDescriptorV2Tagged (ObjCLanguageRuntime::ClassDescriptorSP actual_class_sp,
+                             uint64_t payload)
+    {
+        if (!actual_class_sp)
         {
-            // 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;
+            return;
         }
-        else if (foundation_version >= 900)
-        {
-            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_name = actual_class_sp->GetClassName();
+        if (!m_name)
         {
-            m_info_bits = (value & 0xF0ULL) >> 4;
-            m_value_bits = (value & ~0x0000000000000000FFULL) >> 8;
+            m_valid = false;
+            return;
         }
+        m_valid = true;
+        m_payload = payload;
+        m_info_bits = (m_payload & 0x0FULL);
+        m_value_bits = (m_payload & ~0x0FULL) >> 4;
     }
     
     virtual ConstString
@@ -1533,12 +1540,15 @@ public:
     
     virtual bool
     GetTaggedPointerInfo (uint64_t* info_bits = NULL,
-                          uint64_t* value_bits = NULL)
+                          uint64_t* value_bits = NULL,
+                          uint64_t* payload = NULL)
     {
         if (info_bits)
             *info_bits = GetInfoBits();
         if (value_bits)
             *value_bits = GetValueBits();
+        if (payload)
+            *payload = GetPayload();
         return true;
     }
     
@@ -1554,12 +1564,6 @@ public:
         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 ()
@@ -1573,43 +1577,38 @@ public:
         return (IsValid() ? m_info_bits : 0);
     }
     
-    virtual
-    ~ClassDescriptorV2Tagged ()
-    {}
-    
-protected:
-    // we use the version of Foundation to make assumptions about the ObjC runtime on a target
-    uint32_t
-    GetFoundationVersion (lldb::TargetSP &target_sp)
+    virtual uint64_t
+    GetPayload ()
     {
-        if (!target_sp)
-            return eLazyBoolCalculate;
-        const ModuleList& modules = target_sp->GetImages();
-        uint32_t major = UINT32_MAX;
-        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)
-            {
-                module_sp->GetVersion(&major,1);
-                break;
-            }
-        }
-        return major;
+        return (IsValid() ? m_payload : 0);
     }
     
+    virtual
+    ~ClassDescriptorV2Tagged ()
+    {}
+
 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;
+    uint64_t m_payload;
+
 };
 
 ObjCLanguageRuntime::ClassDescriptorSP
+AppleObjCRuntimeV2::GetClassDescriptor (ObjCISA isa)
+{
+    ObjCLanguageRuntime::ClassDescriptorSP class_descriptor_sp;
+    if (m_non_pointer_isa_cache_ap.get())
+        class_descriptor_sp = m_non_pointer_isa_cache_ap->GetClassDescriptor(isa);
+    if (!class_descriptor_sp)
+        class_descriptor_sp = ObjCLanguageRuntime::GetClassDescriptorFromISA(isa);
+    return class_descriptor_sp;
+}
+
+ObjCLanguageRuntime::ClassDescriptorSP
 AppleObjCRuntimeV2::GetClassDescriptor (ValueObject& valobj)
 {
     ClassDescriptorSP objc_class_sp;
@@ -1623,13 +1622,7 @@ AppleObjCRuntimeV2::GetClassDescriptor (
         // tagged pointer
         if (IsTaggedPointer(isa_pointer))
         {
-            objc_class_sp.reset (new ClassDescriptorV2Tagged(valobj));
-            
-            // probably an invalid tagged pointer - say it's wrong
-            if (objc_class_sp->IsValid())
-                return objc_class_sp;
-            else
-                objc_class_sp.reset();
+            return m_tagged_pointer_vendor_ap->GetClassDescriptor(isa_pointer);
         }
         else
         {
@@ -2353,3 +2346,299 @@ AppleObjCRuntimeV2::LookupRuntimeSymbol
     
     return ret;
 }
+
+AppleObjCRuntimeV2::NonPointerISACache*
+AppleObjCRuntimeV2::NonPointerISACache::CreateInstance (AppleObjCRuntimeV2& runtime, const lldb::ModuleSP& objc_module_sp)
+{
+    Process* process(runtime.GetProcess());
+    
+    Error error;
+    
+    auto objc_debug_isa_magic_mask = ExtractRuntimeGlobalSymbol(process,
+                                                                ConstString("objc_debug_isa_magic_mask"),
+                                                                objc_module_sp,
+                                                                error);
+    if (error.Fail())
+        return NULL;
+
+    auto objc_debug_isa_magic_value = ExtractRuntimeGlobalSymbol(process,
+                                                                 ConstString("objc_debug_isa_magic_value"),
+                                                                 objc_module_sp,
+                                                                 error);
+    if (error.Fail())
+        return NULL;
+
+    auto objc_debug_isa_class_mask = ExtractRuntimeGlobalSymbol(process,
+                                                                ConstString("objc_debug_isa_class_mask"),
+                                                                objc_module_sp,
+                                                                error);
+    if (error.Fail())
+        return NULL;
+
+    // we might want to have some rules to outlaw these other values (e.g if the mask is zero but the value is non-zero, ...)
+    
+    return new NonPointerISACache(runtime,
+                                  objc_debug_isa_class_mask,
+                                  objc_debug_isa_magic_mask,
+                                  objc_debug_isa_magic_value);
+}
+
+AppleObjCRuntimeV2::TaggedPointerVendor*
+AppleObjCRuntimeV2::TaggedPointerVendor::CreateInstance (AppleObjCRuntimeV2& runtime, const lldb::ModuleSP& objc_module_sp)
+{
+    Process* process(runtime.GetProcess());
+    
+    Error error;
+    
+    auto objc_debug_taggedpointer_mask = ExtractRuntimeGlobalSymbol(process,
+                                                                    ConstString("objc_debug_taggedpointer_mask"),
+                                                                    objc_module_sp,
+                                                                    error);
+    if (error.Fail())
+        return new TaggedPointerVendorLegacy(runtime);
+    
+    auto objc_debug_taggedpointer_slot_shift = ExtractRuntimeGlobalSymbol(process,
+                                                                          ConstString("objc_debug_taggedpointer_slot_shift"),
+                                                                          objc_module_sp,
+                                                                          error,
+                                                                          true,
+                                                                          4);
+    if (error.Fail())
+        return new TaggedPointerVendorLegacy(runtime);
+    
+    auto objc_debug_taggedpointer_slot_mask = ExtractRuntimeGlobalSymbol(process,
+                                                                          ConstString("objc_debug_taggedpointer_slot_mask"),
+                                                                          objc_module_sp,
+                                                                          error,
+                                                                          true,
+                                                                          4);
+    if (error.Fail())
+        return new TaggedPointerVendorLegacy(runtime);
+
+    auto objc_debug_taggedpointer_payload_lshift = ExtractRuntimeGlobalSymbol(process,
+                                                                              ConstString("objc_debug_taggedpointer_payload_lshift"),
+                                                                              objc_module_sp,
+                                                                              error,
+                                                                              true,
+                                                                              4);
+    if (error.Fail())
+        return new TaggedPointerVendorLegacy(runtime);
+    
+    auto objc_debug_taggedpointer_payload_rshift = ExtractRuntimeGlobalSymbol(process,
+                                                                              ConstString("objc_debug_taggedpointer_payload_rshift"),
+                                                                              objc_module_sp,
+                                                                              error,
+                                                                              true,
+                                                                              4);
+    if (error.Fail())
+        return new TaggedPointerVendorLegacy(runtime);
+    
+    auto objc_debug_taggedpointer_classes = ExtractRuntimeGlobalSymbol(process,
+                                                                       ConstString("objc_debug_taggedpointer_classes"),
+                                                                       objc_module_sp,
+                                                                       error,
+                                                                       false);
+    if (error.Fail())
+        return new TaggedPointerVendorLegacy(runtime);
+
+    
+    // we might want to have some rules to outlaw these values (e.g if the table's address is zero)
+    
+    return new TaggedPointerVendorRuntimeAssisted(runtime,
+                                                  objc_debug_taggedpointer_mask,
+                                                  objc_debug_taggedpointer_slot_shift,
+                                                  objc_debug_taggedpointer_slot_mask,
+                                                  objc_debug_taggedpointer_payload_lshift,
+                                                  objc_debug_taggedpointer_payload_rshift,
+                                                  objc_debug_taggedpointer_classes);
+}
+
+bool
+AppleObjCRuntimeV2::TaggedPointerVendorLegacy::IsPossibleTaggedPointer (lldb::addr_t ptr)
+{
+    return (ptr & 1);
+}
+
+// we use the version of Foundation to make assumptions about the ObjC runtime on a target
+uint32_t
+AppleObjCRuntimeV2::TaggedPointerVendorLegacy::GetFoundationVersion (Target &target)
+{
+    const ModuleList& modules = target.GetImages();
+    uint32_t major = UINT32_MAX;
+    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)
+        {
+            module_sp->GetVersion(&major,1);
+            break;
+        }
+    }
+    return major;
+}
+
+ObjCLanguageRuntime::ClassDescriptorSP
+AppleObjCRuntimeV2::TaggedPointerVendorLegacy::GetClassDescriptor (lldb::addr_t ptr)
+{
+    if (!IsPossibleTaggedPointer(ptr))
+        return ObjCLanguageRuntime::ClassDescriptorSP();
+
+    Process* process(m_runtime.GetProcess());
+    
+    if (m_Foundation_version == 0)
+        m_Foundation_version = GetFoundationVersion(process->GetTarget());
+    
+    if (m_Foundation_version == UINT32_MAX)
+        return ObjCLanguageRuntime::ClassDescriptorSP();
+    
+    uint64_t class_bits = (ptr & 0xE) >> 1;
+    ConstString name;
+    
+    // TODO: make a table
+    if (m_Foundation_version >= 900)
+    {
+        switch (class_bits)
+        {
+            case 0:
+                name = ConstString("NSAtom");
+                break;
+            case 3:
+                name = ConstString("NSNumber");
+                break;
+            case 4:
+                name = ConstString("NSDateTS");
+                break;
+            case 5:
+                name = ConstString("NSManagedObject");
+                break;
+            case 6:
+                name = ConstString("NSDate");
+                break;
+            default:
+                return ObjCLanguageRuntime::ClassDescriptorSP();
+        }
+    }
+    else
+    {
+        switch (class_bits)
+        {
+            case 1:
+                name = ConstString("NSNumber");
+                break;
+            case 5:
+                name = ConstString("NSManagedObject");
+                break;
+            case 6:
+                name = ConstString("NSDate");
+                break;
+            case 7:
+                name = ConstString("NSDateTS");
+                break;
+            default:
+                return ObjCLanguageRuntime::ClassDescriptorSP();
+        }
+    }
+    return ClassDescriptorSP(new ClassDescriptorV2Tagged(name,ptr));
+}
+
+AppleObjCRuntimeV2::TaggedPointerVendorRuntimeAssisted::TaggedPointerVendorRuntimeAssisted (AppleObjCRuntimeV2& runtime,
+                                                                                            uint64_t objc_debug_taggedpointer_mask,
+                                                                                            uint32_t objc_debug_taggedpointer_slot_shift,
+                                                                                            uint32_t objc_debug_taggedpointer_slot_mask,
+                                                                                            uint32_t objc_debug_taggedpointer_payload_lshift,
+                                                                                            uint32_t objc_debug_taggedpointer_payload_rshift,
+                                                                                            lldb::addr_t objc_debug_taggedpointer_classes) :
+TaggedPointerVendor(runtime),
+m_cache(),
+m_objc_debug_taggedpointer_mask(objc_debug_taggedpointer_mask),
+m_objc_debug_taggedpointer_slot_shift(objc_debug_taggedpointer_slot_shift),
+m_objc_debug_taggedpointer_slot_mask(objc_debug_taggedpointer_slot_mask),
+m_objc_debug_taggedpointer_payload_lshift(objc_debug_taggedpointer_payload_lshift),
+m_objc_debug_taggedpointer_payload_rshift(objc_debug_taggedpointer_payload_rshift),
+m_objc_debug_taggedpointer_classes(objc_debug_taggedpointer_classes)
+{
+}
+
+bool
+AppleObjCRuntimeV2::TaggedPointerVendorRuntimeAssisted::IsPossibleTaggedPointer (lldb::addr_t ptr)
+{
+    return (ptr & m_objc_debug_taggedpointer_mask) != 0;
+}
+
+ObjCLanguageRuntime::ClassDescriptorSP
+AppleObjCRuntimeV2::TaggedPointerVendorRuntimeAssisted::GetClassDescriptor (lldb::addr_t ptr)
+{
+    ClassDescriptorSP actual_class_descriptor_sp;
+    uint64_t data_payload;
+
+    if (!IsPossibleTaggedPointer(ptr))
+        return ObjCLanguageRuntime::ClassDescriptorSP();
+    
+    uintptr_t slot = (ptr >> m_objc_debug_taggedpointer_slot_shift) & m_objc_debug_taggedpointer_slot_mask;
+    
+    CacheIterator iterator = m_cache.find(slot),
+    end = m_cache.end();
+    if (iterator != end)
+    {
+        actual_class_descriptor_sp = iterator->second;
+    }
+    else
+    {
+        Process* process(m_runtime.GetProcess());
+        uintptr_t slot_ptr = slot*process->GetAddressByteSize()+m_objc_debug_taggedpointer_classes;
+        Error error;
+        uintptr_t slot_data = process->ReadPointerFromMemory(slot_ptr, error);
+        if (error.Fail() || slot_data == 0 || slot_data == LLDB_INVALID_ADDRESS)
+            return false;
+        actual_class_descriptor_sp = m_runtime.GetClassDescriptor(slot_data);
+        if (!actual_class_descriptor_sp)
+            return ObjCLanguageRuntime::ClassDescriptorSP();
+        m_cache[slot] = actual_class_descriptor_sp;
+    }
+    
+    data_payload = (((uint64_t)ptr << m_objc_debug_taggedpointer_payload_lshift) >> m_objc_debug_taggedpointer_payload_rshift);
+    
+    return ClassDescriptorSP(new ClassDescriptorV2Tagged(actual_class_descriptor_sp,data_payload));
+}
+
+AppleObjCRuntimeV2::NonPointerISACache::NonPointerISACache (AppleObjCRuntimeV2& runtime,
+                                                            uint64_t objc_debug_isa_class_mask,
+                                                            uint64_t objc_debug_isa_magic_mask,
+                                                            uint64_t objc_debug_isa_magic_value) :
+m_runtime(runtime),
+m_cache(),
+m_objc_debug_isa_class_mask(objc_debug_isa_class_mask),
+m_objc_debug_isa_magic_mask(objc_debug_isa_magic_mask),
+m_objc_debug_isa_magic_value(objc_debug_isa_magic_value)
+{
+}
+
+ObjCLanguageRuntime::ClassDescriptorSP
+AppleObjCRuntimeV2::NonPointerISACache::GetClassDescriptor (ObjCISA isa)
+{
+    ObjCISA real_isa = 0;
+    if (EvaluateNonPointerISA(isa, real_isa) == false)
+        return ObjCLanguageRuntime::ClassDescriptorSP();
+    auto cache_iter = m_cache.find(real_isa);
+    if (cache_iter != m_cache.end())
+        return cache_iter->second;
+    auto descriptor_sp = m_runtime.ObjCLanguageRuntime::GetClassDescriptorFromISA(real_isa);
+    if (descriptor_sp) // cache only positive matches since the table might grow
+        m_cache[real_isa] = descriptor_sp;
+    return descriptor_sp;
+}
+
+bool
+AppleObjCRuntimeV2::NonPointerISACache::EvaluateNonPointerISA (ObjCISA isa, ObjCISA& ret_isa)
+{
+    if ( (isa & ~m_objc_debug_isa_class_mask) == 0)
+        return false;
+    if ( (isa & m_objc_debug_isa_magic_mask) == m_objc_debug_isa_magic_value)
+    {
+        ret_isa = isa & m_objc_debug_isa_class_mask;
+        return (ret_isa != 0); // this is a pointer so 0 is not a valid value
+    }
+    return false;
+}

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=180199&r1=180198&r2=180199&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.h (original)
+++ lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.h Wed Apr 24 12:49:08 2013
@@ -14,6 +14,7 @@
 // C++ Includes
 
 #include <map>
+#include <memory>
 
 // Other libraries and framework includes
 // Project includes
@@ -95,6 +96,9 @@ public:
     virtual ClassDescriptorSP
     GetClassDescriptor (ValueObject& in_value);
     
+    virtual ClassDescriptorSP
+    GetClassDescriptor (ObjCISA isa);
+    
     virtual TypeVendor *
     GetTypeVendor();
     
@@ -125,6 +129,118 @@ private:
         lldb::addr_t m_buckets_ptr;
     };
 
+    class NonPointerISACache
+    {
+    public:
+        static NonPointerISACache*
+        CreateInstance (AppleObjCRuntimeV2& runtime,
+                        const lldb::ModuleSP& objc_module_sp);
+        
+
+        ObjCLanguageRuntime::ClassDescriptorSP
+        GetClassDescriptor (ObjCISA isa);
+    private:
+        NonPointerISACache (AppleObjCRuntimeV2& runtime,
+                            uint64_t objc_debug_isa_class_mask,
+                            uint64_t objc_debug_isa_magic_mask,
+                            uint64_t objc_debug_isa_magic_value);
+        
+        bool
+        EvaluateNonPointerISA (ObjCISA isa, ObjCISA& ret_isa);
+        
+        AppleObjCRuntimeV2&                                         m_runtime;
+        std::map<ObjCISA,ObjCLanguageRuntime::ClassDescriptorSP>    m_cache;
+        uint64_t                                                    m_objc_debug_isa_class_mask;
+        uint64_t                                                    m_objc_debug_isa_magic_mask;
+        uint64_t                                                    m_objc_debug_isa_magic_value;
+
+        DISALLOW_COPY_AND_ASSIGN(NonPointerISACache);
+    };
+    
+    class TaggedPointerVendor
+    {
+    public:
+        static TaggedPointerVendor*
+        CreateInstance (AppleObjCRuntimeV2& runtime,
+                        const lldb::ModuleSP& objc_module_sp);
+        
+        virtual bool
+        IsPossibleTaggedPointer (lldb::addr_t ptr) = 0;
+        
+        virtual ObjCLanguageRuntime::ClassDescriptorSP
+        GetClassDescriptor (lldb::addr_t ptr) = 0;
+        
+        virtual
+        ~TaggedPointerVendor () { }
+    protected:
+        AppleObjCRuntimeV2&                                         m_runtime;
+        
+        TaggedPointerVendor (AppleObjCRuntimeV2& runtime) :
+        m_runtime(runtime)
+        {
+        }
+    private:
+        
+        DISALLOW_COPY_AND_ASSIGN(TaggedPointerVendor);
+    };
+    
+    class TaggedPointerVendorRuntimeAssisted : public TaggedPointerVendor
+    {
+    public:
+        virtual bool
+        IsPossibleTaggedPointer (lldb::addr_t ptr);
+        
+        virtual ObjCLanguageRuntime::ClassDescriptorSP
+        GetClassDescriptor (lldb::addr_t ptr);
+    protected:
+        TaggedPointerVendorRuntimeAssisted (AppleObjCRuntimeV2& runtime,
+                                             uint64_t objc_debug_taggedpointer_mask,
+                                             uint32_t objc_debug_taggedpointer_slot_shift,
+                                             uint32_t objc_debug_taggedpointer_slot_mask,
+                                             uint32_t objc_debug_taggedpointer_payload_lshift,
+                                             uint32_t objc_debug_taggedpointer_payload_rshift,
+                                             lldb::addr_t objc_debug_taggedpointer_classes);
+        
+        typedef std::map<uint8_t,ObjCLanguageRuntime::ClassDescriptorSP> Cache;
+        typedef Cache::iterator CacheIterator;
+        Cache                                                       m_cache;
+        uint64_t                                                    m_objc_debug_taggedpointer_mask;
+        uint32_t                                                    m_objc_debug_taggedpointer_slot_shift;
+        uint32_t                                                    m_objc_debug_taggedpointer_slot_mask;
+        uint32_t                                                    m_objc_debug_taggedpointer_payload_lshift;
+        uint32_t                                                    m_objc_debug_taggedpointer_payload_rshift;
+        lldb::addr_t                                                m_objc_debug_taggedpointer_classes;
+        
+        friend class AppleObjCRuntimeV2::TaggedPointerVendor;
+        
+        DISALLOW_COPY_AND_ASSIGN(TaggedPointerVendorRuntimeAssisted);
+    };
+    
+    class TaggedPointerVendorLegacy : public TaggedPointerVendor
+    {
+    public:
+        virtual bool
+        IsPossibleTaggedPointer (lldb::addr_t ptr);
+        
+        virtual ObjCLanguageRuntime::ClassDescriptorSP
+        GetClassDescriptor (lldb::addr_t ptr);
+    protected:
+        TaggedPointerVendorLegacy (AppleObjCRuntimeV2& runtime) :
+        TaggedPointerVendor (runtime),
+        m_Foundation_version(0)
+        {
+        }
+        
+        static uint32_t
+        GetFoundationVersion (Target& target);
+        
+        uint32_t m_Foundation_version;
+        
+        friend class AppleObjCRuntimeV2::TaggedPointerVendor;
+        
+        DISALLOW_COPY_AND_ASSIGN(TaggedPointerVendorLegacy);
+    };
+    
     AppleObjCRuntimeV2 (Process *process,
                         const lldb::ModuleSP &objc_module_sp);
     
@@ -150,22 +266,23 @@ private:
     lldb::addr_t
     GetSharedCacheReadOnlyAddress();
     
-    std::unique_ptr<ClangFunction>       m_get_class_info_function;
-    std::unique_ptr<ClangUtilityFunction> m_get_class_info_code;
-    lldb::addr_t                        m_get_class_info_args;
-    Mutex                               m_get_class_info_args_mutex;
-
-    std::unique_ptr<ClangFunction>        m_get_shared_cache_class_info_function;
-    std::unique_ptr<ClangUtilityFunction> m_get_shared_cache_class_info_code;
-    lldb::addr_t                        m_get_shared_cache_class_info_args;
-    Mutex                               m_get_shared_cache_class_info_args_mutex;
-
-    std::unique_ptr<TypeVendor>           m_type_vendor_ap;
-    lldb::addr_t                        m_isa_hash_table_ptr;
-    HashTableSignature                  m_hash_signature;
-    bool                                m_has_object_getClass;
-    bool                                m_loaded_objc_opt;
-    
+    std::unique_ptr<ClangFunction>            m_get_class_info_function;
+    std::unique_ptr<ClangUtilityFunction>     m_get_class_info_code;
+    lldb::addr_t                            m_get_class_info_args;
+    Mutex                                   m_get_class_info_args_mutex;
+
+    std::unique_ptr<ClangFunction>            m_get_shared_cache_class_info_function;
+    std::unique_ptr<ClangUtilityFunction>     m_get_shared_cache_class_info_code;
+    lldb::addr_t                            m_get_shared_cache_class_info_args;
+    Mutex                                   m_get_shared_cache_class_info_args_mutex;
+
+    std::unique_ptr<TypeVendor>               m_type_vendor_ap;
+    lldb::addr_t                            m_isa_hash_table_ptr;
+    HashTableSignature                      m_hash_signature;
+    bool                                    m_has_object_getClass;
+    bool                                    m_loaded_objc_opt;
+    std::unique_ptr<NonPointerISACache>       m_non_pointer_isa_cache_ap;
+    std::unique_ptr<TaggedPointerVendor>    m_tagged_pointer_vendor_ap;
 };
     
 } // namespace lldb_private





More information about the lldb-commits mailing list