diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2016-07-23 20:50:09 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2016-07-23 20:50:09 +0000 |
commit | f3fbd1c0586ff6ec7895991e6c28f61a503c36a8 (patch) | |
tree | 48d008fd3df8c0e73271a4b18474e0aac6dbfe33 /source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime | |
parent | 2fc5d2d1dfaf623ce4e24cd8590565902f8c557c (diff) |
Notes
Diffstat (limited to 'source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime')
12 files changed, 580 insertions, 243 deletions
diff --git a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCClassDescriptorV2.cpp b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCClassDescriptorV2.cpp index 711d324d8aa7c..5cf99a573d867 100644 --- a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCClassDescriptorV2.cpp +++ b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCClassDescriptorV2.cpp @@ -499,11 +499,9 @@ ClassDescriptorV2::GetInstanceSize () return 0; } -ClassDescriptorV2::iVarsStorage::iVarsStorage (): -m_filled(false), -m_ivars(), -m_mutex(Mutex::eMutexTypeRecursive) -{} +ClassDescriptorV2::iVarsStorage::iVarsStorage() : m_filled(false), m_ivars(), m_mutex() +{ +} size_t ClassDescriptorV2::iVarsStorage::size () @@ -522,7 +520,7 @@ ClassDescriptorV2::iVarsStorage::fill (AppleObjCRuntimeV2& runtime, ClassDescrip { if (m_filled) return; - Mutex::Locker lock(m_mutex); + std::lock_guard<std::recursive_mutex> guard(m_mutex); Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_TYPES | LIBLLDB_LOG_VERBOSE)); if (log) log->Printf("[ClassDescriptorV2::iVarsStorage::fill] class_name = %s", descriptor.GetClassName().AsCString("<unknown")); diff --git a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCClassDescriptorV2.h b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCClassDescriptorV2.h index 18591ecd6e936..f5fc8bc0644ba 100644 --- a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCClassDescriptorV2.h +++ b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCClassDescriptorV2.h @@ -12,10 +12,11 @@ // C Includes // C++ Includes +#include <mutex> + // Other libraries and framework includes // Project includes #include "lldb/lldb-private.h" -#include "lldb/Host/Mutex.h" #include "lldb/Target/ObjCLanguageRuntime.h" #include "AppleObjCRuntimeV2.h" @@ -247,7 +248,7 @@ private: private: bool m_filled; std::vector<iVarDescriptor> m_ivars; - Mutex m_mutex; + std::recursive_mutex m_mutex; }; // The constructor should only be invoked by the runtime as it builds its caches diff --git a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCDeclVendor.cpp b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCDeclVendor.cpp index cd6ece297ed13..0c0e4f1ce8cc8 100644 --- a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCDeclVendor.cpp +++ b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCDeclVendor.cpp @@ -9,10 +9,11 @@ #include "AppleObjCDeclVendor.h" +#include "Plugins/ExpressionParser/Clang/ASTDumper.h" #include "lldb/Core/Log.h" #include "lldb/Core/Module.h" -#include "Plugins/ExpressionParser/Clang/ASTDumper.h" #include "lldb/Symbol/ClangExternalASTSourceCommon.h" +#include "lldb/Symbol/ClangUtil.h" #include "lldb/Target/ObjCLanguageRuntime.h" #include "lldb/Target/Process.h" #include "lldb/Target/Target.h" @@ -356,9 +357,10 @@ public: } clang::Selector sel = ast_ctx.Selectors.getSelector(is_zero_argument ? 0 : selector_components.size(), selector_components.data()); - - clang::QualType ret_type = ClangASTContext::GetQualType(type_realizer_sp->RealizeType(interface_decl->getASTContext(), m_type_vector[0].c_str(), for_expression)); - + + clang::QualType ret_type = ClangUtil::GetQualType( + type_realizer_sp->RealizeType(interface_decl->getASTContext(), m_type_vector[0].c_str(), for_expression)); + if (ret_type.isNull()) return NULL; @@ -384,8 +386,9 @@ public: ++ai) { const bool for_expression = true; - clang::QualType arg_type = ClangASTContext::GetQualType(type_realizer_sp->RealizeType(ast_ctx, m_type_vector[ai].c_str(), for_expression)); - + clang::QualType arg_type = ClangUtil::GetQualType( + type_realizer_sp->RealizeType(ast_ctx, m_type_vector[ai].c_str(), for_expression)); + if (arg_type.isNull()) return NULL; // well, we just wasted a bunch of time. Wish we could delete the stuff we'd just made! @@ -404,6 +407,24 @@ public: return ret; } + + explicit operator bool () + { + return m_is_valid; + } + + size_t + GetNumTypes () + { + return m_type_vector.size(); + } + + const char* + GetTypeAtIndex (size_t idx) + { + return m_type_vector[idx].c_str(); + } + private: typedef std::vector <std::string> TypeVector; @@ -502,17 +523,12 @@ AppleObjCDeclVendor::FinishDecl(clang::ObjCInterfaceDecl *interface_decl) { clang::TypeSourceInfo * const type_source_info = nullptr; const bool is_synthesized = false; - clang::ObjCIvarDecl *ivar_decl = clang::ObjCIvarDecl::Create (*m_ast_ctx.getASTContext(), - interface_decl, - clang::SourceLocation(), - clang::SourceLocation(), - &m_ast_ctx.getASTContext()->Idents.get(name), - ClangASTContext::GetQualType(ivar_type), - type_source_info, // TypeSourceInfo * - clang::ObjCIvarDecl::Public, - 0, - is_synthesized); - + clang::ObjCIvarDecl *ivar_decl = clang::ObjCIvarDecl::Create( + *m_ast_ctx.getASTContext(), interface_decl, clang::SourceLocation(), clang::SourceLocation(), + &m_ast_ctx.getASTContext()->Idents.get(name), ClangUtil::GetQualType(ivar_type), + type_source_info, // TypeSourceInfo * + clang::ObjCIvarDecl::Public, 0, is_synthesized); + if (ivar_decl) { interface_decl->addDecl(ivar_decl); diff --git a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.cpp b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.cpp index 2810b24cb7a43..6d83f7a7c5e16 100644 --- a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.cpp +++ b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.cpp @@ -23,6 +23,7 @@ #include "lldb/Core/Section.h" #include "lldb/Core/StreamString.h" #include "lldb/Core/ValueObject.h" +#include "lldb/Expression/DiagnosticManager.h" #include "lldb/Expression/FunctionCaller.h" #include "lldb/Symbol/ClangASTContext.h" #include "lldb/Symbol/ObjectFile.h" @@ -151,10 +152,10 @@ AppleObjCRuntime::GetObjectDescription (Stream &strm, Value &value, ExecutionCon exe_ctx.SetFrameSP(thread->GetSelectedFrame()); } } - + // Now we're ready to call the function: - - StreamString error_stream; + + DiagnosticManager diagnostics; lldb::addr_t wrapper_struct_addr = LLDB_INVALID_ADDRESS; if (!m_print_object_caller_up) @@ -172,30 +173,22 @@ AppleObjCRuntime::GetObjectDescription (Stream &strm, Value &value, ExecutionCon strm.Printf("Could not get function runner to call print for debugger function: %s.", error.AsCString()); return false; } - m_print_object_caller_up->InsertFunction(exe_ctx, wrapper_struct_addr, error_stream); + m_print_object_caller_up->InsertFunction(exe_ctx, wrapper_struct_addr, diagnostics); } else { - m_print_object_caller_up->WriteFunctionArguments(exe_ctx, - wrapper_struct_addr, - arg_value_list, - error_stream); + m_print_object_caller_up->WriteFunctionArguments(exe_ctx, wrapper_struct_addr, arg_value_list, diagnostics); } - - EvaluateExpressionOptions options; options.SetUnwindOnError(true); options.SetTryAllThreads(true); options.SetStopOthers(true); options.SetIgnoreBreakpoints(true); options.SetTimeoutUsec(PO_FUNCTION_TIMEOUT_USEC); - - ExpressionResults results = m_print_object_caller_up->ExecuteFunction (exe_ctx, - &wrapper_struct_addr, - options, - error_stream, - ret); + + ExpressionResults results = + m_print_object_caller_up->ExecuteFunction(exe_ctx, &wrapper_struct_addr, options, diagnostics, ret); if (results != eExpressionCompleted) { strm.Printf("Error evaluating Print Object function: %d.\n", results); @@ -401,8 +394,8 @@ AppleObjCRuntime::GetObjCVersion (Process *process, ModuleSP &objc_module_sp) return ObjCRuntimeVersions::eObjC_VersionUnknown; const ModuleList &target_modules = target.GetImages(); - Mutex::Locker modules_locker(target_modules.GetMutex()); - + std::lock_guard<std::recursive_mutex> gaurd(target_modules.GetMutex()); + size_t num_images = target_modules.GetSize(); for (size_t i = 0; i < num_images; i++) { @@ -531,7 +524,7 @@ AppleObjCRuntime::ReadObjCLibraryIfNeeded (const ModuleList &module_list) { if (!HasReadObjCLibrary ()) { - Mutex::Locker locker (module_list.GetMutex ()); + std::lock_guard<std::recursive_mutex> guard(module_list.GetMutex()); size_t num_modules = module_list.GetSize(); for (size_t i = 0; i < num_modules; i++) diff --git a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.cpp b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.cpp index 59b28b63f6b3a..805fca7a31b9d 100644 --- a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.cpp +++ b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.cpp @@ -136,6 +136,7 @@ AppleObjCRuntimeV1::CreateExceptionResolver (Breakpoint *bkpt, bool catch_bp, bo eFunctionNameTypeBase, eLanguageTypeUnknown, Breakpoint::Exact, + 0, eLazyBoolNo)); // FIXME: don't do catch yet. return resolver_sp; diff --git a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp index 584449430829f..e9a799bb36510 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, diff --git a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.h b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.h index 96b47e8770f99..4b27c74004812 100644 --- a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.h +++ b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.h @@ -14,6 +14,7 @@ // C++ Includes #include <map> #include <memory> +#include <mutex> // Other libraries and framework includes // Project includes @@ -234,6 +235,45 @@ private: DISALLOW_COPY_AND_ASSIGN(TaggedPointerVendorRuntimeAssisted); }; + class TaggedPointerVendorExtended : public TaggedPointerVendorRuntimeAssisted + { + public: + ObjCLanguageRuntime::ClassDescriptorSP + GetClassDescriptor(lldb::addr_t ptr) override; + + protected: + 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); + + bool + IsPossibleExtendedTaggedPointer (lldb::addr_t ptr); + + typedef std::map<uint8_t,ObjCLanguageRuntime::ClassDescriptorSP> Cache; + typedef Cache::iterator CacheIterator; + Cache m_ext_cache; + uint64_t m_objc_debug_taggedpointer_ext_mask; + uint32_t m_objc_debug_taggedpointer_ext_slot_shift; + uint32_t m_objc_debug_taggedpointer_ext_slot_mask; + uint32_t m_objc_debug_taggedpointer_ext_payload_lshift; + uint32_t m_objc_debug_taggedpointer_ext_payload_rshift; + lldb::addr_t m_objc_debug_taggedpointer_ext_classes; + + friend class AppleObjCRuntimeV2::TaggedPointerVendorV2; + + DISALLOW_COPY_AND_ASSIGN(TaggedPointerVendorExtended); + }; + class TaggedPointerVendorLegacy : public TaggedPointerVendorV2 { public: @@ -314,11 +354,11 @@ private: std::unique_ptr<UtilityFunction> m_get_class_info_code; lldb::addr_t m_get_class_info_args; - Mutex m_get_class_info_args_mutex; + std::mutex m_get_class_info_args_mutex; std::unique_ptr<UtilityFunction> m_get_shared_cache_class_info_code; lldb::addr_t m_get_shared_cache_class_info_args; - Mutex m_get_shared_cache_class_info_args_mutex; + std::mutex m_get_shared_cache_class_info_args_mutex; std::unique_ptr<DeclVendor> m_decl_vendor_ap; lldb::addr_t m_isa_hash_table_ptr; diff --git a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.cpp b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.cpp index d38a076ad5d74..5fedb80e29a6f 100644 --- a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.cpp +++ b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.cpp @@ -22,19 +22,20 @@ #include "lldb/Core/Module.h" #include "lldb/Core/StreamFile.h" #include "lldb/Core/Value.h" -#include "lldb/Expression/UserExpression.h" +#include "lldb/Expression/DiagnosticManager.h" #include "lldb/Expression/FunctionCaller.h" +#include "lldb/Expression/UserExpression.h" #include "lldb/Expression/UtilityFunction.h" #include "lldb/Host/FileSpec.h" #include "lldb/Symbol/ClangASTContext.h" #include "lldb/Symbol/Symbol.h" #include "lldb/Target/ABI.h" +#include "lldb/Target/ExecutionContext.h" #include "lldb/Target/ObjCLanguageRuntime.h" #include "lldb/Target/Process.h" #include "lldb/Target/RegisterContext.h" #include "lldb/Target/Target.h" #include "lldb/Target/Thread.h" -#include "lldb/Target/ExecutionContext.h" #include "lldb/Target/ThreadPlanRunToAddress.h" #include "llvm/ADT/STLExtras.h" @@ -43,7 +44,6 @@ using namespace lldb; using namespace lldb_private; const char *AppleObjCTrampolineHandler::g_lookup_implementation_function_name = "__lldb_objc_find_implementation_for_selector"; -const char *AppleObjCTrampolineHandler::g_lookup_implementation_function_code = NULL; const char *AppleObjCTrampolineHandler::g_lookup_implementation_with_stret_function_code = " \n\ extern \"C\" \n\ { \n\ @@ -461,7 +461,7 @@ AppleObjCTrampolineHandler::AppleObjCVTables::InitializeVTableSymbols () Target &target = process_sp->GetTarget(); const ModuleList &target_modules = target.GetImages(); - Mutex::Locker modules_locker(target_modules.GetMutex()); + std::lock_guard<std::recursive_mutex> guard(target_modules.GetMutex()); size_t num_modules = target_modules.GetSize(); if (!m_objc_module_sp) { @@ -657,6 +657,7 @@ AppleObjCTrampolineHandler::AppleObjCTrampolineHandler (const ProcessSP &process const ModuleSP &objc_module_sp) : m_process_wp (), m_objc_module_sp (objc_module_sp), + m_lookup_implementation_function_code(nullptr), m_impl_fn_addr (LLDB_INVALID_ADDRESS), m_impl_stret_fn_addr (LLDB_INVALID_ADDRESS), m_msg_forward_addr (LLDB_INVALID_ADDRESS) @@ -703,11 +704,11 @@ AppleObjCTrampolineHandler::AppleObjCTrampolineHandler (const ProcessSP &process // It there is no stret return lookup function, assume that it is the same as the straight lookup: m_impl_stret_fn_addr = m_impl_fn_addr; // Also we will use the version of the lookup code that doesn't rely on the stret version of the function. - g_lookup_implementation_function_code = g_lookup_implementation_no_stret_function_code; + m_lookup_implementation_function_code = g_lookup_implementation_no_stret_function_code; } else { - g_lookup_implementation_function_code = g_lookup_implementation_with_stret_function_code; + m_lookup_implementation_function_code = g_lookup_implementation_with_stret_function_code; } // Look up the addresses for the objc dispatch functions and cache them. For now I'm inspecting the symbol @@ -738,26 +739,28 @@ AppleObjCTrampolineHandler::AppleObjCTrampolineHandler (const ProcessSP &process } lldb::addr_t -AppleObjCTrampolineHandler::SetupDispatchFunction (Thread &thread, ValueList &dispatch_values) +AppleObjCTrampolineHandler::SetupDispatchFunction(Thread &thread, ValueList &dispatch_values) { - ExecutionContext exe_ctx (thread.shared_from_this()); - StreamString errors; - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); + ThreadSP thread_sp(thread.shared_from_this()); + ExecutionContext exe_ctx (thread_sp); + DiagnosticManager diagnostics; + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP)); + lldb::addr_t args_addr = LLDB_INVALID_ADDRESS; FunctionCaller *impl_function_caller = nullptr; // Scope for mutex locker: { - Mutex::Locker locker(m_impl_function_mutex); - + std::lock_guard<std::mutex> guard(m_impl_function_mutex); + // First stage is to make the ClangUtility to hold our injected function: if (!m_impl_code.get()) { - if (g_lookup_implementation_function_code != NULL) + if (m_lookup_implementation_function_code != NULL) { Error error; - m_impl_code.reset (exe_ctx.GetTargetRef().GetUtilityFunctionForLanguage (g_lookup_implementation_function_code, + m_impl_code.reset (exe_ctx.GetTargetRef().GetUtilityFunctionForLanguage (m_lookup_implementation_function_code, eLanguageTypeObjC, g_lookup_implementation_function_name, error)); @@ -768,11 +771,14 @@ AppleObjCTrampolineHandler::SetupDispatchFunction (Thread &thread, ValueList &di m_impl_code.reset(); return args_addr; } - - if (!m_impl_code->Install(errors, exe_ctx)) + + if (!m_impl_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_impl_code.reset(); return args_addr; } @@ -781,10 +787,8 @@ AppleObjCTrampolineHandler::SetupDispatchFunction (Thread &thread, ValueList &di { if (log) log->Printf("No method lookup implementation code."); - errors.Printf ("No method lookup implementation code found."); return LLDB_INVALID_ADDRESS; } - // Next make the runner function for our implementation utility function. ClangASTContext *clang_ast_context = thread.GetProcess()->GetTarget().GetScratchClangASTContext(); @@ -793,6 +797,7 @@ AppleObjCTrampolineHandler::SetupDispatchFunction (Thread &thread, ValueList &di impl_function_caller = m_impl_code->MakeFunctionCaller(clang_void_ptr_type, dispatch_values, + thread_sp, error); if (error.Fail()) { @@ -806,20 +811,23 @@ AppleObjCTrampolineHandler::SetupDispatchFunction (Thread &thread, ValueList &di impl_function_caller = m_impl_code->GetFunctionCaller(); } } - - errors.Clear(); - + + diagnostics.Clear(); + // Now write down the argument values for this particular call. This looks like it might be a race condition // if other threads were calling into here, but actually it isn't because we allocate a new args structure for // this call by passing args_addr = LLDB_INVALID_ADDRESS... - if (impl_function_caller->WriteFunctionArguments (exe_ctx, args_addr, dispatch_values, errors)) + if (!impl_function_caller->WriteFunctionArguments(exe_ctx, args_addr, dispatch_values, diagnostics)) { if (log) - log->Printf ("Error writing function arguments: \"%s\".", errors.GetData()); + { + log->Printf("Error writing function arguments."); + diagnostics.Dump(log); + } return args_addr; } - + return args_addr; } diff --git a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.h b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.h index 42d3461ddfa5a..c0d1944a7f2f2 100644 --- a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.h +++ b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.h @@ -13,12 +13,12 @@ // C Includes // C++ Includes #include <map> +#include <mutex> #include <vector> // Other libraries and framework includes // Project includes #include "lldb/lldb-public.h" -#include "lldb/Host/Mutex.h" #include "lldb/Expression/UtilityFunction.h" namespace lldb_private @@ -65,7 +65,6 @@ public: private: static const char *g_lookup_implementation_function_name; - static const char *g_lookup_implementation_function_code; static const char *g_lookup_implementation_with_stret_function_code; static const char *g_lookup_implementation_no_stret_function_code; @@ -195,8 +194,9 @@ private: MsgsendMap m_msgSend_map; lldb::ProcessWP m_process_wp; lldb::ModuleSP m_objc_module_sp; + const char *m_lookup_implementation_function_code; std::unique_ptr<UtilityFunction> m_impl_code; - Mutex m_impl_function_mutex; + std::mutex m_impl_function_mutex; lldb::addr_t m_impl_fn_addr; lldb::addr_t m_impl_stret_fn_addr; lldb::addr_t m_msg_forward_addr; diff --git a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeEncodingParser.cpp b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeEncodingParser.cpp index 9308c7a668d27..d4adc094bc1b5 100644 --- a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeEncodingParser.cpp +++ b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeEncodingParser.cpp @@ -10,6 +10,7 @@ #include "AppleObjCTypeEncodingParser.h" #include "lldb/Symbol/ClangASTContext.h" +#include "lldb/Symbol/ClangUtil.h" #include "lldb/Symbol/CompilerType.h" #include "lldb/Target/Process.h" #include "lldb/Target/Target.h" @@ -155,7 +156,7 @@ AppleObjCTypeEncodingParser::BuildAggregate (clang::ASTContext &ast_ctx, lldb_ut } ClangASTContext::CompleteTagDeclarationDefinition(union_type); } - return ClangASTContext::GetQualType(union_type); + return ClangUtil::GetQualType(union_type); } clang::QualType @@ -171,7 +172,7 @@ AppleObjCTypeEncodingParser::BuildArray (clang::ASTContext &ast_ctx, lldb_utilit if (!lldb_ctx) return clang::QualType(); CompilerType array_type(lldb_ctx->CreateArrayType(CompilerType(&ast_ctx, element_type), size, false)); - return ClangASTContext::GetQualType(array_type); + return ClangUtil::GetQualType(array_type); } // the runtime can emit these in the form of @"SomeType", giving more specifics @@ -261,8 +262,8 @@ AppleObjCTypeEncodingParser::BuildObjCObjectPointerType (clang::ASTContext &ast_ if (!num_types) return ast_ctx.getObjCIdType(); #endif - - return ClangASTContext::GetQualType(ClangASTContext::GetTypeForDecl(decls[0]).GetPointerType()); + + return ClangUtil::GetQualType(ClangASTContext::GetTypeForDecl(decls[0]).GetPointerType()); } else { diff --git a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleThreadPlanStepThroughObjCTrampoline.cpp b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleThreadPlanStepThroughObjCTrampoline.cpp index 285786a09dbbd..a2101c927b4df 100644 --- a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleThreadPlanStepThroughObjCTrampoline.cpp +++ b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleThreadPlanStepThroughObjCTrampoline.cpp @@ -13,16 +13,16 @@ // Project includes #include "AppleThreadPlanStepThroughObjCTrampoline.h" #include "AppleObjCTrampolineHandler.h" -#include "lldb/Target/Process.h" -#include "lldb/Target/Thread.h" +#include "lldb/Core/Log.h" +#include "lldb/Expression/DiagnosticManager.h" #include "lldb/Expression/FunctionCaller.h" #include "lldb/Expression/UtilityFunction.h" #include "lldb/Target/ExecutionContext.h" #include "lldb/Target/ObjCLanguageRuntime.h" +#include "lldb/Target/Process.h" +#include "lldb/Target/Thread.h" #include "lldb/Target/ThreadPlanRunToAddress.h" #include "lldb/Target/ThreadPlanStepOut.h" -#include "lldb/Core/Log.h" - using namespace lldb; using namespace lldb_private; @@ -75,9 +75,9 @@ AppleThreadPlanStepThroughObjCTrampoline::InitializeFunctionCaller () { if (!m_func_sp) { - StreamString errors; + DiagnosticManager diagnostics; m_args_addr = m_trampoline_handler->SetupDispatchFunction(m_thread, m_input_values); - + if (m_args_addr == LLDB_INVALID_ADDRESS) { return false; @@ -89,12 +89,9 @@ AppleThreadPlanStepThroughObjCTrampoline::InitializeFunctionCaller () options.SetIgnoreBreakpoints(true); options.SetStopOthers(m_stop_others); m_thread.CalculateExecutionContext(exc_ctx); - m_func_sp = m_impl_function->GetThreadPlanToCallFunction (exc_ctx, - m_args_addr, - options, - errors); + m_func_sp = m_impl_function->GetThreadPlanToCallFunction(exc_ctx, m_args_addr, options, diagnostics); m_func_sp->SetOkayToDiscard(true); - m_thread.QueueThreadPlan (m_func_sp, false); + m_thread.QueueThreadPlan(m_func_sp, false); } return true; } diff --git a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/Makefile b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/Makefile deleted file mode 100644 index 485fe75b3f88b..0000000000000 --- a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -##===- source/Plugins/LangRuntime/ObjC/AppleRT/Makefile ----*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LLDB_LEVEL := ../../../../.. -LIBRARYNAME := lldbPluginAppleObjCRuntime -BUILD_ARCHIVE = 1 - -include $(LLDB_LEVEL)/Makefile |