diff options
Diffstat (limited to 'source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp')
-rw-r--r-- | source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp | 576 |
1 files changed, 436 insertions, 140 deletions
diff --git a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp index 584449430829..e9a799bb3651 100644 --- a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp +++ b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp @@ -36,12 +36,14 @@ #include "lldb/Core/StreamString.h" #include "lldb/Core/Timer.h" #include "lldb/Core/ValueObjectVariable.h" +#include "lldb/Expression/DiagnosticManager.h" #include "lldb/Expression/FunctionCaller.h" #include "lldb/Expression/UtilityFunction.h" #include "lldb/Host/StringConvert.h" #include "lldb/Interpreter/CommandObject.h" #include "lldb/Interpreter/CommandObjectMultiword.h" #include "lldb/Interpreter/CommandReturnObject.h" +#include "lldb/Interpreter/OptionValueBoolean.h" #include "lldb/Symbol/ClangASTContext.h" #include "lldb/Symbol/ObjectFile.h" #include "lldb/Symbol/Symbol.h" @@ -60,9 +62,6 @@ #include "AppleObjCDeclVendor.h" #include "AppleObjCTrampolineHandler.h" -#if defined(__APPLE__) -#include "Plugins/Platform/MacOSX/PlatformiOSSimulator.h" -#endif using namespace lldb; using namespace lldb_private; @@ -81,12 +80,7 @@ extern "C" char *strncpy (char * s1, const char * s2, size_t n); int printf(const char * format, ...); } -//#define ENABLE_DEBUG_PRINTF // COMMENT THIS LINE OUT PRIOR TO CHECKIN -#ifdef ENABLE_DEBUG_PRINTF -#define DEBUG_PRINTF(fmt, ...) printf(fmt, ## __VA_ARGS__) -#else -#define DEBUG_PRINTF(fmt, ...) -#endif +#define DEBUG_PRINTF(fmt, ...) if (should_log) printf(fmt, ## __VA_ARGS__) typedef struct _NXMapTable { void *prototype; @@ -112,7 +106,8 @@ struct ClassInfo uint32_t __lldb_apple_objc_v2_get_dynamic_class_info (void *gdb_objc_realized_classes_ptr, void *class_infos_ptr, - uint32_t class_infos_byte_size) + uint32_t class_infos_byte_size, + uint32_t should_log) { DEBUG_PRINTF ("gdb_objc_realized_classes_ptr = %p\n", gdb_objc_realized_classes_ptr); DEBUG_PRINTF ("class_infos_ptr = %p\n", class_infos_ptr); @@ -170,12 +165,7 @@ extern "C" int printf(const char * format, ...); } -// #define ENABLE_DEBUG_PRINTF // COMMENT THIS LINE OUT PRIOR TO CHECKIN -#ifdef ENABLE_DEBUG_PRINTF -#define DEBUG_PRINTF(fmt, ...) printf(fmt, ## __VA_ARGS__) -#else -#define DEBUG_PRINTF(fmt, ...) -#endif +#define DEBUG_PRINTF(fmt, ...) if (should_log) printf(fmt, ## __VA_ARGS__) struct objc_classheader_t { @@ -224,12 +214,13 @@ struct ClassInfo uint32_t __lldb_apple_objc_v2_get_shared_cache_class_info (void *objc_opt_ro_ptr, void *class_infos_ptr, - uint32_t class_infos_byte_size) + uint32_t class_infos_byte_size, + uint32_t should_log) { uint32_t idx = 0; DEBUG_PRINTF ("objc_opt_ro_ptr = %p\n", objc_opt_ro_ptr); DEBUG_PRINTF ("class_infos_ptr = %p\n", class_infos_ptr); - DEBUG_PRINTF ("class_infos_byte_size = %u (%" PRIu64 " class infos)\n", class_infos_byte_size, (size_t)(class_infos_byte_size/sizeof(ClassInfo))); + DEBUG_PRINTF ("class_infos_byte_size = %u (%llu class infos)\n", class_infos_byte_size, (uint64_t)(class_infos_byte_size/sizeof(ClassInfo))); if (objc_opt_ro_ptr) { const objc_opt_t *objc_opt = (objc_opt_t *)objc_opt_ro_ptr; @@ -250,7 +241,7 @@ __lldb_apple_objc_v2_get_shared_cache_class_info (void *objc_opt_ro_ptr, DEBUG_PRINTF ("objc_opt->headeropt_offset = %d\n", objc_opt->headeropt_offset); DEBUG_PRINTF ("objc_opt->clsopt_offset = %d\n", objc_opt->clsopt_offset); } - if (objc_opt->version == 12 || objc_opt->version == 13 || objc_opt->version == 14) + if (objc_opt->version == 12 || objc_opt->version == 13 || objc_opt->version == 14 || objc_opt->version == 15) { const objc_clsopt_t* clsopt = NULL; if (is_v14_format) @@ -258,6 +249,7 @@ __lldb_apple_objc_v2_get_shared_cache_class_info (void *objc_opt_ro_ptr, else clsopt = (const objc_clsopt_t*)((uint8_t *)objc_opt + objc_opt->clsopt_offset); const size_t max_class_infos = class_infos_byte_size/sizeof(ClassInfo); + DEBUG_PRINTF("max_class_infos = %llu\n", (uint64_t)max_class_infos); ClassInfo *class_infos = (ClassInfo *)class_infos_ptr; int32_t invalidEntryOffset = 0; // this is safe to do because the version field order is invariant @@ -269,13 +261,21 @@ __lldb_apple_objc_v2_get_shared_cache_class_info (void *objc_opt_ro_ptr, DEBUG_PRINTF ("clsopt->capacity = %u\n", clsopt->capacity); DEBUG_PRINTF ("clsopt->mask = 0x%8.8x\n", clsopt->mask); DEBUG_PRINTF ("classOffsets = %p\n", classOffsets); + DEBUG_PRINTF("invalidEntryOffset = %d\n", invalidEntryOffset); for (uint32_t i=0; i<clsopt->capacity; ++i) { const int32_t clsOffset = classOffsets[i].clsOffset; + DEBUG_PRINTF("clsOffset[%u] = %u\n", i, clsOffset); if (clsOffset & 1) + { + DEBUG_PRINTF("clsOffset & 1\n"); continue; // duplicate + } else if (clsOffset == invalidEntryOffset) + { + DEBUG_PRINTF("clsOffset == invalidEntryOffset\n"); continue; // invalid offset + } if (class_infos && idx < max_class_infos) { @@ -289,6 +289,10 @@ __lldb_apple_objc_v2_get_shared_cache_class_info (void *objc_opt_ro_ptr, h = ((h << 5) + h) + c; class_infos[idx].hash = h; } + else + { + DEBUG_PRINTF("not(class_infos && idx < max_class_infos)\n"); + } ++idx; } @@ -375,27 +379,27 @@ ExtractRuntimeGlobalSymbol (Process* process, } } -AppleObjCRuntimeV2::AppleObjCRuntimeV2 (Process *process, - const ModuleSP &objc_module_sp) : - AppleObjCRuntime (process), - m_get_class_info_code(), - m_get_class_info_args (LLDB_INVALID_ADDRESS), - m_get_class_info_args_mutex (Mutex::eMutexTypeNormal), - m_get_shared_cache_class_info_code(), - m_get_shared_cache_class_info_args (LLDB_INVALID_ADDRESS), - m_get_shared_cache_class_info_args_mutex (Mutex::eMutexTypeNormal), - m_decl_vendor_ap (), - m_isa_hash_table_ptr (LLDB_INVALID_ADDRESS), - m_hash_signature (), - m_has_object_getClass (false), - m_loaded_objc_opt (false), - m_non_pointer_isa_cache_ap(NonPointerISACache::CreateInstance(*this,objc_module_sp)), - m_tagged_pointer_vendor_ap(TaggedPointerVendorV2::CreateInstance(*this,objc_module_sp)), - m_encoding_to_type_sp(), - m_noclasses_warning_emitted(false) +AppleObjCRuntimeV2::AppleObjCRuntimeV2(Process *process, const ModuleSP &objc_module_sp) + : AppleObjCRuntime(process), + m_get_class_info_code(), + m_get_class_info_args(LLDB_INVALID_ADDRESS), + m_get_class_info_args_mutex(), + m_get_shared_cache_class_info_code(), + m_get_shared_cache_class_info_args(LLDB_INVALID_ADDRESS), + m_get_shared_cache_class_info_args_mutex(), + m_decl_vendor_ap(), + m_isa_hash_table_ptr(LLDB_INVALID_ADDRESS), + m_hash_signature(), + m_has_object_getClass(false), + m_loaded_objc_opt(false), + m_non_pointer_isa_cache_ap(NonPointerISACache::CreateInstance(*this, objc_module_sp)), + m_tagged_pointer_vendor_ap(TaggedPointerVendorV2::CreateInstance(*this, objc_module_sp)), + m_encoding_to_type_sp(), + m_noclasses_warning_emitted(false) { static const ConstString g_gdb_object_getClass("gdb_object_getClass"); - m_has_object_getClass = (objc_module_sp->FindFirstSymbolWithNameAndType(g_gdb_object_getClass, eSymbolTypeCode) != NULL); + m_has_object_getClass = + (objc_module_sp->FindFirstSymbolWithNameAndType(g_gdb_object_getClass, eSymbolTypeCode) != NULL); } bool @@ -485,6 +489,52 @@ AppleObjCRuntimeV2::CreateInstance (Process *process, LanguageType language) class CommandObjectObjC_ClassTable_Dump : public CommandObjectParsed { public: + class CommandOptions : public Options + { + public: + CommandOptions (CommandInterpreter &interpreter) : + Options(interpreter), + m_verbose(false,false) + {} + + ~CommandOptions() override = default; + + Error + SetOptionValue(uint32_t option_idx, const char *option_arg) override + { + Error error; + const int short_option = m_getopt_table[option_idx].val; + switch (short_option) + { + case 'v': + m_verbose.SetCurrentValue(true); + m_verbose.SetOptionWasSet(); + break; + + default: + error.SetErrorStringWithFormat("unrecognized short option '%c'", short_option); + break; + } + + return error; + } + + void + OptionParsingStarting() override + { + m_verbose.Clear(); + } + + const OptionDefinition* + GetDefinitions() override + { + return g_option_table; + } + + OptionValueBoolean m_verbose; + static OptionDefinition g_option_table[]; + }; + CommandObjectObjC_ClassTable_Dump (CommandInterpreter &interpreter) : CommandObjectParsed (interpreter, "dump", @@ -492,39 +542,116 @@ public: "language objc class-table dump", eCommandRequiresProcess | eCommandProcessMustBeLaunched | - eCommandProcessMustBePaused ) + eCommandProcessMustBePaused ), + m_options(interpreter) { + CommandArgumentEntry arg; + CommandArgumentData index_arg; + + // Define the first (and only) variant of this arg. + index_arg.arg_type = eArgTypeRegularExpression; + index_arg.arg_repetition = eArgRepeatOptional; + + // There is only one variant this argument could be; put it into the argument entry. + arg.push_back (index_arg); + + // Push the data for the first argument into the m_arguments vector. + m_arguments.push_back (arg); } ~CommandObjectObjC_ClassTable_Dump() override = default; + Options * + GetOptions() override + { + return &m_options; + } + protected: bool DoExecute(Args& command, CommandReturnObject &result) override { + std::unique_ptr<RegularExpression> regex_up; + switch(command.GetArgumentCount()) + { + case 0: + break; + case 1: + { + regex_up.reset(new RegularExpression()); + if (!regex_up->Compile(command.GetArgumentAtIndex(0))) + { + result.AppendError("invalid argument - please provide a valid regular expression"); + result.SetStatus(lldb::eReturnStatusFailed); + return false; + } + break; + } + default: + { + result.AppendError("please provide 0 or 1 arguments"); + result.SetStatus(lldb::eReturnStatusFailed); + return false; + } + } + Process *process = m_exe_ctx.GetProcessPtr(); ObjCLanguageRuntime *objc_runtime = process->GetObjCLanguageRuntime(); if (objc_runtime) { auto iterators_pair = objc_runtime->GetDescriptorIteratorPair(); auto iterator = iterators_pair.first; + auto &std_out = result.GetOutputStream(); for(; iterator != iterators_pair.second; iterator++) { - result.GetOutputStream().Printf("isa = 0x%" PRIx64, iterator->first); if (iterator->second) { - result.GetOutputStream().Printf(" name = %s", iterator->second->GetClassName().AsCString("<unknown>")); - result.GetOutputStream().Printf(" instance size = %" PRIu64, iterator->second->GetInstanceSize()); - result.GetOutputStream().Printf(" num ivars = %" PRIuPTR, (uintptr_t)iterator->second->GetNumIVars()); + const char* class_name = iterator->second->GetClassName().AsCString("<unknown>"); + if (regex_up && class_name && !regex_up->Execute(class_name)) + continue; + std_out.Printf("isa = 0x%" PRIx64, iterator->first); + std_out.Printf(" name = %s", class_name); + std_out.Printf(" instance size = %" PRIu64, iterator->second->GetInstanceSize()); + std_out.Printf(" num ivars = %" PRIuPTR, (uintptr_t)iterator->second->GetNumIVars()); if (auto superclass = iterator->second->GetSuperclass()) { - result.GetOutputStream().Printf(" superclass = %s", superclass->GetClassName().AsCString("<unknown>")); + std_out.Printf(" superclass = %s", superclass->GetClassName().AsCString("<unknown>")); + } + std_out.Printf("\n"); + if (m_options.m_verbose) + { + for(size_t i = 0; + i < iterator->second->GetNumIVars(); + i++) + { + auto ivar = iterator->second->GetIVarAtIndex(i); + std_out.Printf(" ivar name = %s type = %s size = %" PRIu64 " offset = %" PRId32 "\n", + ivar.m_name.AsCString("<unknown>"), + ivar.m_type.GetDisplayTypeName().AsCString("<unknown>"), + ivar.m_size, + ivar.m_offset); + } + iterator->second->Describe(nullptr, + [objc_runtime, &std_out] (const char* name, const char* type) -> bool { + std_out.Printf(" instance method name = %s type = %s\n", + name, + type); + return false; + }, + [objc_runtime, &std_out] (const char* name, const char* type) -> bool { + std_out.Printf(" class method name = %s type = %s\n", + name, + type); + return false; + }, + nullptr); } - result.GetOutputStream().Printf("\n"); } else { - result.GetOutputStream().Printf(" has no associated class.\n"); + if (regex_up && !regex_up->Execute("")) + continue; + std_out.Printf("isa = 0x%" PRIx64 " has no associated class.\n", iterator->first); } } result.SetStatus(lldb::eReturnStatusSuccessFinishResult); @@ -537,6 +664,15 @@ protected: return false; } } + + CommandOptions m_options; +}; + +OptionDefinition +CommandObjectObjC_ClassTable_Dump::CommandOptions::g_option_table[] = +{ + { LLDB_OPT_SET_ALL, false, "verbose" , 'v', OptionParser::eNoArgument , nullptr, nullptr, 0, eArgTypeNone, "Print ivar and method information in detail"}, + { 0 , false, nullptr , 0, 0 , nullptr, nullptr, 0, eArgTypeNone, nullptr } }; class CommandObjectMultiwordObjC_TaggedPointer_Info : public CommandObjectParsed @@ -639,11 +775,9 @@ protected: class CommandObjectMultiwordObjC_ClassTable : public CommandObjectMultiword { public: - CommandObjectMultiwordObjC_ClassTable (CommandInterpreter &interpreter) : - CommandObjectMultiword (interpreter, - "class-table", - "A set of commands for operating on the Objective-C class table.", - "class-table <subcommand> [<subcommand-options>]") + CommandObjectMultiwordObjC_ClassTable(CommandInterpreter &interpreter) + : CommandObjectMultiword(interpreter, "class-table", "Commands for operating on the Objective-C class table.", + "class-table <subcommand> [<subcommand-options>]") { LoadSubCommand ("dump", CommandObjectSP (new CommandObjectObjC_ClassTable_Dump (interpreter))); } @@ -654,12 +788,10 @@ public: class CommandObjectMultiwordObjC_TaggedPointer : public CommandObjectMultiword { public: - - CommandObjectMultiwordObjC_TaggedPointer (CommandInterpreter &interpreter) : - CommandObjectMultiword (interpreter, - "tagged-pointer", - "A set of commands for operating on Objective-C tagged pointers.", - "class-table <subcommand> [<subcommand-options>]") + CommandObjectMultiwordObjC_TaggedPointer(CommandInterpreter &interpreter) + : CommandObjectMultiword(interpreter, "tagged-pointer", + "Commands for operating on Objective-C tagged pointers.", + "class-table <subcommand> [<subcommand-options>]") { LoadSubCommand ("info", CommandObjectSP (new CommandObjectMultiwordObjC_TaggedPointer_Info (interpreter))); } @@ -670,11 +802,9 @@ public: class CommandObjectMultiwordObjC : public CommandObjectMultiword { public: - CommandObjectMultiwordObjC (CommandInterpreter &interpreter) : - CommandObjectMultiword (interpreter, - "objc", - "A set of commands for operating on the Objective-C Language Runtime.", - "objc <subcommand> [<subcommand-options>]") + CommandObjectMultiwordObjC(CommandInterpreter &interpreter) + : CommandObjectMultiword(interpreter, "objc", "Commands for operating on the Objective-C language runtime.", + "objc <subcommand> [<subcommand-options>]") { LoadSubCommand ("class-table", CommandObjectSP (new CommandObjectMultiwordObjC_ClassTable (interpreter))); LoadSubCommand ("tagged-pointer", CommandObjectSP (new CommandObjectMultiwordObjC_TaggedPointer (interpreter))); @@ -733,6 +863,7 @@ AppleObjCRuntimeV2::CreateExceptionResolver (Breakpoint *bkpt, bool catch_bp, bo eFunctionNameTypeBase, eLanguageTypeUnknown, Breakpoint::Exact, + 0, eLazyBoolNo)); // FIXME: We don't do catch breakpoints for ObjC yet. // Should there be some way for the runtime to specify what it can do in this regard? @@ -1231,7 +1362,7 @@ AppleObjCRuntimeV2::UpdateISAToDescriptorMapDynamic(RemoteNXMapTable &hash_table ExecutionContext exe_ctx; - ThreadSP thread_sp = process->GetThreadList().GetSelectedThread(); + ThreadSP thread_sp = process->GetThreadList().GetExpressionExecutionThread(); if (!thread_sp) return false; @@ -1241,13 +1372,13 @@ AppleObjCRuntimeV2::UpdateISAToDescriptorMapDynamic(RemoteNXMapTable &hash_table if (!ast) return false; - + Address function_address; - - StreamString errors; - + + DiagnosticManager diagnostics; + const uint32_t addr_size = process->GetAddressByteSize(); - + Error err; // Read the total number of classes from the hash table @@ -1281,12 +1412,15 @@ AppleObjCRuntimeV2::UpdateISAToDescriptorMapDynamic(RemoteNXMapTable &hash_table } else { - errors.Clear(); - - if (!m_get_class_info_code->Install(errors, exe_ctx)) + diagnostics.Clear(); + + if (!m_get_class_info_code->Install(diagnostics, exe_ctx)) { if (log) - log->Printf ("Failed to install implementation lookup: %s.", errors.GetData()); + { + log->Printf("Failed to install implementation lookup"); + diagnostics.Dump(log); + } m_get_class_info_code.reset(); } } @@ -1303,9 +1437,11 @@ AppleObjCRuntimeV2::UpdateISAToDescriptorMapDynamic(RemoteNXMapTable &hash_table value.SetValueType (Value::eValueTypeScalar); value.SetCompilerType (clang_uint32_t_type); arguments.PushValue (value); + arguments.PushValue (value); get_class_info_function = m_get_class_info_code->MakeFunctionCaller(clang_uint32_t_type, arguments, + thread_sp, error); if (error.Fail()) @@ -1321,14 +1457,18 @@ AppleObjCRuntimeV2::UpdateISAToDescriptorMapDynamic(RemoteNXMapTable &hash_table if (!get_class_info_function) { if (log) - log->Printf ("Failed to get implementation lookup function caller: %s.", errors.GetData()); + { + log->Printf("Failed to get implementation lookup function caller."); + diagnostics.Dump(log); + } + return false; } arguments = get_class_info_function->GetArgumentValues(); } - errors.Clear(); - + diagnostics.Clear(); + const uint32_t class_info_byte_size = addr_size + 4; const uint32_t class_infos_byte_size = num_classes * class_info_byte_size; lldb::addr_t class_infos_addr = process->AllocateMemory(class_infos_byte_size, @@ -1337,23 +1477,22 @@ AppleObjCRuntimeV2::UpdateISAToDescriptorMapDynamic(RemoteNXMapTable &hash_table if (class_infos_addr == LLDB_INVALID_ADDRESS) return false; - - Mutex::Locker locker(m_get_class_info_args_mutex); - + + std::lock_guard<std::mutex> guard(m_get_class_info_args_mutex); + // Fill in our function argument values arguments.GetValueAtIndex(0)->GetScalar() = hash_table.GetTableLoadAddress(); arguments.GetValueAtIndex(1)->GetScalar() = class_infos_addr; arguments.GetValueAtIndex(2)->GetScalar() = class_infos_byte_size; + arguments.GetValueAtIndex(3)->GetScalar() = (GetLogIfAllCategoriesSet(LIBLLDB_LOG_TYPES) == nullptr ? 0 : 1); + bool success = false; - - errors.Clear(); - + + diagnostics.Clear(); + // Write our function arguments into the process so we can run our function - if (get_class_info_function->WriteFunctionArguments (exe_ctx, - m_get_class_info_args, - arguments, - errors)) + if (get_class_info_function->WriteFunctionArguments(exe_ctx, m_get_class_info_args, arguments, diagnostics)) { EvaluateExpressionOptions options; options.SetUnwindOnError(true); @@ -1365,18 +1504,15 @@ AppleObjCRuntimeV2::UpdateISAToDescriptorMapDynamic(RemoteNXMapTable &hash_table Value return_value; return_value.SetValueType (Value::eValueTypeScalar); //return_value.SetContext (Value::eContextTypeClangType, clang_uint32_t_type); - return_value.SetCompilerType (clang_uint32_t_type); + return_value.SetCompilerType(clang_uint32_t_type); return_value.GetScalar() = 0; - - errors.Clear(); - + + diagnostics.Clear(); + // Run the function - ExpressionResults results = get_class_info_function->ExecuteFunction (exe_ctx, - &m_get_class_info_args, - options, - errors, - return_value); - + ExpressionResults results = get_class_info_function->ExecuteFunction(exe_ctx, &m_get_class_info_args, options, + diagnostics, return_value); + if (results == eExpressionCompleted) { // The result is the number of ClassInfo structures that were filled in @@ -1401,15 +1537,21 @@ AppleObjCRuntimeV2::UpdateISAToDescriptorMapDynamic(RemoteNXMapTable &hash_table else { if (log) - log->Printf("Error evaluating our find class name function: %s.\n", errors.GetData()); + { + log->Printf("Error evaluating our find class name function."); + diagnostics.Dump(log); + } } } else { if (log) - log->Printf ("Error writing function arguments: \"%s\".", errors.GetData()); + { + log->Printf("Error writing function arguments."); + diagnostics.Dump(log); + } } - + // Deallocate the memory we allocated for the ClassInfo array process->DeallocateMemory(class_infos_addr); @@ -1475,7 +1617,7 @@ AppleObjCRuntimeV2::UpdateISAToDescriptorMapSharedCache() ExecutionContext exe_ctx; - ThreadSP thread_sp = process->GetThreadList().GetSelectedThread(); + ThreadSP thread_sp = process->GetThreadList().GetExpressionExecutionThread(); if (!thread_sp) return DescriptorMapUpdateResult::Fail(); @@ -1485,13 +1627,13 @@ AppleObjCRuntimeV2::UpdateISAToDescriptorMapSharedCache() if (!ast) return DescriptorMapUpdateResult::Fail(); - + Address function_address; - - StreamString errors; - + + DiagnosticManager diagnostics; + const uint32_t addr_size = process->GetAddressByteSize(); - + Error err; const lldb::addr_t objc_opt_ptr = GetSharedCacheReadOnlyAddress(); @@ -1530,16 +1672,19 @@ AppleObjCRuntimeV2::UpdateISAToDescriptorMapSharedCache() } else { - errors.Clear(); - - if (!m_get_shared_cache_class_info_code->Install(errors, exe_ctx)) + diagnostics.Clear(); + + if (!m_get_shared_cache_class_info_code->Install(diagnostics, exe_ctx)) { if (log) - log->Printf ("Failed to install implementation lookup: %s.", errors.GetData()); + { + log->Printf("Failed to install implementation lookup."); + diagnostics.Dump(log); + } m_get_shared_cache_class_info_code.reset(); } } - + if (!m_get_shared_cache_class_info_code.get()) return DescriptorMapUpdateResult::Fail(); @@ -1555,9 +1700,11 @@ AppleObjCRuntimeV2::UpdateISAToDescriptorMapSharedCache() //value.SetContext (Value::eContextTypeClangType, clang_uint32_t_type); value.SetCompilerType (clang_uint32_t_type); arguments.PushValue (value); + arguments.PushValue (value); get_shared_cache_class_info_function = m_get_shared_cache_class_info_code->MakeFunctionCaller(clang_uint32_t_type, arguments, + thread_sp, error); if (get_shared_cache_class_info_function == nullptr) @@ -1571,9 +1718,9 @@ AppleObjCRuntimeV2::UpdateISAToDescriptorMapSharedCache() return DescriptorMapUpdateResult::Fail(); arguments = get_shared_cache_class_info_function->GetArgumentValues(); } - - errors.Clear(); - + + diagnostics.Clear(); + const uint32_t class_info_byte_size = addr_size + 4; const uint32_t class_infos_byte_size = num_classes * class_info_byte_size; lldb::addr_t class_infos_addr = process->AllocateMemory (class_infos_byte_size, @@ -1582,24 +1729,24 @@ AppleObjCRuntimeV2::UpdateISAToDescriptorMapSharedCache() if (class_infos_addr == LLDB_INVALID_ADDRESS) return DescriptorMapUpdateResult::Fail(); - - Mutex::Locker locker(m_get_shared_cache_class_info_args_mutex); - + + std::lock_guard<std::mutex> guard(m_get_shared_cache_class_info_args_mutex); + // Fill in our function argument values arguments.GetValueAtIndex(0)->GetScalar() = objc_opt_ptr; arguments.GetValueAtIndex(1)->GetScalar() = class_infos_addr; arguments.GetValueAtIndex(2)->GetScalar() = class_infos_byte_size; + arguments.GetValueAtIndex(3)->GetScalar() = (GetLogIfAllCategoriesSet(LIBLLDB_LOG_TYPES) == nullptr ? 0 : 1); + bool success = false; bool any_found = false; - - errors.Clear(); - + + diagnostics.Clear(); + // Write our function arguments into the process so we can run our function - if (get_shared_cache_class_info_function->WriteFunctionArguments (exe_ctx, - m_get_shared_cache_class_info_args, - arguments, - errors)) + if (get_shared_cache_class_info_function->WriteFunctionArguments(exe_ctx, m_get_shared_cache_class_info_args, + arguments, diagnostics)) { EvaluateExpressionOptions options; options.SetUnwindOnError(true); @@ -1611,18 +1758,15 @@ AppleObjCRuntimeV2::UpdateISAToDescriptorMapSharedCache() Value return_value; return_value.SetValueType (Value::eValueTypeScalar); //return_value.SetContext (Value::eContextTypeClangType, clang_uint32_t_type); - return_value.SetCompilerType (clang_uint32_t_type); + return_value.SetCompilerType(clang_uint32_t_type); return_value.GetScalar() = 0; - - errors.Clear(); - + + diagnostics.Clear(); + // Run the function - ExpressionResults results = get_shared_cache_class_info_function->ExecuteFunction (exe_ctx, - &m_get_shared_cache_class_info_args, - options, - errors, - return_value); - + ExpressionResults results = get_shared_cache_class_info_function->ExecuteFunction( + exe_ctx, &m_get_shared_cache_class_info_args, options, diagnostics, return_value); + if (results == eExpressionCompleted) { // The result is the number of ClassInfo structures that were filled in @@ -1668,15 +1812,21 @@ AppleObjCRuntimeV2::UpdateISAToDescriptorMapSharedCache() else { if (log) - log->Printf("Error evaluating our find class name function: %s.\n", errors.GetData()); + { + log->Printf("Error evaluating our find class name function."); + diagnostics.Dump(log); + } } } else { if (log) - log->Printf ("Error writing function arguments: \"%s\".", errors.GetData()); + { + log->Printf("Error writing function arguments."); + diagnostics.Dump(log); + } } - + // Deallocate the memory we allocated for the ClassInfo array process->DeallocateMemory(class_infos_addr); @@ -1803,17 +1953,14 @@ AppleObjCRuntimeV2::WarnIfNoClassesCached () if (m_noclasses_warning_emitted) return; -#if defined(__APPLE__) if (m_process && m_process->GetTarget().GetPlatform() && - m_process->GetTarget().GetPlatform()->GetPluginName() == PlatformiOSSimulator::GetPluginNameStatic()) + m_process->GetTarget().GetPlatform()->GetPluginName().GetStringRef().endswith("-simulator")) { - // the iOS simulator does not have the objc_opt_ro class table - // so don't actually complain to the user + // Simulators do not have the objc_opt_ro class table so don't actually complain to the user m_noclasses_warning_emitted = true; return; } -#endif Debugger &debugger(GetProcess()->GetTarget().GetDebugger()); @@ -2025,6 +2172,74 @@ AppleObjCRuntimeV2::TaggedPointerVendorV2::CreateInstance (AppleObjCRuntimeV2& r if (error.Fail()) return new TaggedPointerVendorLegacy(runtime); + // try to detect the "extended tagged pointer" variables - if any are missing, use the non-extended vendor + do + { + auto objc_debug_taggedpointer_ext_mask = ExtractRuntimeGlobalSymbol(process, + ConstString("objc_debug_taggedpointer_ext_mask"), + objc_module_sp, + error); + if (error.Fail()) + break; + + auto objc_debug_taggedpointer_ext_slot_shift = ExtractRuntimeGlobalSymbol(process, + ConstString("objc_debug_taggedpointer_ext_slot_shift"), + objc_module_sp, + error, + true, + 4); + if (error.Fail()) + break; + + auto objc_debug_taggedpointer_ext_slot_mask = ExtractRuntimeGlobalSymbol(process, + ConstString("objc_debug_taggedpointer_ext_slot_mask"), + objc_module_sp, + error, + true, + 4); + if (error.Fail()) + break; + + auto objc_debug_taggedpointer_ext_classes = ExtractRuntimeGlobalSymbol(process, + ConstString("objc_debug_taggedpointer_ext_classes"), + objc_module_sp, + error, + false); + if (error.Fail()) + break; + + auto objc_debug_taggedpointer_ext_payload_lshift = ExtractRuntimeGlobalSymbol(process, + ConstString("objc_debug_taggedpointer_ext_payload_lshift"), + objc_module_sp, + error, + true, + 4); + if (error.Fail()) + break; + + auto objc_debug_taggedpointer_ext_payload_rshift = ExtractRuntimeGlobalSymbol(process, + ConstString("objc_debug_taggedpointer_ext_payload_rshift"), + objc_module_sp, + error, + true, + 4); + if (error.Fail()) + break; + + return new TaggedPointerVendorExtended(runtime, + objc_debug_taggedpointer_mask, + objc_debug_taggedpointer_ext_mask, + objc_debug_taggedpointer_slot_shift, + objc_debug_taggedpointer_ext_slot_shift, + objc_debug_taggedpointer_slot_mask, + objc_debug_taggedpointer_ext_slot_mask, + objc_debug_taggedpointer_payload_lshift, + objc_debug_taggedpointer_payload_rshift, + objc_debug_taggedpointer_ext_payload_lshift, + objc_debug_taggedpointer_ext_payload_rshift, + objc_debug_taggedpointer_classes, + objc_debug_taggedpointer_ext_classes); + } while(false); // we might want to have some rules to outlaw these values (e.g if the table's address is zero) @@ -2164,6 +2379,87 @@ AppleObjCRuntimeV2::TaggedPointerVendorRuntimeAssisted::GetClassDescriptor (lldb return ClassDescriptorSP(new ClassDescriptorV2Tagged(actual_class_descriptor_sp,data_payload)); } +AppleObjCRuntimeV2::TaggedPointerVendorExtended::TaggedPointerVendorExtended (AppleObjCRuntimeV2& runtime, + uint64_t objc_debug_taggedpointer_mask, + uint64_t objc_debug_taggedpointer_ext_mask, + uint32_t objc_debug_taggedpointer_slot_shift, + uint32_t objc_debug_taggedpointer_ext_slot_shift, + uint32_t objc_debug_taggedpointer_slot_mask, + uint32_t objc_debug_taggedpointer_ext_slot_mask, + uint32_t objc_debug_taggedpointer_payload_lshift, + uint32_t objc_debug_taggedpointer_payload_rshift, + uint32_t objc_debug_taggedpointer_ext_payload_lshift, + uint32_t objc_debug_taggedpointer_ext_payload_rshift, + lldb::addr_t objc_debug_taggedpointer_classes, + lldb::addr_t objc_debug_taggedpointer_ext_classes) : +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), +m_ext_cache(), +m_objc_debug_taggedpointer_ext_mask(objc_debug_taggedpointer_ext_mask), +m_objc_debug_taggedpointer_ext_slot_shift(objc_debug_taggedpointer_ext_slot_shift), +m_objc_debug_taggedpointer_ext_slot_mask(objc_debug_taggedpointer_ext_slot_mask), +m_objc_debug_taggedpointer_ext_payload_lshift(objc_debug_taggedpointer_ext_payload_lshift), +m_objc_debug_taggedpointer_ext_payload_rshift(objc_debug_taggedpointer_ext_payload_rshift), +m_objc_debug_taggedpointer_ext_classes(objc_debug_taggedpointer_ext_classes) +{ +} + +bool +AppleObjCRuntimeV2::TaggedPointerVendorExtended::IsPossibleExtendedTaggedPointer (lldb::addr_t ptr) +{ + if (!IsPossibleTaggedPointer(ptr)) + return false; + + if (m_objc_debug_taggedpointer_ext_mask == 0) + return false; + + return ((ptr & m_objc_debug_taggedpointer_ext_mask) == m_objc_debug_taggedpointer_ext_mask); +} + +ObjCLanguageRuntime::ClassDescriptorSP +AppleObjCRuntimeV2::TaggedPointerVendorExtended::GetClassDescriptor (lldb::addr_t ptr) +{ + ClassDescriptorSP actual_class_descriptor_sp; + uint64_t data_payload; + + if (!IsPossibleTaggedPointer(ptr)) + return ObjCLanguageRuntime::ClassDescriptorSP(); + + if (!IsPossibleExtendedTaggedPointer(ptr)) + return this->TaggedPointerVendorRuntimeAssisted::GetClassDescriptor(ptr); + + uintptr_t slot = (ptr >> m_objc_debug_taggedpointer_ext_slot_shift) & m_objc_debug_taggedpointer_ext_slot_mask; + + CacheIterator iterator = m_ext_cache.find(slot), + end = m_ext_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_ext_classes; + Error error; + uintptr_t slot_data = process->ReadPointerFromMemory(slot_ptr, error); + if (error.Fail() || slot_data == 0 || slot_data == uintptr_t(LLDB_INVALID_ADDRESS)) + return nullptr; + actual_class_descriptor_sp = m_runtime.GetClassDescriptorFromISA((ObjCISA)slot_data); + if (!actual_class_descriptor_sp) + return ObjCLanguageRuntime::ClassDescriptorSP(); + m_ext_cache[slot] = actual_class_descriptor_sp; + } + + data_payload = (((uint64_t)ptr << m_objc_debug_taggedpointer_ext_payload_lshift) >> m_objc_debug_taggedpointer_ext_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, |