Index: lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.h =================================================================== --- lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.h +++ lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.h @@ -322,6 +322,9 @@ bool GetCFBooleanValuesIfNeeded(); + llvm::Expected + ObjCGetClassNameRaw(AppleObjCRuntime::ObjCISA isa); + friend class ClassDescriptorV2; std::unique_ptr m_get_class_info_code; @@ -332,6 +335,8 @@ lldb::addr_t m_get_shared_cache_class_info_args; std::mutex m_get_shared_cache_class_info_args_mutex; + std::unique_ptr m_debug_class_get_name_raw; + std::unique_ptr m_decl_vendor_up; lldb::addr_t m_tagged_pointer_obfuscator; lldb::addr_t m_isa_hash_table_ptr; Index: lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp =================================================================== --- lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp +++ lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp @@ -73,6 +73,19 @@ char AppleObjCRuntimeV2::ID = 0; +static const char *g_debug_class_get_name_raw_name = + "__lldb_apple_objc_v2_debug_class_getNameRaw"; + +static const char *g_debug_class_get_name_raw_body = R"( +extern "C" +{ + const char *objc_debug_class_getNameRaw(Class cls); +} +const char* __lldb_apple_objc_v2_debug_class_getNameRaw(void* cls) { + return objc_debug_class_getNameRaw((Class)cls); +} +)"; + static const char *g_get_dynamic_class_info_name = "__lldb_apple_objc_v2_get_dynamic_class_info"; // Testing using the new C++11 raw string literals. If this breaks GCC then we @@ -1175,26 +1188,119 @@ return class_descriptor_sp; } -static std::pair ObjCGetClassNameRaw( - AppleObjCRuntime::ObjCISA isa, - Process *process) { - StreamString expr_string; - std::string input = std::to_string(isa); - expr_string.Printf("(const char *)objc_debug_class_getNameRaw(%s)", - input.c_str()); - - ValueObjectSP result_sp; - EvaluateExpressionOptions eval_options; - eval_options.SetLanguage(lldb::eLanguageTypeObjC); - eval_options.SetResultIsInternal(true); - eval_options.SetGenerateDebugInfo(true); - eval_options.SetTimeout(process->GetUtilityExpressionTimeout()); - auto eval_result = process->GetTarget().EvaluateExpression( - expr_string.GetData(), - process->GetThreadList().GetSelectedThread()->GetSelectedFrame().get(), - result_sp, eval_options); - ConstString type_name(result_sp->GetSummaryAsCString()); - return std::make_pair(eval_result == eExpressionCompleted, type_name); +llvm::Expected +AppleObjCRuntimeV2::ObjCGetClassNameRaw(AppleObjCRuntime::ObjCISA isa) { + Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_TYPES)); + + ThreadSP thread_sp = + m_process->GetThreadList().GetExpressionExecutionThread(); + if (!thread_sp) + return llvm::make_error( + "could not get the current thread", llvm::inconvertibleErrorCode()); + + ExecutionContext exe_ctx; + thread_sp->CalculateExecutionContext(exe_ctx); + + TypeSystemClang *ast = TypeSystemClang::GetScratch(m_process->GetTarget()); + if (!ast) + return llvm::make_error( + "could not get clang type system", llvm::inconvertibleErrorCode()); + + CompilerType clang_void_pointer_type = + ast->GetBasicType(eBasicTypeVoid).GetPointerType(); + CompilerType clang_char_pointer_type = + ast->GetBasicType(eBasicTypeChar).GetPointerType(); + + FunctionCaller *debug_class_get_name_raw_function = nullptr; + Status error; + ValueList arguments; + DiagnosticManager diagnostics; + + if (!m_debug_class_get_name_raw) { + m_debug_class_get_name_raw.reset( + GetTargetRef().GetUtilityFunctionForLanguage( + g_debug_class_get_name_raw_body, eLanguageTypeObjC, + g_debug_class_get_name_raw_name, error)); + + if (error.Fail()) + return error.ToError(); + + if (!m_debug_class_get_name_raw->Install(diagnostics, exe_ctx)) { + if (log) + diagnostics.Dump(log); + m_debug_class_get_name_raw.reset(); + return llvm::make_error( + "could not install utility function", llvm::inconvertibleErrorCode()); + } + + Value value; + value.SetValueType(Value::eValueTypeScalar); + value.SetCompilerType(clang_void_pointer_type); + arguments.PushValue(value); + + debug_class_get_name_raw_function = + m_debug_class_get_name_raw->MakeFunctionCaller( + clang_char_pointer_type, arguments, thread_sp, error); + if (error.Fail()) + return error.ToError(); + } else { + debug_class_get_name_raw_function = + m_debug_class_get_name_raw->GetFunctionCaller(); + if (!debug_class_get_name_raw_function) + return llvm::make_error( + "could not lookup function caller", llvm::inconvertibleErrorCode()); + arguments = debug_class_get_name_raw_function->GetArgumentValues(); + } + + // Fill in our function argument values + arguments.GetValueAtIndex(0)->GetScalar() = isa; + + // Write our function arguments into the process so we can run our function. + diagnostics.Clear(); + lldb::addr_t m_debug_class_get_name_raw_args = LLDB_INVALID_ADDRESS; + if (!debug_class_get_name_raw_function->WriteFunctionArguments( + exe_ctx, m_debug_class_get_name_raw_args, arguments, diagnostics)) { + if (log) + diagnostics.Dump(log); + return llvm::make_error( + "could write function argument(s)", llvm::inconvertibleErrorCode()); + } + + Value return_value; + return_value.SetValueType(Value::eValueTypeScalar); + return_value.SetCompilerType(clang_char_pointer_type); + return_value.GetScalar() = 0; + + EvaluateExpressionOptions options; + options.SetUnwindOnError(true); + options.SetTryAllThreads(false); + options.SetStopOthers(true); + options.SetIgnoreBreakpoints(true); + options.SetTimeout(m_process->GetUtilityExpressionTimeout()); + options.SetIsForUtilityExpr(true); + + diagnostics.Clear(); + + // Run the function + ExpressionResults results = + debug_class_get_name_raw_function->ExecuteFunction( + exe_ctx, &m_debug_class_get_name_raw_args, options, diagnostics, + return_value); + + if (results != eExpressionCompleted) { + if (log) + diagnostics.Dump(log); + return llvm::make_error("could execute function", + llvm::inconvertibleErrorCode()); + } + + lldb::addr_t result = return_value.GetScalar().ULongLong(); + std::string str; + m_process->ReadCStringFromMemory(result, str, error); + if (error.Fail()) + return error.ToError(); + + return ConstString(str); } ObjCLanguageRuntime::ClassDescriptorSP @@ -1246,10 +1352,14 @@ } ClassDescriptorSP descriptor_sp(new ClassDescriptorV2(*this, isa, nullptr)); - auto resolved = ObjCGetClassNameRaw(isa, process); - if (resolved.first == true) { - AddClass(isa, descriptor_sp, resolved.second.AsCString()); + llvm::Expected raw_class_name = ObjCGetClassNameRaw(isa); + if (raw_class_name) { + AddClass(isa, descriptor_sp, raw_class_name->AsCString()); objc_class_sp = descriptor_sp; + } else { + std::string error = llvm ::toString(raw_class_name.takeError()); + Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_TYPES)); + LLDB_LOG(log, "ObjCGetClassNameRaw failed: {0}", error); } return objc_class_sp; }