[Lldb-commits] [lldb] r363206 - Re-land r363103 ("When reading ObjC class table, use new SPI if it is avail")

Jason Molenda via lldb-commits lldb-commits at lists.llvm.org
Wed Jun 12 14:44:53 PDT 2019


Author: jmolenda
Date: Wed Jun 12 14:44:53 2019
New Revision: 363206

URL: http://llvm.org/viewvc/llvm-project?rev=363206&view=rev
Log:
Re-land r363103 ("When reading ObjC class table, use new SPI if it is avail")
with a call to snprintf() to find the size of the formatted string,
malloc memory, then snprintf again to format it into the buffer, instead
of calling asprintf.

Orig commit msg:

When reading ObjC class table, use new SPI if it is avail

In the latest OS betas, the objc runtime has a special interface
for the debugger, class_getNameRaw(), instead of the existing
class_getName(), which will return class names in their raw, unmangled
(in the case of swift) form.  When lldb can access the unmangled
names of classes, it won't need to fetch them out of the inferior
process after we run our "get the objc class table" expression.

If the new interface is absent (debugging a process on an older
target), lldb will fall back to class_getName and reading any class
names that it got back in demangled form, at a bit of a performance
cost on the first expression.

<rdar://problem/50688054> 


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

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=363206&r1=363205&r2=363206&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp (original)
+++ lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp Wed Jun 12 14:44:53 2019
@@ -157,6 +157,16 @@ __lldb_apple_objc_v2_get_dynamic_class_i
 
 )";
 
+// We'll substitute in class_getName or class_getNameRaw depending
+// on which is present.
+static const char *g_shared_cache_class_name_funcptr = R"(
+extern "C"
+{
+    const char *%s(void *objc_class);
+    const char *(*class_name_lookup_func)(void *) = %s;
+}
+)";
+
 static const char *g_get_shared_cache_class_info_name =
     "__lldb_apple_objc_v2_get_shared_cache_class_info";
 // Testing using the new C++11 raw string literals. If this breaks GCC then we
@@ -165,7 +175,6 @@ static const char *g_get_shared_cache_cl
 
 extern "C"
 {
-    const char *class_getName(void *objc_class);
     size_t strlen(const char *);
     char *strncpy (char * s1, const char * s2, size_t n);
     int printf(const char * format, ...);
@@ -286,7 +295,7 @@ __lldb_apple_objc_v2_get_shared_cache_cl
                 if (class_infos && idx < max_class_infos)
                 {
                     class_infos[idx].isa = (Class)((uint8_t *)clsopt + clsOffset);
-                    const char *name = class_getName (class_infos[idx].isa);
+                    const char *name = class_name_lookup_func (class_infos[idx].isa);
                     DEBUG_PRINTF ("[%u] isa = %8p %s\n", idx, class_infos[idx].isa, name);
                     // Hash the class name so we don't have to read it
                     const char *s = name;
@@ -329,7 +338,7 @@ __lldb_apple_objc_v2_get_shared_cache_cl
                 if (class_infos && idx < max_class_infos)
                 {
                     class_infos[idx].isa = (Class)((uint8_t *)clsopt + clsOffset);
-                    const char *name = class_getName (class_infos[idx].isa);
+                    const char *name = class_name_lookup_func (class_infos[idx].isa);
                     DEBUG_PRINTF ("[%u] isa = %8p %s\n", idx, class_infos[idx].isa, name);
                     // Hash the class name so we don't have to read it
                     const char *s = name;
@@ -1589,9 +1598,52 @@ AppleObjCRuntimeV2::UpdateISAToDescripto
 
   if (!m_get_shared_cache_class_info_code) {
     Status error;
+
+    // If the inferior objc.dylib has the class_getNameRaw function,
+    // use that in our jitted expression.  Else fall back to the old
+    // class_getName.
+    static ConstString g_class_getName_symbol_name("class_getName");
+    static ConstString g_class_getNameRaw_symbol_name("class_getNameRaw");
+    ConstString class_name_getter_function_name = g_class_getName_symbol_name;
+
+    ObjCLanguageRuntime *objc_runtime = ObjCLanguageRuntime::Get(*process);
+    if (objc_runtime) {
+      const ModuleList &images = process->GetTarget().GetImages();
+      std::lock_guard<std::recursive_mutex> guard(images.GetMutex());
+      for (size_t i = 0; i < images.GetSize(); ++i) {
+        lldb::ModuleSP mod_sp = images.GetModuleAtIndexUnlocked(i);
+        if (objc_runtime->IsModuleObjCLibrary(mod_sp)) {
+          const Symbol *symbol =
+              mod_sp->FindFirstSymbolWithNameAndType(g_class_getNameRaw_symbol_name, 
+                                                lldb::eSymbolTypeCode);
+          if (symbol && 
+              (symbol->ValueIsAddress() || symbol->GetAddressRef().IsValid())) {
+            class_name_getter_function_name = g_class_getNameRaw_symbol_name;
+          }
+        }
+      }
+    }
+
+    // Substitute in the correct class_getName / class_getNameRaw function name,
+    // concatenate the two parts of our expression text.  The format string
+    // has two %s's, so provide the name twice.
+    int prefix_string_size = snprintf (nullptr, 0, 
+                               g_shared_cache_class_name_funcptr,
+                               class_name_getter_function_name.AsCString(),
+                               class_name_getter_function_name.AsCString());
+
+    char *class_name_func_ptr_expr = (char*) malloc (prefix_string_size + 1);
+    snprintf (class_name_func_ptr_expr, prefix_string_size + 1,
+              g_shared_cache_class_name_funcptr,
+              class_name_getter_function_name.AsCString(),
+              class_name_getter_function_name.AsCString());
+    std::string shared_class_expression = class_name_func_ptr_expr;
+    shared_class_expression += g_get_shared_cache_class_info_body;
+    free (class_name_func_ptr_expr);
+
     m_get_shared_cache_class_info_code.reset(
         GetTargetRef().GetUtilityFunctionForLanguage(
-            g_get_shared_cache_class_info_body, eLanguageTypeObjC,
+            shared_class_expression.c_str(), eLanguageTypeObjC,
             g_get_shared_cache_class_info_name, error));
     if (error.Fail()) {
       if (log)




More information about the lldb-commits mailing list