[Lldb-commits] [lldb] r165730 - in /lldb/trunk: include/lldb/Core/ include/lldb/Target/ source/Core/ source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/ source/Target/

Greg Clayton gclayton at apple.com
Thu Oct 11 11:07:22 PDT 2012


Author: gclayton
Date: Thu Oct 11 13:07:21 2012
New Revision: 165730

URL: http://llvm.org/viewvc/llvm-project?rev=165730&view=rev
Log:
<rdar://problem/12331741>

Dynamic type code must be efficient and fast. Now it is.

Added ObjC v1 support for getting the complete list of ISA values.

The main flow of the AppleObjCRuntime subclasses is now they must override "virtual bool UpdateISAToDescriptorMap_Impl();". This function will update the complete list of ISA values and create ClassDescriptorSP objects for each one. Now we have the complete list of valid ISA values which we can use for verification when doing dynamic typing.

Refactored a bunch of stuff so that the AppleObjCRuntime subclasses don't have to implement as many functions as they used to.


Modified:
    lldb/trunk/include/lldb/Core/FormatNavigator.h
    lldb/trunk/include/lldb/Target/ObjCLanguageRuntime.h
    lldb/trunk/source/Core/ValueObject.cpp
    lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.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

Modified: lldb/trunk/include/lldb/Core/FormatNavigator.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Core/FormatNavigator.h?rev=165730&r1=165729&r2=165730&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Core/FormatNavigator.h (original)
+++ lldb/trunk/include/lldb/Core/FormatNavigator.h Thu Oct 11 13:07:21 2012
@@ -504,14 +504,14 @@
                 log->Printf("no valid ObjC runtime, skipping dynamic");
             return false;
         }
-        ObjCLanguageRuntime::ObjCISA isa = runtime->GetISA(valobj);
-        if (runtime->IsValidISA(isa) == false)
+        ObjCLanguageRuntime::ClassDescriptorSP objc_class_sp (runtime->GetClassDescriptor(valobj));
+        if (!objc_class_sp)
         {
             if (log)
                 log->Printf("invalid ISA, skipping dynamic");
             return false;
         }
-        ConstString name = runtime->GetActualTypeName(isa);
+        ConstString name (objc_class_sp->GetClassName());
         if (log)
             log->Printf("dynamic type inferred is %s - looking for direct dynamic match", name.GetCString());
         if (Get(name, entry))

Modified: lldb/trunk/include/lldb/Target/ObjCLanguageRuntime.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Target/ObjCLanguageRuntime.h?rev=165730&r1=165729&r2=165730&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Target/ObjCLanguageRuntime.h (original)
+++ lldb/trunk/include/lldb/Target/ObjCLanguageRuntime.h Thu Oct 11 13:07:21 2012
@@ -174,12 +174,18 @@
     virtual ClassDescriptorSP
     GetClassDescriptor (ValueObject& in_value);
     
+    ClassDescriptorSP
+    GetNonKVOClassDescriptor (ValueObject& in_value);
+
+    virtual ClassDescriptorSP
+    GetClassDescriptor (const ConstString &class_name);
+
     virtual ClassDescriptorSP
     GetClassDescriptor (ObjCISA isa);
 
     ClassDescriptorSP
     GetNonKVOClassDescriptor (ObjCISA isa);
-
+    
     virtual
     ~ObjCLanguageRuntime();
     
@@ -200,10 +206,7 @@
     
     virtual lldb::ThreadPlanSP
     GetStepThroughTrampolinePlan (Thread &thread, bool stop_others) = 0;
-    
-    virtual ClassDescriptorSP
-    CreateClassDescriptor (ObjCISA isa) = 0;
-    
+
     lldb::addr_t
     LookupInMethodCache (lldb::addr_t class_addr, lldb::addr_t sel);
 
@@ -231,17 +234,15 @@
         return eObjC_VersionUnknown;
     }
         
-    virtual bool
-    IsValidISA(ObjCISA isa) = 0;
-    
-    virtual ObjCISA
-    GetISA(ValueObject& valobj) = 0;
-    
-    virtual void
-    UpdateISAToDescriptorMap_Impl()
+    bool
+    IsValidISA(ObjCISA isa)
     {
-        // to be implemented by runtimes if they support doing this
+        UpdateISAToDescriptorMap();
+        return m_isa_to_descriptor_cache.count(isa) > 0;
     }
+
+    virtual bool
+    UpdateISAToDescriptorMap_Impl() = 0;
     
     void
     UpdateISAToDescriptorMap()
@@ -249,9 +250,7 @@
         if (m_isa_to_descriptor_cache_is_up_to_date)
             return;
         
-        m_isa_to_descriptor_cache_is_up_to_date = true;
-
-        UpdateISAToDescriptorMap_Impl();
+        m_isa_to_descriptor_cache_is_up_to_date = UpdateISAToDescriptorMap_Impl();
     }
     
     virtual ObjCISA

Modified: lldb/trunk/source/Core/ValueObject.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/ValueObject.cpp?rev=165730&r1=165729&r2=165730&view=diff
==============================================================================
--- lldb/trunk/source/Core/ValueObject.cpp (original)
+++ lldb/trunk/source/Core/ValueObject.cpp Thu Oct 11 13:07:21 2012
@@ -3223,12 +3223,11 @@
                             s.Printf(", dynamic type: unknown) ");
                         else
                         {
-                            ObjCLanguageRuntime::ObjCISA isa = runtime->GetISA(*valobj);
-                            if (!runtime->IsValidISA(isa))
-                                s.Printf(", dynamic type: unknown) ");
+                            ObjCLanguageRuntime::ClassDescriptorSP objc_class_sp (runtime->GetNonKVOClassDescriptor(*valobj));
+                            if (objc_class_sp)
+                                s.Printf(", dynamic type: %s) ", objc_class_sp->GetClassName().GetCString());
                             else
-                                s.Printf(", dynamic type: %s) ",
-                                         runtime->GetActualTypeName(isa).GetCString());
+                                s.Printf(", dynamic type: unknown) ");
                         }
                     }
                 }

Modified: lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.cpp?rev=165730&r1=165729&r2=165730&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.cpp (original)
+++ lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.cpp Thu Oct 11 13:07:21 2012
@@ -168,6 +168,30 @@
     return cstr_len > 0;
 }
 
+lldb::ModuleSP
+AppleObjCRuntime::GetObjCModule ()
+{
+    ModuleSP module_sp (m_objc_module_wp.lock());
+    if (module_sp)
+        return module_sp;
+
+    Process *process = GetProcess();
+    if (process)
+    {
+        ModuleList& modules = process->GetTarget().GetImages();
+        for (uint32_t idx = 0; idx < modules.GetSize(); idx++)
+        {
+            module_sp = modules.GetModuleAtIndex(idx);
+            if (AppleObjCRuntime::AppleIsModuleObjCLibrary(module_sp))
+            {
+                m_objc_module_wp = module_sp;
+                return module_sp;
+            }
+        }
+    }
+    return ModuleSP();
+}
+
 Address *
 AppleObjCRuntime::GetPrintForDebuggerAddr()
 {
@@ -211,15 +235,17 @@
 bool
 AppleObjCRuntime::AppleIsModuleObjCLibrary (const ModuleSP &module_sp)
 {
-    const FileSpec &module_file_spec = module_sp->GetFileSpec();
-    static ConstString ObjCName ("libobjc.A.dylib");
-    
-    if (module_file_spec)
+    if (module_sp)
     {
-        if (module_file_spec.GetFilename() == ObjCName)
-            return true;
+        const FileSpec &module_file_spec = module_sp->GetFileSpec();
+        static ConstString ObjCName ("libobjc.A.dylib");
+        
+        if (module_file_spec)
+        {
+            if (module_file_spec.GetFilename() == ObjCName)
+                return true;
+        }
     }
-    
     return false;
 }
 

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=165730&r1=165729&r2=165730&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.h (original)
+++ lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.h Thu Oct 11 13:07:21 2012
@@ -63,17 +63,10 @@
     virtual lldb::ThreadPlanSP
     GetStepThroughTrampolinePlan (Thread &thread, bool stop_others);
     
-    virtual bool
-    IsValidISA(ObjCISA isa)
-    {
-        return false;
-    }
-    
-    virtual ObjCISA
-    GetISA(ValueObject& valobj)
-    {
-        return 0;
-    }
+    // Get the "libobjc.A.dylib" module from the current target if we can find
+    // it, also cache it once it is found to ensure quick lookups.
+    lldb::ModuleSP
+    GetObjCModule ();
     
     //------------------------------------------------------------------
     // Static Functions
@@ -111,8 +104,9 @@
     bool m_read_objc_library;
     std::auto_ptr<lldb_private::AppleObjCTrampolineHandler> m_objc_trampoline_handler_ap;
     lldb::BreakpointSP m_objc_exception_bp_sp;
+    lldb::ModuleWP m_objc_module_wp;
 
-    AppleObjCRuntime(Process *process) : 
+    AppleObjCRuntime(Process *process) :
         lldb_private::ObjCLanguageRuntime(process),
         m_read_objc_library (false),
         m_objc_trampoline_handler_ap(NULL)

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=165730&r1=165729&r2=165730&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.cpp (original)
+++ lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.cpp Thu Oct 11 13:07:21 2012
@@ -24,6 +24,7 @@
 #include "lldb/Expression/ClangFunction.h"
 #include "lldb/Expression/ClangUtilityFunction.h"
 #include "lldb/Symbol/ClangASTContext.h"
+#include "lldb/Symbol/Symbol.h"
 #include "lldb/Target/ExecutionContext.h"
 #include "lldb/Target/Process.h"
 #include "lldb/Target/RegisterContext.h"
@@ -155,35 +156,35 @@
 
 // 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)
+//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;
-    
-    // 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;
-}
+//    
+//    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)
 {
@@ -287,11 +288,124 @@
     return ObjCLanguageRuntime::ClassDescriptorSP(new AppleObjCRuntimeV1::ClassDescriptorV1(m_parent_isa,process_sp));
 }
 
-ObjCLanguageRuntime::ClassDescriptorSP
-AppleObjCRuntimeV1::CreateClassDescriptor (ObjCISA isa)
+bool
+AppleObjCRuntimeV1::UpdateISAToDescriptorMap_Impl()
 {
-    ClassDescriptorSP objc_class_sp;
-    if (isa != 0)
-        objc_class_sp.reset (new ClassDescriptorV1(isa,m_process->CalculateProcess()));
-    return objc_class_sp;
+    lldb::LogSP log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
+    
+    Process *process_ptr = GetProcess();
+    
+    if (!process_ptr)
+        return false;
+    
+    ProcessSP process_sp = process_ptr->shared_from_this();
+    
+    ModuleSP objc_module_sp(GetObjCModule());
+    
+    if (!objc_module_sp)
+        return false;
+    
+    uint32_t isa_count = 0;
+    
+    static ConstString g_objc_debug_class_hash("_objc_debug_class_hash");
+    
+    const Symbol *symbol = objc_module_sp->FindFirstSymbolWithNameAndType(g_objc_debug_class_hash, lldb::eSymbolTypeData);
+    if (symbol)
+    {
+        lldb::addr_t objc_debug_class_hash_addr = symbol->GetAddress().GetLoadAddress(&process_sp->GetTarget());
+        
+        if (objc_debug_class_hash_addr != LLDB_INVALID_ADDRESS)
+        {
+            Error error;
+            lldb::addr_t objc_debug_class_hash_ptr = process_sp->ReadPointerFromMemory(objc_debug_class_hash_addr, error);
+            if (error.Success() && objc_debug_class_hash_ptr != 0 && objc_debug_class_hash_ptr != LLDB_INVALID_ADDRESS)
+            {
+                // Read the NXHashTable struct:
+                //
+                // typedef struct {
+                //     const NXHashTablePrototype *prototype;
+                //     unsigned   count;
+                //     unsigned   nbBuckets;
+                //     void       *buckets;
+                //     const void *info;
+                // } NXHashTable;
+
+                DataBufferHeap buffer(1024, 0);
+                if (process_sp->ReadMemory(objc_debug_class_hash_ptr, buffer.GetBytes(), 20, error) == 20)
+                {
+                    const uint32_t addr_size = m_process->GetAddressByteSize();
+                    const ByteOrder byte_order = m_process->GetByteOrder();
+                    DataExtractor data (buffer.GetBytes(), buffer.GetByteSize(), byte_order, addr_size);
+                    uint32_t offset = addr_size + 4; // Skip prototype
+                    const uint32_t num_buckets = data.GetU32(&offset);
+                    const addr_t buckets_ptr = data.GetPointer(&offset);
+                
+                    const uint32_t data_size = num_buckets * 2 * sizeof(uint32_t);
+                    buffer.SetByteSize(data_size);
+                    
+                    if (process_sp->ReadMemory(buckets_ptr, buffer.GetBytes(), data_size, error) == data_size)
+                    {
+                        data.SetData(buffer.GetBytes(), buffer.GetByteSize(), byte_order);
+                        offset = 0;
+                        for (uint32_t bucket_idx = 0; bucket_idx < num_buckets; ++bucket_idx)
+                        {
+                            const uint32_t bucket_isa_count = data.GetU32 (&offset);
+                            const lldb::addr_t bucket_data = data.GetU32 (&offset);
+                            
+
+                            if (bucket_isa_count == 0)
+                                continue;
+                            
+                            isa_count += bucket_isa_count;
+
+                            ObjCISA isa;
+                            if (bucket_isa_count == 1)
+                            {
+                                // When we only have one entry in the bucket, the bucket data is the "isa"
+                                isa = bucket_data;
+                                if (isa)
+                                {
+                                    if (m_isa_to_descriptor_cache.count(isa) == 0)
+                                    {
+                                        ClassDescriptorSP descriptor_sp (new ClassDescriptorV1(isa, process_sp));
+                                        
+                                        if (log && log->GetVerbose())
+                                            log->Printf("AppleObjCRuntimeV1 added (ObjCISA)0x%llx from _objc_debug_class_hash to isa->descriptor cache", isa);
+                                        
+                                        m_isa_to_descriptor_cache[isa] = descriptor_sp;
+                                    }
+                                }
+                            }
+                            else
+                            {
+                                // When we have more than one entry in the bucket, the bucket data is a pointer
+                                // to an array of "isa" values
+                                addr_t isa_addr = bucket_data;
+                                for (uint32_t isa_idx = 0; isa_idx < bucket_isa_count; ++isa_idx, isa_addr += addr_size)
+                                {
+                                    isa = m_process->ReadPointerFromMemory(isa_addr, error);
+
+                                    if (isa && isa != LLDB_INVALID_ADDRESS)
+                                    {
+                                        if (m_isa_to_descriptor_cache.count(isa) == 0)
+                                        {
+                                            ClassDescriptorSP descriptor_sp (new ClassDescriptorV1(isa, process_sp));
+                                            
+                                            if (log && log->GetVerbose())
+                                                log->Printf("AppleObjCRuntimeV1 added (ObjCISA)0x%llx from _objc_debug_class_hash to isa->descriptor cache", isa);
+                                            
+                                            m_isa_to_descriptor_cache[isa] = descriptor_sp;
+                                        }
+                                    }
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    return isa_count > 0;
 }
+

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=165730&r1=165729&r2=165730&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.h (original)
+++ lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.h Thu Oct 11 13:07:21 2012
@@ -124,17 +124,8 @@
     }
     
     virtual bool
-    IsValidISA(ObjCISA isa)
-    {
-        return (isa != 0) && ( (isa % 2) == 0);
-    }
-    
-    virtual ObjCISA
-    GetISA(ValueObject& valobj);
-    
-    virtual ClassDescriptorSP
-    CreateClassDescriptor (ObjCISA isa);
-    
+    UpdateISAToDescriptorMap_Impl();
+
 protected:
     virtual lldb::BreakpointResolverSP
     CreateExceptionResolver (Breakpoint *bkpt, bool catch_bp, bool throw_bp);

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=165730&r1=165729&r2=165730&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp (original)
+++ lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp Thu Oct 11 13:07:21 2012
@@ -585,7 +585,7 @@
 bool
 AppleObjCRuntimeV2::IsTaggedPointer(addr_t ptr)
 {
-    return (ptr & 0x01);
+    return (ptr & 1);
 }
 
 class RemoteNXMapTable
@@ -597,7 +597,7 @@
         m_end_iterator(*this, -1),
         m_load_addr(load_addr),
         m_map_pair_size(m_process_sp->GetAddressByteSize() * 2),
-        m_NXMAPNOTAKEY(m_process_sp->GetAddressByteSize() == 8 ? 0xffffffffffffffffull : 0xffffffffull)
+        m_NXMAPNOTAKEY(m_process_sp->GetAddressByteSize() == 8 ? UINT64_MAX : UINT32_MAX)
     {
         lldb::addr_t cursor = load_addr;
      
@@ -1668,49 +1668,45 @@
 };
 
 ObjCLanguageRuntime::ClassDescriptorSP
-AppleObjCRuntimeV2::CreateClassDescriptor (ObjCISA isa)
-{
-    UpdateISAToDescriptorMap();
-    
-    ISAToDescriptorMap::const_iterator di = m_isa_to_descriptor_cache.find(isa);
-    
-    if (di == m_isa_to_descriptor_cache.end())
-        return ObjCLanguageRuntime::ClassDescriptorSP();
-    else
-        return di->second;
-}
-
-ObjCLanguageRuntime::ClassDescriptorSP
-AppleObjCRuntimeV2::GetClassDescriptor (ValueObject& in_value)
+AppleObjCRuntimeV2::GetClassDescriptor (ValueObject& valobj)
 {
     ClassDescriptorSP objc_class_sp;
-    uint64_t ptr_value = in_value.GetValueAsUnsigned(0);
-    if (ptr_value)
+    // 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)
     {
-        if (ptr_value & 1)
-            objc_class_sp = ClassDescriptorSP(new ClassDescriptorV2Tagged(in_value));
+        addr_t isa_pointer = valobj.GetPointerValue();
+        
+        // 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();
+        }
         else
-            objc_class_sp = ObjCLanguageRuntime::GetClassDescriptor (in_value);
+        {
+            ExecutionContext exe_ctx (valobj.GetExecutionContextRef());
+            
+            Process *process = exe_ctx.GetProcessPtr();
+            if (process)
+            {
+                Error error;
+                ObjCISA isa = process->ReadPointerFromMemory(isa_pointer, error);
+                if (isa != LLDB_INVALID_ADDRESS)
+                    objc_class_sp = ObjCLanguageRuntime::GetClassDescriptor (isa);
+            }
+        }
     }
     return objc_class_sp;
 }
 
-ModuleSP FindLibobjc (Target &target)
-{
-    ModuleList& modules = target.GetImages();
-    for (uint32_t idx = 0; idx < modules.GetSize(); idx++)
-    {
-        lldb::ModuleSP module_sp = modules.GetModuleAtIndex(idx);
-        if (!module_sp)
-            continue;
-        if (strncmp(module_sp->GetFileSpec().GetFilename().AsCString(""), "libobjc.", sizeof("libobjc.") - 1) == 0)
-            return module_sp;
-    }
-    
-    return ModuleSP();
-}
-
-void
+bool
 AppleObjCRuntimeV2::UpdateISAToDescriptorMap_Impl()
 {
     lldb::LogSP log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
@@ -1718,193 +1714,105 @@
     Process *process_ptr = GetProcess();
     
     if (!process_ptr)
-        return;
-    
-    ProcessSP process_sp = process_ptr->shared_from_this();
+        return false;
     
-    Target &target(process_sp->GetTarget());
+    ProcessSP process_sp (process_ptr->shared_from_this());
     
-    ModuleSP objc_module_sp(FindLibobjc(target));
+    ModuleSP objc_module_sp(GetObjCModule());
     
     if (!objc_module_sp)
-        return;
-    
-    do
-    {
-        SymbolContextList sc_list;
-    
-        size_t num_symbols = objc_module_sp->FindSymbolsWithNameAndType(ConstString("gdb_objc_realized_classes"),
-                                                                        lldb::eSymbolTypeData,
-                                                                        sc_list);
-    
-        if (!num_symbols)
-            break;
-        
-        SymbolContext gdb_objc_realized_classes_sc;
-        
-        if (!sc_list.GetContextAtIndex(0, gdb_objc_realized_classes_sc))
-             break;
-        
-        AddressRange gdb_objc_realized_classes_addr_range;
-        
-        const uint32_t scope = eSymbolContextSymbol;
-        const uint32_t range_idx = 0;
-        bool use_inline_block_range = false;
+        return false;
 
-        if (!gdb_objc_realized_classes_sc.GetAddressRange(scope,
-                                                          range_idx,
-                                                          use_inline_block_range,
-                                                          gdb_objc_realized_classes_addr_range))
-            break;
-        
-        lldb::addr_t gdb_objc_realized_classes_ptr = gdb_objc_realized_classes_addr_range.GetBaseAddress().GetLoadAddress(&target);
-        
-        if (gdb_objc_realized_classes_ptr == LLDB_INVALID_ADDRESS)
-            break;
-    
-        // <rdar://problem/10763513>
-        
-        lldb::addr_t gdb_objc_realized_classes_nxmaptable_ptr;
+    uint32_t num_map_table_isas = 0;
+    uint32_t num_objc_opt_ro_isas = 0;
+
+    static ConstString g_gdb_objc_realized_classes("gdb_objc_realized_classes");
+
+    const Symbol *symbol = objc_module_sp->FindFirstSymbolWithNameAndType(g_gdb_objc_realized_classes, lldb::eSymbolTypeData);
+    if (symbol)
+    {
+        lldb::addr_t gdb_objc_realized_classes_ptr = symbol->GetAddress().GetLoadAddress(&process_sp->GetTarget());
         
+        if (gdb_objc_realized_classes_ptr != LLDB_INVALID_ADDRESS)
         {
+            // <rdar://problem/10763513>
+
+            lldb::addr_t gdb_objc_realized_classes_nxmaptable_ptr;
+            
             Error err;
             gdb_objc_realized_classes_nxmaptable_ptr = process_sp->ReadPointerFromMemory(gdb_objc_realized_classes_ptr, err);
-            if (!err.Success())
-                break;
-        }
-        
-        RemoteNXMapTable gdb_objc_realized_classes(process_sp, gdb_objc_realized_classes_nxmaptable_ptr);
-    
-        for (RemoteNXMapTable::element elt : gdb_objc_realized_classes)
-        {
-            if (m_isa_to_descriptor_cache.count(elt.second))
-                continue;
-            
-            ClassDescriptorSP descriptor_sp = ClassDescriptorSP(new ClassDescriptorV2(*this, elt.second));
-            
-            if (log && log->GetVerbose())
-                log->Printf("AppleObjCRuntimeV2 added (ObjCISA)0x%llx (%s) from dynamic table to isa->descriptor cache", elt.second, elt.first.AsCString());
+            if (err.Success())
+            {
+                RemoteNXMapTable gdb_objc_realized_classes(process_sp, gdb_objc_realized_classes_nxmaptable_ptr);
             
-            m_isa_to_descriptor_cache[elt.second] = descriptor_sp;
+                for (RemoteNXMapTable::element elt : gdb_objc_realized_classes)
+                {
+                    ++num_map_table_isas;
+                    
+                    if (m_isa_to_descriptor_cache.count(elt.second))
+                        continue;
+                    
+                    ClassDescriptorSP descriptor_sp = ClassDescriptorSP(new ClassDescriptorV2(*this, elt.second));
+                    
+                    if (log && log->GetVerbose())
+                        log->Printf("AppleObjCRuntimeV2 added (ObjCISA)0x%llx (%s) from dynamic table to isa->descriptor cache", elt.second, elt.first.AsCString());
+                    
+                    m_isa_to_descriptor_cache[elt.second] = descriptor_sp;
+                }
+            }
         }
     }
-    while(0);
     
-    do
+    ObjectFile *objc_object = objc_module_sp->GetObjectFile();
+    
+    if (objc_object)
     {
-        ObjectFile *objc_object = objc_module_sp->GetObjectFile();
-        
-        if (!objc_object)
-            break;
-        
         SectionList *section_list = objc_object->GetSectionList();
-        
-        if (!section_list)
-            break;
-        
-        SectionSP TEXT_section_sp = section_list->FindSectionByName(ConstString("__TEXT"));
-        
-        if (!TEXT_section_sp)
-            break;
-        
-        SectionList &TEXT_children = TEXT_section_sp->GetChildren();
-        
-        SectionSP objc_opt_section_sp = TEXT_children.FindSectionByName(ConstString("__objc_opt_ro"));
-        
-        if (!objc_opt_section_sp)
-            break;
-        
-        lldb::addr_t objc_opt_ptr = objc_opt_section_sp->GetLoadBaseAddress(&target);
-        
-        if (objc_opt_ptr == LLDB_INVALID_ADDRESS)
-            break;
-        
-        RemoteObjCOpt objc_opt(process_sp, objc_opt_ptr);
-        
-        for (ObjCLanguageRuntime::ObjCISA objc_isa : objc_opt)
+    
+        if (section_list)
         {
-            if (m_isa_to_descriptor_cache.count(objc_isa))
-                continue;
+            SectionSP text_segment_sp (section_list->FindSectionByName(ConstString("__TEXT")));
             
-            ClassDescriptorSP descriptor_sp = ClassDescriptorSP(new ClassDescriptorV2(*this, objc_isa));
-            
-            if (log && log->GetVerbose())
-                log->Printf("AppleObjCRuntimeV2 added (ObjCISA)0x%llx (%s) from static table to isa->descriptor cache", objc_isa, descriptor_sp->GetClassName().AsCString());
-            
-            m_isa_to_descriptor_cache[objc_isa] = descriptor_sp;
+            if (text_segment_sp)
+            {
+                SectionSP objc_opt_section_sp (text_segment_sp->GetChildren().FindSectionByName(ConstString("__objc_opt_ro")));
+                
+                if (objc_opt_section_sp)
+                {
+                    lldb::addr_t objc_opt_ptr = objc_opt_section_sp->GetLoadBaseAddress(&process_sp->GetTarget());
+                    
+                    if (objc_opt_ptr != LLDB_INVALID_ADDRESS)
+                    {
+                        RemoteObjCOpt objc_opt(process_sp, objc_opt_ptr);
+                        
+                        for (ObjCLanguageRuntime::ObjCISA objc_isa : objc_opt)
+                        {
+                            ++num_objc_opt_ro_isas;
+                            if (m_isa_to_descriptor_cache.count(objc_isa))
+                                continue;
+                            
+                            ClassDescriptorSP descriptor_sp = ClassDescriptorSP(new ClassDescriptorV2(*this, objc_isa));
+                            
+                            if (log && log->GetVerbose())
+                                log->Printf("AppleObjCRuntimeV2 added (ObjCISA)0x%llx (%s) from static table to isa->descriptor cache", objc_isa, descriptor_sp->GetClassName().AsCString());
+                            
+                            m_isa_to_descriptor_cache[objc_isa] = descriptor_sp;
+                        }
+                    }
+                }
+            }
         }
     }
-    while (0);
-}
-
-// 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
-// struct class_t in the ObjCv2 runtime
-ObjCLanguageRuntime::ObjCISA
-AppleObjCRuntimeV2::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();
     
-    // tagged pointer
-    if (IsTaggedPointer(isa_pointer))
-    {
-        ClassDescriptorV2Tagged descriptor(valobj);
-        
-        // probably an invalid tagged pointer - say it's wrong
-        if (!descriptor.IsValid())
-            return 0;
-        
-        static const ConstString g_objc_tagged_isa_nsatom_name ("NSAtom");
-        static const ConstString g_objc_tagged_isa_nsnumber_name ("NSNumber");
-        static const ConstString g_objc_tagged_isa_nsdatets_name ("NSDateTS");
-        static const ConstString g_objc_tagged_isa_nsmanagedobject_name ("NSManagedObject");
-        static const ConstString g_objc_tagged_isa_nsdate_name ("NSDate");
-        
-        ConstString class_name_const_string = descriptor.GetClassName();
-
-        if (class_name_const_string == g_objc_tagged_isa_nsatom_name)
-            return g_objc_Tagged_ISA_NSAtom;
-        if (class_name_const_string == g_objc_tagged_isa_nsnumber_name)
-            return g_objc_Tagged_ISA_NSNumber;
-        if (class_name_const_string == g_objc_tagged_isa_nsdatets_name)
-            return g_objc_Tagged_ISA_NSDateTS;
-        if (class_name_const_string == g_objc_tagged_isa_nsmanagedobject_name)
-            return g_objc_Tagged_ISA_NSManagedObject;
-        if (class_name_const_string == g_objc_tagged_isa_nsdate_name)
-            return g_objc_Tagged_ISA_NSDate;
-        return g_objc_Tagged_ISA;
-    }
-
-    ExecutionContext exe_ctx (valobj.GetExecutionContextRef());
-
-    Process *process = exe_ctx.GetProcessPtr();
-    if (process)
-    {
-        Error error;
-        ObjCISA isa = process->ReadPointerFromMemory(isa_pointer, error);
-        if (isa != LLDB_INVALID_ADDRESS)
-            return isa;
-    }
-    return 0; // For some reason zero is being used to indicate invalid ISA instead of LLDB_INVALID_ADDRESS
+    return num_objc_opt_ro_isas > 0 && num_map_table_isas > 0;
 }
 
+
 // TODO: should we have a transparent_kvo parameter here to say if we
 // want to replace the KVO swizzled class with the actual user-level type?
 ConstString
 AppleObjCRuntimeV2::GetActualTypeName(ObjCLanguageRuntime::ObjCISA isa)
 {
-    if (!IsValidISA(isa))
-        return ConstString();
-     
     if (isa == g_objc_Tagged_ISA)
     {
         static const ConstString g_objc_tagged_isa_name ("_lldb_Tagged_ObjC_ISA");
@@ -1935,7 +1843,6 @@
         static const ConstString g_objc_tagged_isa_nsdate_name ("NSDate");
         return g_objc_tagged_isa_nsdate_name;
     }
-    
     return ObjCLanguageRuntime::GetActualTypeName(isa);
 }
 

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=165730&r1=165729&r2=165730&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.h (original)
+++ lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.h Thu Oct 11 13:07:21 2012
@@ -73,14 +73,8 @@
     virtual size_t
     GetByteOffsetForIvar (ClangASTType &parent_qual_type, const char *ivar_name);
     
-    virtual void
-    UpdateISAToDescriptorMap_Impl();
-    
     virtual bool
-    IsValidISA (ObjCLanguageRuntime::ObjCISA isa)
-    {
-        return (isa != 0);
-    }
+    UpdateISAToDescriptorMap_Impl();
     
     // none of these are valid ISAs - we use them to infer the type
     // of tagged pointers - if we have something meaningful to say
@@ -94,19 +88,12 @@
     static const ObjCLanguageRuntime::ObjCISA g_objc_Tagged_ISA_NSManagedObject = 5;
     static const ObjCLanguageRuntime::ObjCISA g_objc_Tagged_ISA_NSDate = 6;
 
-    
-    virtual ObjCLanguageRuntime::ObjCISA
-    GetISA(ValueObject& valobj);
-    
     virtual ConstString
     GetActualTypeName(ObjCLanguageRuntime::ObjCISA isa);
     
     virtual ClassDescriptorSP
     GetClassDescriptor (ValueObject& in_value);
     
-    virtual ClassDescriptorSP
-    CreateClassDescriptor (ObjCISA isa);
-    
     virtual TypeVendor *
     GetTypeVendor();
     

Modified: lldb/trunk/source/Target/ObjCLanguageRuntime.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/ObjCLanguageRuntime.cpp?rev=165730&r1=165729&r2=165730&view=diff
==============================================================================
--- lldb/trunk/source/Target/ObjCLanguageRuntime.cpp (original)
+++ lldb/trunk/source/Target/ObjCLanguageRuntime.cpp Thu Oct 11 13:07:21 2012
@@ -31,6 +31,7 @@
 ObjCLanguageRuntime::ObjCLanguageRuntime (Process *process) :
     LanguageRuntime (process),
     m_has_new_literals_and_indexing (eLazyBoolCalculate),
+    m_isa_to_descriptor_cache(),
     m_isa_to_descriptor_cache_is_up_to_date (false)
 {
 
@@ -284,24 +285,10 @@
 ObjCLanguageRuntime::ObjCISA
 ObjCLanguageRuntime::GetISA(const ConstString &name)
 {
-    // Try once regardless of whether the map has been brought up to date.  We
-    // might have encountered the relevant isa directly.
-    for (const ISAToDescriptorMap::value_type &val : m_isa_to_descriptor_cache)
-        if (val.second && val.second->GetClassName() == name)
-            return val.first;
- 
-    // If the map is up to date and we didn't find the isa, give up.
-    if (m_isa_to_descriptor_cache_is_up_to_date)
-        return 0;
-    
-    // Try again after bringing the map up to date.
     UpdateISAToDescriptorMap();
-
     for (const ISAToDescriptorMap::value_type &val : m_isa_to_descriptor_cache)
         if (val.second && val.second->GetClassName() == name)
             return val.first;
-    
-    // Now we know for sure that the class isn't there.  Give up.
     return 0;
 }
 
@@ -318,8 +305,6 @@
     return 0;
 }
 
-// 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)
 {
@@ -330,34 +315,74 @@
 }
 
 ObjCLanguageRuntime::ClassDescriptorSP
-ObjCLanguageRuntime::GetClassDescriptor (ValueObject& in_value)
+ObjCLanguageRuntime::GetClassDescriptor (const ConstString &class_name)
 {
-    ObjCISA isa = GetISA(in_value);
-    if (isa)
-        return GetClassDescriptor (isa);
+    UpdateISAToDescriptorMap();
+    for (const ISAToDescriptorMap::value_type &val : m_isa_to_descriptor_cache)
+        if (val.second && val.second->GetClassName() == class_name)
+            return val.second;
     return ClassDescriptorSP();
+
 }
 
 ObjCLanguageRuntime::ClassDescriptorSP
-ObjCLanguageRuntime::GetClassDescriptor (ObjCISA isa)
+ObjCLanguageRuntime::GetClassDescriptor (ValueObject& valobj)
 {
     ClassDescriptorSP objc_class_sp;
-    if (isa)
+    // 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)
     {
-        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;
-    
-        objc_class_sp = CreateClassDescriptor(isa);
-        if (objc_class_sp && objc_class_sp->IsValid())
-            m_isa_to_descriptor_cache[isa] = objc_class_sp;
+        addr_t isa_pointer = valobj.GetPointerValue();
+        if (isa_pointer != LLDB_INVALID_ADDRESS)
+        {
+            ExecutionContext exe_ctx (valobj.GetExecutionContextRef());
+            
+            Process *process = exe_ctx.GetProcessPtr();
+            if (process)
+            {
+                Error error;
+                ObjCISA isa = process->ReadPointerFromMemory(isa_pointer, error);
+                if (isa != LLDB_INVALID_ADDRESS)
+                    objc_class_sp = GetClassDescriptor (isa);
+            }
+        }
     }
     return objc_class_sp;
 }
 
 ObjCLanguageRuntime::ClassDescriptorSP
+ObjCLanguageRuntime::GetNonKVOClassDescriptor (ValueObject& valobj)
+{
+    ObjCLanguageRuntime::ClassDescriptorSP objc_class_sp (GetClassDescriptor (valobj));
+    if (objc_class_sp)
+    {
+        if (!objc_class_sp->IsKVO())
+            return objc_class_sp;
+        
+        ClassDescriptorSP non_kvo_objc_class_sp(objc_class_sp->GetSuperclass());
+        if (non_kvo_objc_class_sp && non_kvo_objc_class_sp->IsValid())
+            return non_kvo_objc_class_sp;
+    }
+    return ClassDescriptorSP();
+}
+
+
+ObjCLanguageRuntime::ClassDescriptorSP
+ObjCLanguageRuntime::GetClassDescriptor (ObjCISA isa)
+{
+    if (isa)
+    {
+        UpdateISAToDescriptorMap();
+        ObjCLanguageRuntime::ISAToDescriptorIterator pos = m_isa_to_descriptor_cache.find(isa);    
+        if (pos != m_isa_to_descriptor_cache.end())
+            return pos->second;
+    }
+    return ClassDescriptorSP();
+}
+
+ObjCLanguageRuntime::ClassDescriptorSP
 ObjCLanguageRuntime::GetNonKVOClassDescriptor (ObjCISA isa)
 {
     if (isa)
@@ -365,14 +390,12 @@
         ClassDescriptorSP objc_class_sp = GetClassDescriptor (isa);
         if (objc_class_sp && objc_class_sp->IsValid())
         {
-            if (objc_class_sp->IsKVO())
-            {
-                ClassDescriptorSP non_kvo_objc_class_sp(objc_class_sp->GetSuperclass());
-                if (non_kvo_objc_class_sp && non_kvo_objc_class_sp->IsValid())
-                    return non_kvo_objc_class_sp;
-            }
-            else
+            if (!objc_class_sp->IsKVO())
                 return objc_class_sp;
+
+            ClassDescriptorSP non_kvo_objc_class_sp(objc_class_sp->GetSuperclass());
+            if (non_kvo_objc_class_sp && non_kvo_objc_class_sp->IsValid())
+                return non_kvo_objc_class_sp;
         }
     }
     return ClassDescriptorSP();





More information about the lldb-commits mailing list