[Lldb-commits] [lldb] r276220 - Fix an issue where LLDB would detect an empty shared cache - which is legitimate albeit suboptimal - and warn about being unable to fetch ObjC class information, even though class data was actually properly loaded from the dynamic hashmap

Enrico Granata via lldb-commits lldb-commits at lists.llvm.org
Wed Jul 20 17:13:40 PDT 2016


Author: enrico
Date: Wed Jul 20 19:13:40 2016
New Revision: 276220

URL: http://llvm.org/viewvc/llvm-project?rev=276220&view=rev
Log:
Fix an issue where LLDB would detect an empty shared cache - which is legitimate albeit suboptimal - and warn about being unable to fetch ObjC class information, even though class data was actually properly loaded from the dynamic hashmap

Only ever warn about missing ObjC runtime class data if one either can't run the expressions to obtain such data, or the total count of classes is below a threshold that makes things sound really suspicious

Fixes rdar://27438500


Modified:
    lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp
    lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.h

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=276220&r1=276219&r2=276220&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp (original)
+++ lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp Wed Jul 20 19:13:40 2016
@@ -1350,13 +1350,15 @@ AppleObjCRuntimeV2::GetISAHashTablePoint
     return m_isa_hash_table_ptr;
 }
 
-bool
+AppleObjCRuntimeV2::DescriptorMapUpdateResult
 AppleObjCRuntimeV2::UpdateISAToDescriptorMapDynamic(RemoteNXMapTable &hash_table)
 {
     Process *process = GetProcess();
     
     if (process == NULL)
-        return false;
+        return DescriptorMapUpdateResult::Fail();
+    
+    uint32_t num_class_infos = 0;
     
     Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
     
@@ -1365,13 +1367,13 @@ AppleObjCRuntimeV2::UpdateISAToDescripto
     ThreadSP thread_sp = process->GetThreadList().GetExpressionExecutionThread();
     
     if (!thread_sp)
-        return false;
+        return DescriptorMapUpdateResult::Fail();
     
     thread_sp->CalculateExecutionContext(exe_ctx);
     ClangASTContext *ast = process->GetTarget().GetScratchClangASTContext();
     
     if (!ast)
-        return false;
+        return DescriptorMapUpdateResult::Fail();
 
     Address function_address;
 
@@ -1387,7 +1389,7 @@ AppleObjCRuntimeV2::UpdateISAToDescripto
     {
         if (log)
             log->Printf ("No dynamic classes found in gdb_objc_realized_classes.");
-        return false;
+        return DescriptorMapUpdateResult::Fail();
     }
     
     // Make some types for our arguments
@@ -1425,7 +1427,7 @@ AppleObjCRuntimeV2::UpdateISAToDescripto
             }
         }
         if (!m_get_class_info_code.get())
-            return false;
+            return DescriptorMapUpdateResult::Fail();
         
         // Next make the runner function for our implementation utility function.
         Value value;
@@ -1448,7 +1450,7 @@ AppleObjCRuntimeV2::UpdateISAToDescripto
         {
             if (log)
                 log->Printf("Failed to make function caller for implementation lookup: %s.", error.AsCString());
-            return false;
+            return DescriptorMapUpdateResult::Fail();
         }
     }
     else
@@ -1462,7 +1464,7 @@ AppleObjCRuntimeV2::UpdateISAToDescripto
                 diagnostics.Dump(log);
             }
 
-            return false;
+            return DescriptorMapUpdateResult::Fail();
         }
         arguments = get_class_info_function->GetArgumentValues();
     }
@@ -1476,7 +1478,7 @@ AppleObjCRuntimeV2::UpdateISAToDescripto
                                                             err);
     
     if (class_infos_addr == LLDB_INVALID_ADDRESS)
-        return false;
+        return DescriptorMapUpdateResult::Fail();
 
     std::lock_guard<std::mutex> guard(m_get_class_info_args_mutex);
 
@@ -1516,7 +1518,7 @@ AppleObjCRuntimeV2::UpdateISAToDescripto
         if (results == eExpressionCompleted)
         {
             // The result is the number of ClassInfo structures that were filled in
-            uint32_t num_class_infos = return_value.GetScalar().ULong();
+            num_class_infos = return_value.GetScalar().ULong();
             if (log)
                 log->Printf("Discovered %u ObjC classes\n",num_class_infos);
             if (num_class_infos > 0)
@@ -1555,7 +1557,7 @@ AppleObjCRuntimeV2::UpdateISAToDescripto
     // Deallocate the memory we allocated for the ClassInfo array
     process->DeallocateMemory(class_infos_addr);
     
-    return success;
+    return DescriptorMapUpdateResult(success, num_class_infos);
 }
 
 uint32_t
@@ -1636,6 +1638,8 @@ AppleObjCRuntimeV2::UpdateISAToDescripto
 
     Error err;
     
+    uint32_t num_class_infos = 0;
+    
     const lldb::addr_t objc_opt_ptr = GetSharedCacheReadOnlyAddress();
     
     if (objc_opt_ptr == LLDB_INVALID_ADDRESS)
@@ -1770,7 +1774,7 @@ AppleObjCRuntimeV2::UpdateISAToDescripto
         if (results == eExpressionCompleted)
         {
             // The result is the number of ClassInfo structures that were filled in
-            uint32_t num_class_infos = return_value.GetScalar().ULong();
+            num_class_infos = return_value.GetScalar().ULong();
             if (log)
                 log->Printf("Discovered %u ObjC classes in shared cache\n",num_class_infos);
 #ifdef LLDB_CONFIGURATION_DEBUG
@@ -1830,7 +1834,7 @@ AppleObjCRuntimeV2::UpdateISAToDescripto
     // Deallocate the memory we allocated for the ClassInfo array
     process->DeallocateMemory(class_infos_addr);
     
-    return DescriptorMapUpdateResult(success, any_found);
+    return DescriptorMapUpdateResult(success, num_class_infos);
 }
 
 bool
@@ -1927,16 +1931,30 @@ AppleObjCRuntimeV2::UpdateISAToDescripto
         m_hash_signature.UpdateSignature (hash_table);
 
         // Grab the dynamically loaded objc classes from the hash table in memory
-        UpdateISAToDescriptorMapDynamic(hash_table);
+        DescriptorMapUpdateResult dynamic_update_result = UpdateISAToDescriptorMapDynamic(hash_table);
 
         // Now get the objc classes that are baked into the Objective C runtime
         // in the shared cache, but only once per process as this data never
         // changes
         if (!m_loaded_objc_opt)
         {
+            // it is legitimately possible for the shared cache to be empty - in that case, the dynamic hash table
+            // will contain all the class information we need; the situation we're trying to detect is one where
+            // we aren't seeing class information from the runtime - in order to detect that vs. just the shared cache
+            // being empty or sparsely populated, we set an arbitrary (very low) threshold for the number of classes
+            // that we want to see in a "good" scenario - anything below that is suspicious (Foundation alone has thousands
+            // of classes)
+            const uint32_t num_classes_to_warn_at = 500;
+            
             DescriptorMapUpdateResult shared_cache_update_result = UpdateISAToDescriptorMapSharedCache();
-            if (!shared_cache_update_result.any_found)
-                WarnIfNoClassesCached ();
+            
+            // warn if:
+            // - we could not run either expression
+            // - we found fewer than num_classes_to_warn_at classes total
+            if ((false == shared_cache_update_result.m_update_ran) || (false == dynamic_update_result.m_update_ran))
+                WarnIfNoClassesCached();
+            else if (dynamic_update_result.m_num_found + shared_cache_update_result.m_num_found < num_classes_to_warn_at)
+                WarnIfNoClassesCached();
             else
                 m_loaded_objc_opt = true;
         }

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=276220&r1=276219&r2=276220&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.h (original)
+++ lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.h Wed Jul 20 19:13:40 2016
@@ -296,26 +296,26 @@ private:
     
     struct DescriptorMapUpdateResult
     {
-        bool update_ran;
-        bool any_found;
+        bool m_update_ran;
+        uint32_t m_num_found;
         
         DescriptorMapUpdateResult (bool ran,
-                                   bool found)
+                                   uint32_t found)
         {
-            update_ran = ran;
-            any_found = found;
+            m_update_ran = ran;
+            m_num_found = found;
         }
         
         static DescriptorMapUpdateResult
         Fail ()
         {
-            return {false, false};
+            return {false, 0};
         }
         
         static DescriptorMapUpdateResult
-        Success ()
+        Success (uint32_t found)
         {
-            return {true, true};
+            return {true, found};
         }
     };
     
@@ -334,7 +334,7 @@ private:
     bool
     UpdateISAToDescriptorMapFromMemory (RemoteNXMapTable &hash_table);
     
-    bool
+    DescriptorMapUpdateResult
     UpdateISAToDescriptorMapDynamic(RemoteNXMapTable &hash_table);
     
     uint32_t




More information about the lldb-commits mailing list