diff options
Diffstat (limited to 'source/Plugins/SystemRuntime/MacOSX')
11 files changed, 0 insertions, 3415 deletions
diff --git a/source/Plugins/SystemRuntime/MacOSX/AppleGetItemInfoHandler.cpp b/source/Plugins/SystemRuntime/MacOSX/AppleGetItemInfoHandler.cpp deleted file mode 100644 index 43e401330c5c..000000000000 --- a/source/Plugins/SystemRuntime/MacOSX/AppleGetItemInfoHandler.cpp +++ /dev/null @@ -1,398 +0,0 @@ -//===-- AppleGetItemInfoHandler.cpp -------------------------------*- C++ -//-*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "AppleGetItemInfoHandler.h" - - -#include "lldb/Core/Module.h" -#include "lldb/Core/Value.h" -#include "lldb/Expression/DiagnosticManager.h" -#include "lldb/Expression/FunctionCaller.h" -#include "lldb/Expression/UtilityFunction.h" -#include "lldb/Symbol/ClangASTContext.h" -#include "lldb/Symbol/Symbol.h" -#include "lldb/Target/ExecutionContext.h" -#include "lldb/Target/Process.h" -#include "lldb/Target/Target.h" -#include "lldb/Target/Thread.h" -#include "lldb/Utility/ConstString.h" -#include "lldb/Utility/Log.h" -#include "lldb/Utility/StreamString.h" - -using namespace lldb; -using namespace lldb_private; - -const char *AppleGetItemInfoHandler::g_get_item_info_function_name = - "__lldb_backtrace_recording_get_item_info"; -const char *AppleGetItemInfoHandler::g_get_item_info_function_code = - " \n\ -extern \"C\" \n\ -{ \n\ - /* \n\ - * mach defines \n\ - */ \n\ - \n\ - typedef unsigned int uint32_t; \n\ - typedef unsigned long long uint64_t; \n\ - typedef uint32_t mach_port_t; \n\ - typedef mach_port_t vm_map_t; \n\ - typedef int kern_return_t; \n\ - typedef uint64_t mach_vm_address_t; \n\ - typedef uint64_t mach_vm_size_t; \n\ - \n\ - mach_port_t mach_task_self (); \n\ - kern_return_t mach_vm_deallocate (vm_map_t target, mach_vm_address_t address, mach_vm_size_t size); \n\ - \n\ - /* \n\ - * libBacktraceRecording defines \n\ - */ \n\ - \n\ - typedef uint32_t queue_list_scope_t; \n\ - typedef void *dispatch_queue_t; \n\ - typedef void *introspection_dispatch_queue_info_t; \n\ - typedef void *introspection_dispatch_item_info_ref; \n\ - \n\ - extern uint64_t __introspection_dispatch_queue_item_get_info (introspection_dispatch_item_info_ref item_info_ref, \n\ - introspection_dispatch_item_info_ref *returned_queues_buffer, \n\ - uint64_t *returned_queues_buffer_size); \n\ - extern int printf(const char *format, ...); \n\ - \n\ - /* \n\ - * return type define \n\ - */ \n\ - \n\ - struct get_item_info_return_values \n\ - { \n\ - uint64_t item_info_buffer_ptr; /* the address of the items buffer from libBacktraceRecording */ \n\ - uint64_t item_info_buffer_size; /* the size of the items buffer from libBacktraceRecording */ \n\ - }; \n\ - \n\ - void __lldb_backtrace_recording_get_item_info \n\ - (struct get_item_info_return_values *return_buffer, \n\ - int debug, \n\ - uint64_t /* introspection_dispatch_item_info_ref item_info_ref */ item, \n\ - void *page_to_free, \n\ - uint64_t page_to_free_size) \n\ -{ \n\ - if (debug) \n\ - printf (\"entering get_item_info with args return_buffer == %p, debug == %d, item == 0x%llx, page_to_free == %p, page_to_free_size == 0x%llx\\n\", return_buffer, debug, item, page_to_free, page_to_free_size); \n\ - if (page_to_free != 0) \n\ - { \n\ - mach_vm_deallocate (mach_task_self(), (mach_vm_address_t) page_to_free, (mach_vm_size_t) page_to_free_size); \n\ - } \n\ - \n\ - __introspection_dispatch_queue_item_get_info ((void*) item, \n\ - (void**)&return_buffer->item_info_buffer_ptr, \n\ - &return_buffer->item_info_buffer_size); \n\ -} \n\ -} \n\ -"; - -AppleGetItemInfoHandler::AppleGetItemInfoHandler(Process *process) - : m_process(process), m_get_item_info_impl_code(), - m_get_item_info_function_mutex(), - m_get_item_info_return_buffer_addr(LLDB_INVALID_ADDRESS), - m_get_item_info_retbuffer_mutex() {} - -AppleGetItemInfoHandler::~AppleGetItemInfoHandler() {} - -void AppleGetItemInfoHandler::Detach() { - - if (m_process && m_process->IsAlive() && - m_get_item_info_return_buffer_addr != LLDB_INVALID_ADDRESS) { - std::unique_lock<std::mutex> lock(m_get_item_info_retbuffer_mutex, - std::defer_lock); - lock.try_lock(); // Even if we don't get the lock, deallocate the buffer - m_process->DeallocateMemory(m_get_item_info_return_buffer_addr); - } -} - -// Compile our __lldb_backtrace_recording_get_item_info() function (from the -// source above in g_get_item_info_function_code) if we don't find that -// function in the inferior already with USE_BUILTIN_FUNCTION defined. (e.g. -// this would be the case for testing.) -// -// Insert the __lldb_backtrace_recording_get_item_info into the inferior -// process if needed. -// -// Write the get_item_info_arglist into the inferior's memory space to prepare -// for the call. -// -// Returns the address of the arguments written down in the inferior process, -// which can be used to make the function call. - -lldb::addr_t AppleGetItemInfoHandler::SetupGetItemInfoFunction( - Thread &thread, ValueList &get_item_info_arglist) { - ExecutionContext exe_ctx(thread.shared_from_this()); - DiagnosticManager diagnostics; - Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_SYSTEM_RUNTIME)); - lldb::addr_t args_addr = LLDB_INVALID_ADDRESS; - FunctionCaller *get_item_info_caller = nullptr; - - // Scope for mutex locker: - { - std::lock_guard<std::mutex> guard(m_get_item_info_function_mutex); - - // First stage is to make the UtilityFunction to hold our injected - // function: - - if (!m_get_item_info_impl_code.get()) { - if (g_get_item_info_function_code != NULL) { - Status error; - m_get_item_info_impl_code.reset( - exe_ctx.GetTargetRef().GetUtilityFunctionForLanguage( - g_get_item_info_function_code, eLanguageTypeObjC, - g_get_item_info_function_name, error)); - if (error.Fail()) { - if (log) - log->Printf("Failed to get utility function: %s.", - error.AsCString()); - return args_addr; - } - - if (!m_get_item_info_impl_code->Install(diagnostics, exe_ctx)) { - if (log) { - log->Printf("Failed to install get-item-info introspection."); - diagnostics.Dump(log); - } - m_get_item_info_impl_code.reset(); - return args_addr; - } - } else { - if (log) - log->Printf("No get-item-info introspection code found."); - return LLDB_INVALID_ADDRESS; - } - - // Next make the runner function for our implementation utility function. - Status error; - - TypeSystem *type_system = - thread.GetProcess()->GetTarget().GetScratchTypeSystemForLanguage( - nullptr, eLanguageTypeC); - CompilerType get_item_info_return_type = - type_system->GetBasicTypeFromAST(eBasicTypeVoid).GetPointerType(); - - get_item_info_caller = m_get_item_info_impl_code->MakeFunctionCaller( - get_item_info_return_type, get_item_info_arglist, - thread.shared_from_this(), error); - if (error.Fail() || get_item_info_caller == nullptr) { - if (log) - log->Printf("Error Inserting get-item-info function: \"%s\".", - error.AsCString()); - return args_addr; - } - } else { - // If it's already made, then we can just retrieve the caller: - get_item_info_caller = m_get_item_info_impl_code->GetFunctionCaller(); - if (!get_item_info_caller) { - if (log) - log->Printf("Failed to get get-item-info introspection caller."); - m_get_item_info_impl_code.reset(); - return args_addr; - } - } - } - - 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 (!get_item_info_caller->WriteFunctionArguments( - exe_ctx, args_addr, get_item_info_arglist, diagnostics)) { - if (log) { - log->Printf("Error writing get-item-info function arguments."); - diagnostics.Dump(log); - } - - return args_addr; - } - - return args_addr; -} - -AppleGetItemInfoHandler::GetItemInfoReturnInfo -AppleGetItemInfoHandler::GetItemInfo(Thread &thread, uint64_t item, - addr_t page_to_free, - uint64_t page_to_free_size, - Status &error) { - lldb::StackFrameSP thread_cur_frame = thread.GetStackFrameAtIndex(0); - ProcessSP process_sp(thread.CalculateProcess()); - TargetSP target_sp(thread.CalculateTarget()); - ClangASTContext *clang_ast_context = target_sp->GetScratchClangASTContext(); - Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_SYSTEM_RUNTIME)); - - GetItemInfoReturnInfo return_value; - return_value.item_buffer_ptr = LLDB_INVALID_ADDRESS; - return_value.item_buffer_size = 0; - - error.Clear(); - - if (!thread.SafeToCallFunctions()) { - if (log) - log->Printf("Not safe to call functions on thread 0x%" PRIx64, - thread.GetID()); - error.SetErrorString("Not safe to call functions on this thread."); - return return_value; - } - - // Set up the arguments for a call to - - // struct get_item_info_return_values - // { - // uint64_t item_info_buffer_ptr; /* the address of the items buffer - // from libBacktraceRecording */ - // uint64_t item_info_buffer_size; /* the size of the items buffer from - // libBacktraceRecording */ - // }; - // - // void __lldb_backtrace_recording_get_item_info - // (struct - // get_item_info_return_values - // *return_buffer, - // int debug, - // uint64_t item, - // void *page_to_free, - // uint64_t page_to_free_size) - - // Where the return_buffer argument points to a 24 byte region of memory - // already allocated by lldb in the inferior process. - - CompilerType clang_void_ptr_type = - clang_ast_context->GetBasicType(eBasicTypeVoid).GetPointerType(); - Value return_buffer_ptr_value; - return_buffer_ptr_value.SetValueType(Value::eValueTypeScalar); - return_buffer_ptr_value.SetCompilerType(clang_void_ptr_type); - - CompilerType clang_int_type = clang_ast_context->GetBasicType(eBasicTypeInt); - Value debug_value; - debug_value.SetValueType(Value::eValueTypeScalar); - debug_value.SetCompilerType(clang_int_type); - - CompilerType clang_uint64_type = - clang_ast_context->GetBasicType(eBasicTypeUnsignedLongLong); - Value item_value; - item_value.SetValueType(Value::eValueTypeScalar); - item_value.SetCompilerType(clang_uint64_type); - - Value page_to_free_value; - page_to_free_value.SetValueType(Value::eValueTypeScalar); - page_to_free_value.SetCompilerType(clang_void_ptr_type); - - Value page_to_free_size_value; - page_to_free_size_value.SetValueType(Value::eValueTypeScalar); - page_to_free_size_value.SetCompilerType(clang_uint64_type); - - std::lock_guard<std::mutex> guard(m_get_item_info_retbuffer_mutex); - if (m_get_item_info_return_buffer_addr == LLDB_INVALID_ADDRESS) { - addr_t bufaddr = process_sp->AllocateMemory( - 32, ePermissionsReadable | ePermissionsWritable, error); - if (!error.Success() || bufaddr == LLDB_INVALID_ADDRESS) { - if (log) - log->Printf("Failed to allocate memory for return buffer for get " - "current queues func call"); - return return_value; - } - m_get_item_info_return_buffer_addr = bufaddr; - } - - ValueList argument_values; - - return_buffer_ptr_value.GetScalar() = m_get_item_info_return_buffer_addr; - argument_values.PushValue(return_buffer_ptr_value); - - debug_value.GetScalar() = 0; - argument_values.PushValue(debug_value); - - item_value.GetScalar() = item; - argument_values.PushValue(item_value); - - if (page_to_free != LLDB_INVALID_ADDRESS) - page_to_free_value.GetScalar() = page_to_free; - else - page_to_free_value.GetScalar() = 0; - argument_values.PushValue(page_to_free_value); - - page_to_free_size_value.GetScalar() = page_to_free_size; - argument_values.PushValue(page_to_free_size_value); - - addr_t args_addr = SetupGetItemInfoFunction(thread, argument_values); - - DiagnosticManager diagnostics; - ExecutionContext exe_ctx; - EvaluateExpressionOptions options; - options.SetUnwindOnError(true); - options.SetIgnoreBreakpoints(true); - options.SetStopOthers(true); - options.SetTimeout(std::chrono::milliseconds(500)); - options.SetTryAllThreads(false); - options.SetIsForUtilityExpr(true); - thread.CalculateExecutionContext(exe_ctx); - - if (!m_get_item_info_impl_code) { - error.SetErrorString("Unable to compile function to call " - "__introspection_dispatch_queue_item_get_info"); - return return_value; - } - - ExpressionResults func_call_ret; - Value results; - FunctionCaller *func_caller = m_get_item_info_impl_code->GetFunctionCaller(); - if (!func_caller) { - if (log) - log->Printf("Could not retrieve function caller for " - "__introspection_dispatch_queue_item_get_info."); - error.SetErrorString("Could not retrieve function caller for " - "__introspection_dispatch_queue_item_get_info."); - return return_value; - } - - func_call_ret = func_caller->ExecuteFunction(exe_ctx, &args_addr, options, - diagnostics, results); - if (func_call_ret != eExpressionCompleted || !error.Success()) { - if (log) - log->Printf("Unable to call " - "__introspection_dispatch_queue_item_get_info(), got " - "ExpressionResults %d, error contains %s", - func_call_ret, error.AsCString("")); - error.SetErrorString("Unable to call " - "__introspection_dispatch_queue_get_item_info() for " - "list of queues"); - return return_value; - } - - return_value.item_buffer_ptr = m_process->ReadUnsignedIntegerFromMemory( - m_get_item_info_return_buffer_addr, 8, LLDB_INVALID_ADDRESS, error); - if (!error.Success() || - return_value.item_buffer_ptr == LLDB_INVALID_ADDRESS) { - return_value.item_buffer_ptr = LLDB_INVALID_ADDRESS; - return return_value; - } - - return_value.item_buffer_size = m_process->ReadUnsignedIntegerFromMemory( - m_get_item_info_return_buffer_addr + 8, 8, 0, error); - - if (!error.Success()) { - return_value.item_buffer_ptr = LLDB_INVALID_ADDRESS; - return return_value; - } - if (log) - log->Printf("AppleGetItemInfoHandler called " - "__introspection_dispatch_queue_item_get_info (page_to_free == " - "0x%" PRIx64 ", size = %" PRId64 - "), returned page is at 0x%" PRIx64 ", size %" PRId64, - page_to_free, page_to_free_size, return_value.item_buffer_ptr, - return_value.item_buffer_size); - - return return_value; -} diff --git a/source/Plugins/SystemRuntime/MacOSX/AppleGetItemInfoHandler.h b/source/Plugins/SystemRuntime/MacOSX/AppleGetItemInfoHandler.h deleted file mode 100644 index ac3711ead878..000000000000 --- a/source/Plugins/SystemRuntime/MacOSX/AppleGetItemInfoHandler.h +++ /dev/null @@ -1,115 +0,0 @@ -//===-- AppleGetItemInfoHandler.h ----------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef lldb_AppleGetItemInfoHandler_h_ -#define lldb_AppleGetItemInfoHandler_h_ - -#include <map> -#include <mutex> -#include <vector> - -#include "lldb/Expression/UtilityFunction.h" -#include "lldb/Symbol/CompilerType.h" -#include "lldb/Utility/Status.h" -#include "lldb/lldb-public.h" - -// This class will insert a UtilityFunction into the inferior process for -// calling libBacktraceRecording's -// __introspection_dispatch_queue_item_get_info() -// function. The function in the inferior will return a struct by value -// with these members: -// -// struct get_item_info_return_values -// { -// introspection_dispatch_item_info_ref *item_buffer; -// uint64_t item_buffer_size; -// }; -// -// The item_buffer pointer is an address in the inferior program's address -// space (item_buffer_size in size) which must be mach_vm_deallocate'd by -// lldb. -// -// The AppleGetItemInfoHandler object should persist so that the UtilityFunction -// can be reused multiple times. - -namespace lldb_private { - -class AppleGetItemInfoHandler { -public: - AppleGetItemInfoHandler(lldb_private::Process *process); - - ~AppleGetItemInfoHandler(); - - struct GetItemInfoReturnInfo { - lldb::addr_t item_buffer_ptr; /* the address of the item buffer from - libBacktraceRecording */ - lldb::addr_t item_buffer_size; /* the size of the item buffer from - libBacktraceRecording */ - - GetItemInfoReturnInfo() - : item_buffer_ptr(LLDB_INVALID_ADDRESS), item_buffer_size(0) {} - }; - - //---------------------------------------------------------- - /// Get the information about a work item by calling - /// __introspection_dispatch_queue_item_get_info. If there's a page of - /// memory that needs to be freed, pass in the address and size and it will - /// be freed before getting the list of queues. - /// - /// @param [in] thread - /// The thread to run this plan on. - /// - /// @param [in] item - /// The introspection_dispatch_item_info_ref value for the item of - /// interest. - /// - /// @param [in] page_to_free - /// An address of an inferior process vm page that needs to be - /// deallocated, - /// LLDB_INVALID_ADDRESS if this is not needed. - /// - /// @param [in] page_to_free_size - /// The size of the vm page that needs to be deallocated if an address was - /// passed in to page_to_free. - /// - /// @param [out] error - /// This object will be updated with the error status / error string from - /// any failures encountered. - /// - /// @returns - /// The result of the inferior function call execution. If there was a - /// failure of any kind while getting - /// the information, the item_buffer_ptr value will be - /// LLDB_INVALID_ADDRESS. - //---------------------------------------------------------- - GetItemInfoReturnInfo GetItemInfo(Thread &thread, lldb::addr_t item, - lldb::addr_t page_to_free, - uint64_t page_to_free_size, - lldb_private::Status &error); - - void Detach(); - -private: - lldb::addr_t SetupGetItemInfoFunction(Thread &thread, - ValueList &get_item_info_arglist); - - static const char *g_get_item_info_function_name; - static const char *g_get_item_info_function_code; - - lldb_private::Process *m_process; - std::unique_ptr<UtilityFunction> m_get_item_info_impl_code; - std::mutex m_get_item_info_function_mutex; - - lldb::addr_t m_get_item_info_return_buffer_addr; - std::mutex m_get_item_info_retbuffer_mutex; -}; - -} // using namespace lldb_private - -#endif // lldb_AppleGetItemInfoHandler_h_ diff --git a/source/Plugins/SystemRuntime/MacOSX/AppleGetPendingItemsHandler.cpp b/source/Plugins/SystemRuntime/MacOSX/AppleGetPendingItemsHandler.cpp deleted file mode 100644 index 78e50e673af0..000000000000 --- a/source/Plugins/SystemRuntime/MacOSX/AppleGetPendingItemsHandler.cpp +++ /dev/null @@ -1,406 +0,0 @@ -//===-- AppleGetPendingItemsHandler.cpp -------------------------------*- C++ -//-*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "AppleGetPendingItemsHandler.h" - - -#include "lldb/Core/Module.h" -#include "lldb/Core/Value.h" -#include "lldb/Expression/DiagnosticManager.h" -#include "lldb/Expression/FunctionCaller.h" -#include "lldb/Expression/UtilityFunction.h" -#include "lldb/Symbol/ClangASTContext.h" -#include "lldb/Symbol/Symbol.h" -#include "lldb/Target/ExecutionContext.h" -#include "lldb/Target/Process.h" -#include "lldb/Target/Target.h" -#include "lldb/Target/Thread.h" -#include "lldb/Utility/ConstString.h" -#include "lldb/Utility/Log.h" -#include "lldb/Utility/StreamString.h" - -using namespace lldb; -using namespace lldb_private; - -const char *AppleGetPendingItemsHandler::g_get_pending_items_function_name = - "__lldb_backtrace_recording_get_pending_items"; -const char *AppleGetPendingItemsHandler::g_get_pending_items_function_code = - " \n\ -extern \"C\" \n\ -{ \n\ - /* \n\ - * mach defines \n\ - */ \n\ - \n\ - typedef unsigned int uint32_t; \n\ - typedef unsigned long long uint64_t; \n\ - typedef uint32_t mach_port_t; \n\ - typedef mach_port_t vm_map_t; \n\ - typedef int kern_return_t; \n\ - typedef uint64_t mach_vm_address_t; \n\ - typedef uint64_t mach_vm_size_t; \n\ - \n\ - mach_port_t mach_task_self (); \n\ - kern_return_t mach_vm_deallocate (vm_map_t target, mach_vm_address_t address, mach_vm_size_t size); \n\ - \n\ - /* \n\ - * libBacktraceRecording defines \n\ - */ \n\ - \n\ - typedef uint32_t queue_list_scope_t; \n\ - typedef void *dispatch_queue_t; \n\ - typedef void *introspection_dispatch_queue_info_t; \n\ - typedef void *introspection_dispatch_item_info_ref; \n\ - \n\ - extern uint64_t __introspection_dispatch_queue_get_pending_items (dispatch_queue_t queue, \n\ - introspection_dispatch_item_info_ref *returned_queues_buffer, \n\ - uint64_t *returned_queues_buffer_size); \n\ - extern int printf(const char *format, ...); \n\ - \n\ - /* \n\ - * return type define \n\ - */ \n\ - \n\ - struct get_pending_items_return_values \n\ - { \n\ - uint64_t pending_items_buffer_ptr; /* the address of the items buffer from libBacktraceRecording */ \n\ - uint64_t pending_items_buffer_size; /* the size of the items buffer from libBacktraceRecording */ \n\ - uint64_t count; /* the number of items included in the queues buffer */ \n\ - }; \n\ - \n\ - void __lldb_backtrace_recording_get_pending_items \n\ - (struct get_pending_items_return_values *return_buffer, \n\ - int debug, \n\ - uint64_t /* dispatch_queue_t */ queue, \n\ - void *page_to_free, \n\ - uint64_t page_to_free_size) \n\ -{ \n\ - if (debug) \n\ - printf (\"entering get_pending_items with args return_buffer == %p, debug == %d, queue == 0x%llx, page_to_free == %p, page_to_free_size == 0x%llx\\n\", return_buffer, debug, queue, page_to_free, page_to_free_size); \n\ - if (page_to_free != 0) \n\ - { \n\ - mach_vm_deallocate (mach_task_self(), (mach_vm_address_t) page_to_free, (mach_vm_size_t) page_to_free_size); \n\ - } \n\ - \n\ - return_buffer->count = __introspection_dispatch_queue_get_pending_items ( \n\ - (void*) queue, \n\ - (void**)&return_buffer->pending_items_buffer_ptr, \n\ - &return_buffer->pending_items_buffer_size); \n\ - if (debug) \n\ - printf(\"result was count %lld\\n\", return_buffer->count); \n\ -} \n\ -} \n\ -"; - -AppleGetPendingItemsHandler::AppleGetPendingItemsHandler(Process *process) - : m_process(process), m_get_pending_items_impl_code(), - m_get_pending_items_function_mutex(), - m_get_pending_items_return_buffer_addr(LLDB_INVALID_ADDRESS), - m_get_pending_items_retbuffer_mutex() {} - -AppleGetPendingItemsHandler::~AppleGetPendingItemsHandler() {} - -void AppleGetPendingItemsHandler::Detach() { - if (m_process && m_process->IsAlive() && - m_get_pending_items_return_buffer_addr != LLDB_INVALID_ADDRESS) { - std::unique_lock<std::mutex> lock(m_get_pending_items_retbuffer_mutex, - std::defer_lock); - lock.try_lock(); // Even if we don't get the lock, deallocate the buffer - m_process->DeallocateMemory(m_get_pending_items_return_buffer_addr); - } -} - -// Compile our __lldb_backtrace_recording_get_pending_items() function (from -// the source above in g_get_pending_items_function_code) if we don't find that -// function in the inferior already with USE_BUILTIN_FUNCTION defined. (e.g. -// this would be the case for testing.) -// -// Insert the __lldb_backtrace_recording_get_pending_items into the inferior -// process if needed. -// -// Write the get_pending_items_arglist into the inferior's memory space to -// prepare for the call. -// -// Returns the address of the arguments written down in the inferior process, -// which can be used to make the function call. - -lldb::addr_t AppleGetPendingItemsHandler::SetupGetPendingItemsFunction( - Thread &thread, ValueList &get_pending_items_arglist) { - ThreadSP thread_sp(thread.shared_from_this()); - ExecutionContext exe_ctx(thread_sp); - DiagnosticManager diagnostics; - Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_SYSTEM_RUNTIME)); - - lldb::addr_t args_addr = LLDB_INVALID_ADDRESS; - FunctionCaller *get_pending_items_caller = nullptr; - - // Scope for mutex locker: - { - std::lock_guard<std::mutex> guard(m_get_pending_items_function_mutex); - - // First stage is to make the ClangUtility to hold our injected function: - - if (!m_get_pending_items_impl_code.get()) { - if (g_get_pending_items_function_code != NULL) { - Status error; - m_get_pending_items_impl_code.reset( - exe_ctx.GetTargetRef().GetUtilityFunctionForLanguage( - g_get_pending_items_function_code, eLanguageTypeObjC, - g_get_pending_items_function_name, error)); - if (error.Fail()) { - if (log) - log->Printf("Failed to get UtilityFunction for pending-items " - "introspection: %s.", - error.AsCString()); - return args_addr; - } - - if (!m_get_pending_items_impl_code->Install(diagnostics, exe_ctx)) { - if (log) { - log->Printf("Failed to install pending-items introspection."); - diagnostics.Dump(log); - } - m_get_pending_items_impl_code.reset(); - return args_addr; - } - } else { - if (log) - log->Printf("No pending-items introspection code found."); - return LLDB_INVALID_ADDRESS; - } - - // Next make the runner function for our implementation utility function. - Status error; - ClangASTContext *clang_ast_context = - thread.GetProcess()->GetTarget().GetScratchClangASTContext(); - CompilerType get_pending_items_return_type = - clang_ast_context->GetBasicType(eBasicTypeVoid).GetPointerType(); - get_pending_items_caller = - m_get_pending_items_impl_code->MakeFunctionCaller( - get_pending_items_return_type, get_pending_items_arglist, - thread_sp, error); - if (error.Fail() || get_pending_items_caller == nullptr) { - if (log) - log->Printf("Failed to install pending-items introspection function " - "caller: %s.", - error.AsCString()); - m_get_pending_items_impl_code.reset(); - return args_addr; - } - } - } - - diagnostics.Clear(); - - if (get_pending_items_caller == nullptr) { - if (log) - log->Printf("Failed to get get_pending_items_caller."); - return LLDB_INVALID_ADDRESS; - } - - // 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 (!get_pending_items_caller->WriteFunctionArguments( - exe_ctx, args_addr, get_pending_items_arglist, diagnostics)) { - if (log) { - log->Printf("Error writing pending-items function arguments."); - diagnostics.Dump(log); - } - - return args_addr; - } - - return args_addr; -} - -AppleGetPendingItemsHandler::GetPendingItemsReturnInfo -AppleGetPendingItemsHandler::GetPendingItems(Thread &thread, addr_t queue, - addr_t page_to_free, - uint64_t page_to_free_size, - Status &error) { - lldb::StackFrameSP thread_cur_frame = thread.GetStackFrameAtIndex(0); - ProcessSP process_sp(thread.CalculateProcess()); - TargetSP target_sp(thread.CalculateTarget()); - ClangASTContext *clang_ast_context = target_sp->GetScratchClangASTContext(); - Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_SYSTEM_RUNTIME)); - - GetPendingItemsReturnInfo return_value; - return_value.items_buffer_ptr = LLDB_INVALID_ADDRESS; - return_value.items_buffer_size = 0; - return_value.count = 0; - - error.Clear(); - - if (!thread.SafeToCallFunctions()) { - if (log) - log->Printf("Not safe to call functions on thread 0x%" PRIx64, - thread.GetID()); - error.SetErrorString("Not safe to call functions on this thread."); - return return_value; - } - - // Set up the arguments for a call to - - // struct get_pending_items_return_values - // { - // uint64_t pending_items_buffer_ptr; /* the address of the items - // buffer from libBacktraceRecording */ - // uint64_t pending_items_buffer_size; /* the size of the items buffer - // from libBacktraceRecording */ - // uint64_t count; /* the number of items included in the - // queues buffer */ - // }; - // - // void __lldb_backtrace_recording_get_pending_items - // (struct - // get_pending_items_return_values - // *return_buffer, - // int debug, - // uint64_t /* dispatch_queue_t */ - // queue - // void *page_to_free, - // uint64_t page_to_free_size) - - // Where the return_buffer argument points to a 24 byte region of memory - // already allocated by lldb in the inferior process. - - CompilerType clang_void_ptr_type = - clang_ast_context->GetBasicType(eBasicTypeVoid).GetPointerType(); - Value return_buffer_ptr_value; - return_buffer_ptr_value.SetValueType(Value::eValueTypeScalar); - return_buffer_ptr_value.SetCompilerType(clang_void_ptr_type); - - CompilerType clang_int_type = clang_ast_context->GetBasicType(eBasicTypeInt); - Value debug_value; - debug_value.SetValueType(Value::eValueTypeScalar); - debug_value.SetCompilerType(clang_int_type); - - CompilerType clang_uint64_type = - clang_ast_context->GetBasicType(eBasicTypeUnsignedLongLong); - Value queue_value; - queue_value.SetValueType(Value::eValueTypeScalar); - queue_value.SetCompilerType(clang_uint64_type); - - Value page_to_free_value; - page_to_free_value.SetValueType(Value::eValueTypeScalar); - page_to_free_value.SetCompilerType(clang_void_ptr_type); - - Value page_to_free_size_value; - page_to_free_size_value.SetValueType(Value::eValueTypeScalar); - page_to_free_size_value.SetCompilerType(clang_uint64_type); - - std::lock_guard<std::mutex> guard(m_get_pending_items_retbuffer_mutex); - if (m_get_pending_items_return_buffer_addr == LLDB_INVALID_ADDRESS) { - addr_t bufaddr = process_sp->AllocateMemory( - 32, ePermissionsReadable | ePermissionsWritable, error); - if (!error.Success() || bufaddr == LLDB_INVALID_ADDRESS) { - if (log) - log->Printf("Failed to allocate memory for return buffer for get " - "current queues func call"); - return return_value; - } - m_get_pending_items_return_buffer_addr = bufaddr; - } - - ValueList argument_values; - - return_buffer_ptr_value.GetScalar() = m_get_pending_items_return_buffer_addr; - argument_values.PushValue(return_buffer_ptr_value); - - debug_value.GetScalar() = 0; - argument_values.PushValue(debug_value); - - queue_value.GetScalar() = queue; - argument_values.PushValue(queue_value); - - if (page_to_free != LLDB_INVALID_ADDRESS) - page_to_free_value.GetScalar() = page_to_free; - else - page_to_free_value.GetScalar() = 0; - argument_values.PushValue(page_to_free_value); - - page_to_free_size_value.GetScalar() = page_to_free_size; - argument_values.PushValue(page_to_free_size_value); - - addr_t args_addr = SetupGetPendingItemsFunction(thread, argument_values); - - DiagnosticManager diagnostics; - ExecutionContext exe_ctx; - FunctionCaller *get_pending_items_caller = - m_get_pending_items_impl_code->GetFunctionCaller(); - - EvaluateExpressionOptions options; - options.SetUnwindOnError(true); - options.SetIgnoreBreakpoints(true); - options.SetStopOthers(true); - options.SetTimeout(std::chrono::milliseconds(500)); - options.SetTryAllThreads(false); - options.SetIsForUtilityExpr(true); - thread.CalculateExecutionContext(exe_ctx); - - if (get_pending_items_caller == NULL) { - error.SetErrorString("Unable to compile function to call " - "__introspection_dispatch_queue_get_pending_items"); - return return_value; - } - - ExpressionResults func_call_ret; - Value results; - func_call_ret = get_pending_items_caller->ExecuteFunction( - exe_ctx, &args_addr, options, diagnostics, results); - if (func_call_ret != eExpressionCompleted || !error.Success()) { - if (log) - log->Printf("Unable to call " - "__introspection_dispatch_queue_get_pending_items(), got " - "ExpressionResults %d, error contains %s", - func_call_ret, error.AsCString("")); - error.SetErrorString("Unable to call " - "__introspection_dispatch_queue_get_pending_items() " - "for list of queues"); - return return_value; - } - - return_value.items_buffer_ptr = m_process->ReadUnsignedIntegerFromMemory( - m_get_pending_items_return_buffer_addr, 8, LLDB_INVALID_ADDRESS, error); - if (!error.Success() || - return_value.items_buffer_ptr == LLDB_INVALID_ADDRESS) { - return_value.items_buffer_ptr = LLDB_INVALID_ADDRESS; - return return_value; - } - - return_value.items_buffer_size = m_process->ReadUnsignedIntegerFromMemory( - m_get_pending_items_return_buffer_addr + 8, 8, 0, error); - - if (!error.Success()) { - return_value.items_buffer_ptr = LLDB_INVALID_ADDRESS; - return return_value; - } - - return_value.count = m_process->ReadUnsignedIntegerFromMemory( - m_get_pending_items_return_buffer_addr + 16, 8, 0, error); - if (!error.Success()) { - return_value.items_buffer_ptr = LLDB_INVALID_ADDRESS; - return return_value; - } - - if (log) - log->Printf("AppleGetPendingItemsHandler called " - "__introspection_dispatch_queue_get_pending_items " - "(page_to_free == 0x%" PRIx64 ", size = %" PRId64 - "), returned page is at 0x%" PRIx64 ", size %" PRId64 - ", count = %" PRId64, - page_to_free, page_to_free_size, return_value.items_buffer_ptr, - return_value.items_buffer_size, return_value.count); - - return return_value; -} diff --git a/source/Plugins/SystemRuntime/MacOSX/AppleGetPendingItemsHandler.h b/source/Plugins/SystemRuntime/MacOSX/AppleGetPendingItemsHandler.h deleted file mode 100644 index d35a72c2ff43..000000000000 --- a/source/Plugins/SystemRuntime/MacOSX/AppleGetPendingItemsHandler.h +++ /dev/null @@ -1,120 +0,0 @@ -//===-- AppleGetPendingItemsHandler.h ----------------------------*- C++ -//-*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef lldb_AppleGetPendingItemsHandler_h_ -#define lldb_AppleGetPendingItemsHandler_h_ - -#include <map> -#include <mutex> -#include <vector> - -#include "lldb/Symbol/CompilerType.h" -#include "lldb/Utility/Status.h" -#include "lldb/lldb-public.h" - -// This class will insert a UtilityFunction into the inferior process for -// calling libBacktraceRecording's -// __introspection_dispatch_queue_get_pending_items() -// function. The function in the inferior will return a struct by value -// with these members: -// -// struct get_pending_items_return_values -// { -// introspection_dispatch_item_info_ref *items_buffer; -// uint64_t items_buffer_size; -// uint64_t count; -// }; -// -// The items_buffer pointer is an address in the inferior program's address -// space (items_buffer_size in size) which must be mach_vm_deallocate'd by -// lldb. count is the number of items that were stored in the buffer. -// -// The AppleGetPendingItemsHandler object should persist so that the -// UtilityFunction -// can be reused multiple times. - -namespace lldb_private { - -class AppleGetPendingItemsHandler { -public: - AppleGetPendingItemsHandler(lldb_private::Process *process); - - ~AppleGetPendingItemsHandler(); - - struct GetPendingItemsReturnInfo { - lldb::addr_t items_buffer_ptr; /* the address of the pending items buffer - from libBacktraceRecording */ - lldb::addr_t - items_buffer_size; /* the size of the pending items buffer from - libBacktraceRecording */ - uint64_t count; /* the number of pending items included in the buffer */ - - GetPendingItemsReturnInfo() - : items_buffer_ptr(LLDB_INVALID_ADDRESS), items_buffer_size(0), - count(0) {} - }; - - //---------------------------------------------------------- - /// Get the list of pending items for a given queue via a call to - /// __introspection_dispatch_queue_get_pending_items. If there's a page of - /// memory that needs to be freed, pass in the address and size and it will - /// be freed before getting the list of queues. - /// - /// @param [in] thread - /// The thread to run this plan on. - /// - /// @param [in] queue - /// The dispatch_queue_t value for the queue of interest. - /// - /// @param [in] page_to_free - /// An address of an inferior process vm page that needs to be - /// deallocated, - /// LLDB_INVALID_ADDRESS if this is not needed. - /// - /// @param [in] page_to_free_size - /// The size of the vm page that needs to be deallocated if an address was - /// passed in to page_to_free. - /// - /// @param [out] error - /// This object will be updated with the error status / error string from - /// any failures encountered. - /// - /// @returns - /// The result of the inferior function call execution. If there was a - /// failure of any kind while getting - /// the information, the items_buffer_ptr value will be - /// LLDB_INVALID_ADDRESS. - //---------------------------------------------------------- - GetPendingItemsReturnInfo GetPendingItems(Thread &thread, lldb::addr_t queue, - lldb::addr_t page_to_free, - uint64_t page_to_free_size, - lldb_private::Status &error); - - void Detach(); - -private: - lldb::addr_t - SetupGetPendingItemsFunction(Thread &thread, - ValueList &get_pending_items_arglist); - - static const char *g_get_pending_items_function_name; - static const char *g_get_pending_items_function_code; - - lldb_private::Process *m_process; - std::unique_ptr<UtilityFunction> m_get_pending_items_impl_code; - std::mutex m_get_pending_items_function_mutex; - - lldb::addr_t m_get_pending_items_return_buffer_addr; - std::mutex m_get_pending_items_retbuffer_mutex; -}; - -} // using namespace lldb_private - -#endif // lldb_AppleGetPendingItemsHandler_h_ diff --git a/source/Plugins/SystemRuntime/MacOSX/AppleGetQueuesHandler.cpp b/source/Plugins/SystemRuntime/MacOSX/AppleGetQueuesHandler.cpp deleted file mode 100644 index 245ff6742b43..000000000000 --- a/source/Plugins/SystemRuntime/MacOSX/AppleGetQueuesHandler.cpp +++ /dev/null @@ -1,403 +0,0 @@ -//===-- AppleGetQueuesHandler.cpp -------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "AppleGetQueuesHandler.h" - -#include "lldb/Core/Module.h" -#include "lldb/Core/Value.h" -#include "lldb/Expression/DiagnosticManager.h" -#include "lldb/Expression/FunctionCaller.h" -#include "lldb/Expression/UtilityFunction.h" -#include "lldb/Symbol/ClangASTContext.h" -#include "lldb/Symbol/Symbol.h" -#include "lldb/Target/ExecutionContext.h" -#include "lldb/Target/Process.h" -#include "lldb/Target/Target.h" -#include "lldb/Target/Thread.h" -#include "lldb/Utility/ConstString.h" -#include "lldb/Utility/Log.h" -#include "lldb/Utility/StreamString.h" - -using namespace lldb; -using namespace lldb_private; - -const char *AppleGetQueuesHandler::g_get_current_queues_function_name = - "__lldb_backtrace_recording_get_current_queues"; -const char *AppleGetQueuesHandler::g_get_current_queues_function_code = - " \n\ -extern \"C\" \n\ -{ \n\ - /* \n\ - * mach defines \n\ - */ \n\ - \n\ - typedef unsigned int uint32_t; \n\ - typedef unsigned long long uint64_t; \n\ - typedef uint32_t mach_port_t; \n\ - typedef mach_port_t vm_map_t; \n\ - typedef int kern_return_t; \n\ - typedef uint64_t mach_vm_address_t; \n\ - typedef uint64_t mach_vm_size_t; \n\ - \n\ - mach_port_t mach_task_self (); \n\ - kern_return_t mach_vm_deallocate (vm_map_t target, mach_vm_address_t address, mach_vm_size_t size); \n\ - \n\ - /* \n\ - * libBacktraceRecording defines \n\ - */ \n\ - \n\ - typedef uint32_t queue_list_scope_t; \n\ - typedef void *introspection_dispatch_queue_info_t; \n\ - \n\ - extern uint64_t __introspection_dispatch_get_queues (queue_list_scope_t scope, \n\ - introspection_dispatch_queue_info_t *returned_queues_buffer, \n\ - uint64_t *returned_queues_buffer_size); \n\ - extern int printf(const char *format, ...); \n\ - \n\ - /* \n\ - * return type define \n\ - */ \n\ - \n\ - struct get_current_queues_return_values \n\ - { \n\ - uint64_t queues_buffer_ptr; /* the address of the queues buffer from libBacktraceRecording */ \n\ - uint64_t queues_buffer_size; /* the size of the queues buffer from libBacktraceRecording */ \n\ - uint64_t count; /* the number of queues included in the queues buffer */ \n\ - }; \n\ - \n\ - void __lldb_backtrace_recording_get_current_queues \n\ - (struct get_current_queues_return_values *return_buffer, \n\ - int debug, \n\ - void *page_to_free, \n\ - uint64_t page_to_free_size) \n\ -{ \n\ - if (debug) \n\ - printf (\"entering get_current_queues with args %p, %d, 0x%p, 0x%llx\\n\", return_buffer, debug, page_to_free, page_to_free_size); \n\ - if (page_to_free != 0) \n\ - { \n\ - mach_vm_deallocate (mach_task_self(), (mach_vm_address_t) page_to_free, (mach_vm_size_t) page_to_free_size); \n\ - } \n\ - \n\ - return_buffer->count = __introspection_dispatch_get_queues ( \n\ - /* QUEUES_WITH_ANY_ITEMS */ 2, \n\ - (void**)&return_buffer->queues_buffer_ptr, \n\ - &return_buffer->queues_buffer_size); \n\ - if (debug) \n\ - printf(\"result was count %lld\\n\", return_buffer->count); \n\ -} \n\ -} \n\ -"; - -AppleGetQueuesHandler::AppleGetQueuesHandler(Process *process) - : m_process(process), m_get_queues_impl_code_up(), - m_get_queues_function_mutex(), - m_get_queues_return_buffer_addr(LLDB_INVALID_ADDRESS), - m_get_queues_retbuffer_mutex() {} - -AppleGetQueuesHandler::~AppleGetQueuesHandler() {} - -void AppleGetQueuesHandler::Detach() { - - if (m_process && m_process->IsAlive() && - m_get_queues_return_buffer_addr != LLDB_INVALID_ADDRESS) { - std::unique_lock<std::mutex> lock(m_get_queues_retbuffer_mutex, - std::defer_lock); - lock.try_lock(); // Even if we don't get the lock, deallocate the buffer - m_process->DeallocateMemory(m_get_queues_return_buffer_addr); - } -} - -// Construct a CompilerType for the structure that -// g_get_current_queues_function_code will return by value so we can extract -// the fields after performing the function call. i.e. we are getting this -// struct returned to us: -// -// struct get_current_queues_return_values -// { -// introspection_dispatch_queue_info_t *queues_buffer; -// uint64_t queues_buffer_size; -// uint64_t count; -// }; - -// Compile our __lldb_backtrace_recording_get_current_queues() function (from -// the source above in g_get_current_queues_function_code) if we don't find -// that function in the inferior already with USE_BUILTIN_FUNCTION defined. -// (e.g. this would be the case for testing.) -// -// Insert the __lldb_backtrace_recording_get_current_queues into the inferior -// process if needed. -// -// Write the get_queues_arglist into the inferior's memory space to prepare for -// the call. -// -// Returns the address of the arguments written down in the inferior process, -// which can be used to make the function call. - -lldb::addr_t -AppleGetQueuesHandler::SetupGetQueuesFunction(Thread &thread, - ValueList &get_queues_arglist) { - ThreadSP thread_sp(thread.shared_from_this()); - ExecutionContext exe_ctx(thread_sp); - - Address impl_code_address; - DiagnosticManager diagnostics; - Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_SYSTEM_RUNTIME)); - lldb::addr_t args_addr = LLDB_INVALID_ADDRESS; - - FunctionCaller *get_queues_caller = nullptr; - - // Scope for mutex locker: - { - std::lock_guard<std::mutex> guard(m_get_queues_function_mutex); - - // First stage is to make the ClangUtility to hold our injected function: - - if (!m_get_queues_impl_code_up.get()) { - if (g_get_current_queues_function_code != NULL) { - Status error; - m_get_queues_impl_code_up.reset( - exe_ctx.GetTargetRef().GetUtilityFunctionForLanguage( - g_get_current_queues_function_code, eLanguageTypeC, - g_get_current_queues_function_name, error)); - if (error.Fail()) { - if (log) - log->Printf( - "Failed to get UtilityFunction for queues introspection: %s.", - error.AsCString()); - return args_addr; - } - - if (!m_get_queues_impl_code_up->Install(diagnostics, exe_ctx)) { - if (log) { - log->Printf("Failed to install queues introspection"); - diagnostics.Dump(log); - } - m_get_queues_impl_code_up.reset(); - return args_addr; - } - } else { - if (log) { - log->Printf("No queues introspection code found."); - diagnostics.Dump(log); - } - return LLDB_INVALID_ADDRESS; - } - } - - // Next make the runner function for our implementation utility function. - ClangASTContext *clang_ast_context = - thread.GetProcess()->GetTarget().GetScratchClangASTContext(); - CompilerType get_queues_return_type = - clang_ast_context->GetBasicType(eBasicTypeVoid).GetPointerType(); - Status error; - get_queues_caller = m_get_queues_impl_code_up->MakeFunctionCaller( - get_queues_return_type, get_queues_arglist, thread_sp, error); - if (error.Fail() || get_queues_caller == nullptr) { - if (log) - log->Printf( - "Could not get function caller for get-queues function: %s.", - error.AsCString()); - return args_addr; - } - } - - 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 (!get_queues_caller->WriteFunctionArguments( - exe_ctx, args_addr, get_queues_arglist, diagnostics)) { - if (log) { - log->Printf("Error writing get-queues function arguments."); - diagnostics.Dump(log); - } - return args_addr; - } - - return args_addr; -} - -AppleGetQueuesHandler::GetQueuesReturnInfo -AppleGetQueuesHandler::GetCurrentQueues(Thread &thread, addr_t page_to_free, - uint64_t page_to_free_size, - Status &error) { - lldb::StackFrameSP thread_cur_frame = thread.GetStackFrameAtIndex(0); - ProcessSP process_sp(thread.CalculateProcess()); - TargetSP target_sp(thread.CalculateTarget()); - ClangASTContext *clang_ast_context = target_sp->GetScratchClangASTContext(); - Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_SYSTEM_RUNTIME)); - - GetQueuesReturnInfo return_value; - return_value.queues_buffer_ptr = LLDB_INVALID_ADDRESS; - return_value.queues_buffer_size = 0; - return_value.count = 0; - - error.Clear(); - - if (!thread.SafeToCallFunctions()) { - if (log) - log->Printf("Not safe to call functions on thread 0x%" PRIx64, - thread.GetID()); - error.SetErrorString("Not safe to call functions on this thread."); - return return_value; - } - - // Set up the arguments for a call to - - // struct get_current_queues_return_values - // { - // uint64_t queues_buffer_ptr; /* the address of the queues buffer from - // libBacktraceRecording */ - // uint64_t queues_buffer_size; /* the size of the queues buffer from - // libBacktraceRecording */ - // uint64_t count; /* the number of queues included in the - // queues buffer */ - // }; - // - // void - // __lldb_backtrace_recording_get_current_queues - // (struct - // get_current_queues_return_values - // *return_buffer, - // void *page_to_free, - // uint64_t page_to_free_size); - - // Where the return_buffer argument points to a 24 byte region of memory - // already allocated by lldb in the inferior process. - - CompilerType clang_void_ptr_type = - clang_ast_context->GetBasicType(eBasicTypeVoid).GetPointerType(); - Value return_buffer_ptr_value; - return_buffer_ptr_value.SetValueType(Value::eValueTypeScalar); - return_buffer_ptr_value.SetCompilerType(clang_void_ptr_type); - - CompilerType clang_int_type = clang_ast_context->GetBasicType(eBasicTypeInt); - Value debug_value; - debug_value.SetValueType(Value::eValueTypeScalar); - debug_value.SetCompilerType(clang_int_type); - - Value page_to_free_value; - page_to_free_value.SetValueType(Value::eValueTypeScalar); - page_to_free_value.SetCompilerType(clang_void_ptr_type); - - CompilerType clang_uint64_type = - clang_ast_context->GetBasicType(eBasicTypeUnsignedLongLong); - Value page_to_free_size_value; - page_to_free_size_value.SetValueType(Value::eValueTypeScalar); - page_to_free_size_value.SetCompilerType(clang_uint64_type); - - std::lock_guard<std::mutex> guard(m_get_queues_retbuffer_mutex); - if (m_get_queues_return_buffer_addr == LLDB_INVALID_ADDRESS) { - addr_t bufaddr = process_sp->AllocateMemory( - 32, ePermissionsReadable | ePermissionsWritable, error); - if (!error.Success() || bufaddr == LLDB_INVALID_ADDRESS) { - if (log) - log->Printf("Failed to allocate memory for return buffer for get " - "current queues func call"); - return return_value; - } - m_get_queues_return_buffer_addr = bufaddr; - } - - ValueList argument_values; - - return_buffer_ptr_value.GetScalar() = m_get_queues_return_buffer_addr; - argument_values.PushValue(return_buffer_ptr_value); - - debug_value.GetScalar() = 0; - argument_values.PushValue(debug_value); - - if (page_to_free != LLDB_INVALID_ADDRESS) - page_to_free_value.GetScalar() = page_to_free; - else - page_to_free_value.GetScalar() = 0; - argument_values.PushValue(page_to_free_value); - - page_to_free_size_value.GetScalar() = page_to_free_size; - argument_values.PushValue(page_to_free_size_value); - - addr_t args_addr = SetupGetQueuesFunction(thread, argument_values); - - if (!m_get_queues_impl_code_up) { - error.SetErrorString( - "Unable to compile __introspection_dispatch_get_queues."); - return return_value; - } - - FunctionCaller *get_queues_caller = - m_get_queues_impl_code_up->GetFunctionCaller(); - - if (get_queues_caller == NULL) { - error.SetErrorString( - "Unable to get caller for call __introspection_dispatch_get_queues"); - return return_value; - } - - DiagnosticManager diagnostics; - ExecutionContext exe_ctx; - EvaluateExpressionOptions options; - options.SetUnwindOnError(true); - options.SetIgnoreBreakpoints(true); - options.SetStopOthers(true); - options.SetTimeout(std::chrono::milliseconds(500)); - options.SetTryAllThreads(false); - options.SetIsForUtilityExpr(true); - thread.CalculateExecutionContext(exe_ctx); - - ExpressionResults func_call_ret; - Value results; - func_call_ret = get_queues_caller->ExecuteFunction( - exe_ctx, &args_addr, options, diagnostics, results); - if (func_call_ret != eExpressionCompleted || !error.Success()) { - if (log) - log->Printf("Unable to call introspection_get_dispatch_queues(), got " - "ExpressionResults %d, error contains %s", - func_call_ret, error.AsCString("")); - error.SetErrorString("Unable to call introspection_get_dispatch_queues() " - "for list of queues"); - return return_value; - } - - return_value.queues_buffer_ptr = m_process->ReadUnsignedIntegerFromMemory( - m_get_queues_return_buffer_addr, 8, LLDB_INVALID_ADDRESS, error); - if (!error.Success() || - return_value.queues_buffer_ptr == LLDB_INVALID_ADDRESS) { - return_value.queues_buffer_ptr = LLDB_INVALID_ADDRESS; - return return_value; - } - - return_value.queues_buffer_size = m_process->ReadUnsignedIntegerFromMemory( - m_get_queues_return_buffer_addr + 8, 8, 0, error); - - if (!error.Success()) { - return_value.queues_buffer_ptr = LLDB_INVALID_ADDRESS; - return return_value; - } - - return_value.count = m_process->ReadUnsignedIntegerFromMemory( - m_get_queues_return_buffer_addr + 16, 8, 0, error); - if (!error.Success()) { - return_value.queues_buffer_ptr = LLDB_INVALID_ADDRESS; - return return_value; - } - - if (log) - log->Printf("AppleGetQueuesHandler called " - "__introspection_dispatch_get_queues (page_to_free == " - "0x%" PRIx64 ", size = %" PRId64 - "), returned page is at 0x%" PRIx64 ", size %" PRId64 - ", count = %" PRId64, - page_to_free, page_to_free_size, return_value.queues_buffer_ptr, - return_value.queues_buffer_size, return_value.count); - - return return_value; -} diff --git a/source/Plugins/SystemRuntime/MacOSX/AppleGetQueuesHandler.h b/source/Plugins/SystemRuntime/MacOSX/AppleGetQueuesHandler.h deleted file mode 100644 index 0d8e4dc64a68..000000000000 --- a/source/Plugins/SystemRuntime/MacOSX/AppleGetQueuesHandler.h +++ /dev/null @@ -1,112 +0,0 @@ -//===-- AppleGetQueuesHandler.h ----------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef lldb_AppleGetQueuesHandler_h_ -#define lldb_AppleGetQueuesHandler_h_ - -#include <map> -#include <mutex> -#include <vector> - -#include "lldb/Symbol/CompilerType.h" -#include "lldb/Utility/Status.h" -#include "lldb/lldb-public.h" - -// This class will insert a UtilityFunction into the inferior process for -// calling libBacktraceRecording's introspection_get_dispatch_queues() -// function. The function in the inferior will return a struct by value -// with these members: -// -// struct get_current_queues_return_values -// { -// introspection_dispatch_queue_info_t *queues_buffer; -// uint64_t queues_buffer_size; -// uint64_t count; -// }; -// -// The queues_buffer pointer is an address in the inferior program's address -// space (queues_buffer_size in size) which must be mach_vm_deallocate'd by -// lldb. count is the number of queues that were stored in the buffer. -// -// The AppleGetQueuesHandler object should persist so that the UtilityFunction -// can be reused multiple times. - -namespace lldb_private { - -class AppleGetQueuesHandler { -public: - AppleGetQueuesHandler(lldb_private::Process *process); - - ~AppleGetQueuesHandler(); - - struct GetQueuesReturnInfo { - lldb::addr_t queues_buffer_ptr; /* the address of the queues buffer from - libBacktraceRecording */ - lldb::addr_t queues_buffer_size; /* the size of the queues buffer from - libBacktraceRecording */ - uint64_t count; /* the number of queues included in the queues buffer */ - - GetQueuesReturnInfo() - : queues_buffer_ptr(LLDB_INVALID_ADDRESS), queues_buffer_size(0), - count(0) {} - }; - - //---------------------------------------------------------- - /// Get the list of queues that exist (with any active or pending items) via - /// a call to introspection_get_dispatch_queues(). If there's a page of - /// memory that needs to be freed, pass in the address and size and it will - /// be freed before getting the list of queues. - /// - /// @param [in] thread - /// The thread to run this plan on. - /// - /// @param [in] page_to_free - /// An address of an inferior process vm page that needs to be - /// deallocated, - /// LLDB_INVALID_ADDRESS if this is not needed. - /// - /// @param [in] page_to_free_size - /// The size of the vm page that needs to be deallocated if an address was - /// passed in to page_to_free. - /// - /// @param [out] error - /// This object will be updated with the error status / error string from - /// any failures encountered. - /// - /// @returns - /// The result of the inferior function call execution. If there was a - /// failure of any kind while getting - /// the information, the queues_buffer_ptr value will be - /// LLDB_INVALID_ADDRESS. - //---------------------------------------------------------- - GetQueuesReturnInfo GetCurrentQueues(Thread &thread, - lldb::addr_t page_to_free, - uint64_t page_to_free_size, - lldb_private::Status &error); - - void Detach(); - -private: - lldb::addr_t SetupGetQueuesFunction(Thread &thread, - ValueList &get_queues_arglist); - - static const char *g_get_current_queues_function_name; - static const char *g_get_current_queues_function_code; - - lldb_private::Process *m_process; - std::unique_ptr<UtilityFunction> m_get_queues_impl_code_up; - std::mutex m_get_queues_function_mutex; - - lldb::addr_t m_get_queues_return_buffer_addr; - std::mutex m_get_queues_retbuffer_mutex; -}; - -} // using namespace lldb_private - -#endif // lldb_AppleGetQueuesHandler_h_ diff --git a/source/Plugins/SystemRuntime/MacOSX/AppleGetThreadItemInfoHandler.cpp b/source/Plugins/SystemRuntime/MacOSX/AppleGetThreadItemInfoHandler.cpp deleted file mode 100644 index ede81333a3e6..000000000000 --- a/source/Plugins/SystemRuntime/MacOSX/AppleGetThreadItemInfoHandler.cpp +++ /dev/null @@ -1,410 +0,0 @@ -//===-- AppleGetThreadItemInfoHandler.cpp -------------------------------*- C++ -//-*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "AppleGetThreadItemInfoHandler.h" - - -#include "lldb/Core/Module.h" -#include "lldb/Core/Value.h" -#include "lldb/Expression/DiagnosticManager.h" -#include "lldb/Expression/Expression.h" -#include "lldb/Expression/FunctionCaller.h" -#include "lldb/Expression/UtilityFunction.h" -#include "lldb/Symbol/ClangASTContext.h" -#include "lldb/Symbol/Symbol.h" -#include "lldb/Target/ExecutionContext.h" -#include "lldb/Target/Process.h" -#include "lldb/Target/StackFrame.h" -#include "lldb/Target/Target.h" -#include "lldb/Target/Thread.h" -#include "lldb/Utility/ConstString.h" -#include "lldb/Utility/Log.h" -#include "lldb/Utility/StreamString.h" -#include "lldb/lldb-private.h" - -using namespace lldb; -using namespace lldb_private; - -const char - *AppleGetThreadItemInfoHandler::g_get_thread_item_info_function_name = - "__lldb_backtrace_recording_get_thread_item_info"; -const char - *AppleGetThreadItemInfoHandler::g_get_thread_item_info_function_code = - " \n\ -extern \"C\" \n\ -{ \n\ - /* \n\ - * mach defines \n\ - */ \n\ - \n\ - typedef unsigned int uint32_t; \n\ - typedef unsigned long long uint64_t; \n\ - typedef uint32_t mach_port_t; \n\ - typedef mach_port_t vm_map_t; \n\ - typedef int kern_return_t; \n\ - typedef uint64_t mach_vm_address_t; \n\ - typedef uint64_t mach_vm_size_t; \n\ - \n\ - mach_port_t mach_task_self (); \n\ - kern_return_t mach_vm_deallocate (vm_map_t target, mach_vm_address_t address, mach_vm_size_t size); \n\ - \n\ - typedef void *pthread_t; \n\ - extern int printf(const char *format, ...); \n\ - extern pthread_t pthread_self(void); \n\ - \n\ - /* \n\ - * libBacktraceRecording defines \n\ - */ \n\ - \n\ - typedef uint32_t queue_list_scope_t; \n\ - typedef void *dispatch_queue_t; \n\ - typedef void *introspection_dispatch_queue_info_t; \n\ - typedef void *introspection_dispatch_item_info_ref; \n\ - \n\ - extern void __introspection_dispatch_thread_get_item_info (uint64_t thread_id, \n\ - introspection_dispatch_item_info_ref *returned_queues_buffer, \n\ - uint64_t *returned_queues_buffer_size); \n\ - \n\ - /* \n\ - * return type define \n\ - */ \n\ - \n\ - struct get_thread_item_info_return_values \n\ - { \n\ - uint64_t item_info_buffer_ptr; /* the address of the items buffer from libBacktraceRecording */ \n\ - uint64_t item_info_buffer_size; /* the size of the items buffer from libBacktraceRecording */ \n\ - }; \n\ - \n\ - void __lldb_backtrace_recording_get_thread_item_info \n\ - (struct get_thread_item_info_return_values *return_buffer, \n\ - int debug, \n\ - uint64_t thread_id, \n\ - void *page_to_free, \n\ - uint64_t page_to_free_size) \n\ -{ \n\ - void *pthread_id = pthread_self (); \n\ - if (debug) \n\ - printf (\"entering get_thread_item_info with args return_buffer == %p, debug == %d, thread id == 0x%llx, page_to_free == %p, page_to_free_size == 0x%llx\\n\", return_buffer, debug, (uint64_t) thread_id, page_to_free, page_to_free_size); \n\ - if (page_to_free != 0) \n\ - { \n\ - mach_vm_deallocate (mach_task_self(), (mach_vm_address_t) page_to_free, (mach_vm_size_t) page_to_free_size); \n\ - } \n\ - \n\ - __introspection_dispatch_thread_get_item_info (thread_id, \n\ - (void**)&return_buffer->item_info_buffer_ptr, \n\ - &return_buffer->item_info_buffer_size); \n\ -} \n\ -} \n\ -"; - -AppleGetThreadItemInfoHandler::AppleGetThreadItemInfoHandler(Process *process) - : m_process(process), m_get_thread_item_info_impl_code(), - m_get_thread_item_info_function_mutex(), - m_get_thread_item_info_return_buffer_addr(LLDB_INVALID_ADDRESS), - m_get_thread_item_info_retbuffer_mutex() {} - -AppleGetThreadItemInfoHandler::~AppleGetThreadItemInfoHandler() {} - -void AppleGetThreadItemInfoHandler::Detach() { - - if (m_process && m_process->IsAlive() && - m_get_thread_item_info_return_buffer_addr != LLDB_INVALID_ADDRESS) { - std::unique_lock<std::mutex> lock(m_get_thread_item_info_retbuffer_mutex, - std::defer_lock); - lock.try_lock(); // Even if we don't get the lock, deallocate the buffer - m_process->DeallocateMemory(m_get_thread_item_info_return_buffer_addr); - } -} - -// Compile our __lldb_backtrace_recording_get_thread_item_info() function (from -// the source above in g_get_thread_item_info_function_code) if we don't find -// that function in the inferior already with USE_BUILTIN_FUNCTION defined. -// (e.g. this would be the case for testing.) -// -// Insert the __lldb_backtrace_recording_get_thread_item_info into the inferior -// process if needed. -// -// Write the get_thread_item_info_arglist into the inferior's memory space to -// prepare for the call. -// -// Returns the address of the arguments written down in the inferior process, -// which can be used to make the function call. - -lldb::addr_t AppleGetThreadItemInfoHandler::SetupGetThreadItemInfoFunction( - Thread &thread, ValueList &get_thread_item_info_arglist) { - ThreadSP thread_sp(thread.shared_from_this()); - ExecutionContext exe_ctx(thread_sp); - Address impl_code_address; - DiagnosticManager diagnostics; - Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_SYSTEM_RUNTIME)); - lldb::addr_t args_addr = LLDB_INVALID_ADDRESS; - FunctionCaller *get_thread_item_info_caller = nullptr; - - // Scope for mutex locker: - { - std::lock_guard<std::mutex> guard(m_get_thread_item_info_function_mutex); - - // First stage is to make the ClangUtility to hold our injected function: - - if (!m_get_thread_item_info_impl_code.get()) { - Status error; - if (g_get_thread_item_info_function_code != NULL) { - m_get_thread_item_info_impl_code.reset( - exe_ctx.GetTargetRef().GetUtilityFunctionForLanguage( - g_get_thread_item_info_function_code, eLanguageTypeC, - g_get_thread_item_info_function_name, error)); - if (error.Fail()) { - if (log) - log->Printf("Failed to get UtilityFunction for " - "get-thread-item-info introspection: %s.", - error.AsCString()); - m_get_thread_item_info_impl_code.reset(); - return args_addr; - } - - if (!m_get_thread_item_info_impl_code->Install(diagnostics, exe_ctx)) { - if (log) { - log->Printf( - "Failed to install get-thread-item-info introspection."); - diagnostics.Dump(log); - } - - m_get_thread_item_info_impl_code.reset(); - return args_addr; - } - } else { - if (log) - log->Printf("No get-thread-item-info introspection code found."); - return LLDB_INVALID_ADDRESS; - } - - // Also make the FunctionCaller for this UtilityFunction: - - ClangASTContext *clang_ast_context = - thread.GetProcess()->GetTarget().GetScratchClangASTContext(); - CompilerType get_thread_item_info_return_type = - clang_ast_context->GetBasicType(eBasicTypeVoid).GetPointerType(); - - get_thread_item_info_caller = - m_get_thread_item_info_impl_code->MakeFunctionCaller( - get_thread_item_info_return_type, get_thread_item_info_arglist, - thread_sp, error); - if (error.Fail() || get_thread_item_info_caller == nullptr) { - if (log) - log->Printf("Failed to install get-thread-item-info introspection " - "caller: %s.", - error.AsCString()); - m_get_thread_item_info_impl_code.reset(); - return args_addr; - } - - } else { - get_thread_item_info_caller = - m_get_thread_item_info_impl_code->GetFunctionCaller(); - } - } - - 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 (!get_thread_item_info_caller->WriteFunctionArguments( - exe_ctx, args_addr, get_thread_item_info_arglist, diagnostics)) { - if (log) { - log->Printf("Error writing get-thread-item-info function arguments"); - diagnostics.Dump(log); - } - return args_addr; - } - - return args_addr; -} - -AppleGetThreadItemInfoHandler::GetThreadItemInfoReturnInfo -AppleGetThreadItemInfoHandler::GetThreadItemInfo(Thread &thread, - tid_t thread_id, - addr_t page_to_free, - uint64_t page_to_free_size, - Status &error) { - lldb::StackFrameSP thread_cur_frame = thread.GetStackFrameAtIndex(0); - ProcessSP process_sp(thread.CalculateProcess()); - TargetSP target_sp(thread.CalculateTarget()); - ClangASTContext *clang_ast_context = target_sp->GetScratchClangASTContext(); - Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_SYSTEM_RUNTIME)); - - GetThreadItemInfoReturnInfo return_value; - return_value.item_buffer_ptr = LLDB_INVALID_ADDRESS; - return_value.item_buffer_size = 0; - - error.Clear(); - - if (!thread.SafeToCallFunctions()) { - if (log) - log->Printf("Not safe to call functions on thread 0x%" PRIx64, - thread.GetID()); - error.SetErrorString("Not safe to call functions on this thread."); - return return_value; - } - - // Set up the arguments for a call to - - // struct get_thread_item_info_return_values { - // uint64_t item_info_buffer_ptr; /* the address of the items buffer - // from libBacktraceRecording */ - // uint64_t item_info_buffer_size; /* the size of the items buffer from - // libBacktraceRecording */ - // }; - // - // void __lldb_backtrace_recording_get_thread_item_info - // (struct - // get_thread_item_info_return_values - // *return_buffer, - // int debug, - // void *page_to_free, - // uint64_t page_to_free_size) - - // Where the return_buffer argument points to a 24 byte region of memory - // already allocated by lldb in the inferior process. - - CompilerType clang_void_ptr_type = - clang_ast_context->GetBasicType(eBasicTypeVoid).GetPointerType(); - Value return_buffer_ptr_value; - return_buffer_ptr_value.SetValueType(Value::eValueTypeScalar); - return_buffer_ptr_value.SetCompilerType(clang_void_ptr_type); - - CompilerType clang_int_type = clang_ast_context->GetBasicType(eBasicTypeInt); - Value debug_value; - debug_value.SetValueType(Value::eValueTypeScalar); - debug_value.SetCompilerType(clang_int_type); - - CompilerType clang_uint64_type = - clang_ast_context->GetBasicType(eBasicTypeUnsignedLongLong); - Value thread_id_value; - thread_id_value.SetValueType(Value::eValueTypeScalar); - thread_id_value.SetCompilerType(clang_uint64_type); - - Value page_to_free_value; - page_to_free_value.SetValueType(Value::eValueTypeScalar); - page_to_free_value.SetCompilerType(clang_void_ptr_type); - - Value page_to_free_size_value; - page_to_free_size_value.SetValueType(Value::eValueTypeScalar); - page_to_free_size_value.SetCompilerType(clang_uint64_type); - - std::lock_guard<std::mutex> guard(m_get_thread_item_info_retbuffer_mutex); - if (m_get_thread_item_info_return_buffer_addr == LLDB_INVALID_ADDRESS) { - addr_t bufaddr = process_sp->AllocateMemory( - 32, ePermissionsReadable | ePermissionsWritable, error); - if (!error.Success() || bufaddr == LLDB_INVALID_ADDRESS) { - if (log) - log->Printf("Failed to allocate memory for return buffer for get " - "current queues func call"); - return return_value; - } - m_get_thread_item_info_return_buffer_addr = bufaddr; - } - - ValueList argument_values; - - return_buffer_ptr_value.GetScalar() = - m_get_thread_item_info_return_buffer_addr; - argument_values.PushValue(return_buffer_ptr_value); - - debug_value.GetScalar() = 0; - argument_values.PushValue(debug_value); - - thread_id_value.GetScalar() = thread_id; - argument_values.PushValue(thread_id_value); - - if (page_to_free != LLDB_INVALID_ADDRESS) - page_to_free_value.GetScalar() = page_to_free; - else - page_to_free_value.GetScalar() = 0; - argument_values.PushValue(page_to_free_value); - - page_to_free_size_value.GetScalar() = page_to_free_size; - argument_values.PushValue(page_to_free_size_value); - - addr_t args_addr = SetupGetThreadItemInfoFunction(thread, argument_values); - - DiagnosticManager diagnostics; - ExecutionContext exe_ctx; - EvaluateExpressionOptions options; - FunctionCaller *get_thread_item_info_caller = nullptr; - - options.SetUnwindOnError(true); - options.SetIgnoreBreakpoints(true); - options.SetStopOthers(true); - options.SetTimeout(std::chrono::milliseconds(500)); - options.SetTryAllThreads(false); - options.SetIsForUtilityExpr(true); - thread.CalculateExecutionContext(exe_ctx); - - if (!m_get_thread_item_info_impl_code) { - error.SetErrorString("Unable to compile function to call " - "__introspection_dispatch_thread_get_item_info"); - return return_value; - } - - get_thread_item_info_caller = - m_get_thread_item_info_impl_code->GetFunctionCaller(); - - if (!get_thread_item_info_caller) { - error.SetErrorString("Unable to compile function caller for " - "__introspection_dispatch_thread_get_item_info"); - return return_value; - } - - ExpressionResults func_call_ret; - Value results; - func_call_ret = get_thread_item_info_caller->ExecuteFunction( - exe_ctx, &args_addr, options, diagnostics, results); - if (func_call_ret != eExpressionCompleted || !error.Success()) { - if (log) - log->Printf("Unable to call " - "__introspection_dispatch_thread_get_item_info(), got " - "ExpressionResults %d, error contains %s", - func_call_ret, error.AsCString("")); - error.SetErrorString("Unable to call " - "__introspection_dispatch_thread_get_item_info() for " - "list of queues"); - return return_value; - } - - return_value.item_buffer_ptr = m_process->ReadUnsignedIntegerFromMemory( - m_get_thread_item_info_return_buffer_addr, 8, LLDB_INVALID_ADDRESS, - error); - if (!error.Success() || - return_value.item_buffer_ptr == LLDB_INVALID_ADDRESS) { - return_value.item_buffer_ptr = LLDB_INVALID_ADDRESS; - return return_value; - } - - return_value.item_buffer_size = m_process->ReadUnsignedIntegerFromMemory( - m_get_thread_item_info_return_buffer_addr + 8, 8, 0, error); - - if (!error.Success()) { - return_value.item_buffer_ptr = LLDB_INVALID_ADDRESS; - return return_value; - } - - if (log) - log->Printf("AppleGetThreadItemInfoHandler called " - "__introspection_dispatch_thread_get_item_info (page_to_free " - "== 0x%" PRIx64 ", size = %" PRId64 - "), returned page is at 0x%" PRIx64 ", size %" PRId64, - page_to_free, page_to_free_size, return_value.item_buffer_ptr, - return_value.item_buffer_size); - - return return_value; -} diff --git a/source/Plugins/SystemRuntime/MacOSX/AppleGetThreadItemInfoHandler.h b/source/Plugins/SystemRuntime/MacOSX/AppleGetThreadItemInfoHandler.h deleted file mode 100644 index 47e196102362..000000000000 --- a/source/Plugins/SystemRuntime/MacOSX/AppleGetThreadItemInfoHandler.h +++ /dev/null @@ -1,114 +0,0 @@ -//===-- AppleGetThreadItemInfoHandler.h ----------------------------*- C++ -//-*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef lldb_AppleGetThreadItemInfoHandler_h_ -#define lldb_AppleGetThreadItemInfoHandler_h_ - -#include <map> -#include <mutex> -#include <vector> - -#include "lldb/Symbol/CompilerType.h" -#include "lldb/Utility/Status.h" -#include "lldb/lldb-public.h" - -// This class will insert a UtilityFunction into the inferior process for -// calling libBacktraceRecording's -// __introspection_dispatch_thread_get_item_info() -// function. The function in the inferior will return a struct by value -// with these members: -// -// struct get_thread_item_info_return_values -// { -// introspection_dispatch_item_info_ref *item_buffer; -// uint64_t item_buffer_size; -// }; -// -// The item_buffer pointer is an address in the inferior program's address -// space (item_buffer_size in size) which must be mach_vm_deallocate'd by -// lldb. -// -// The AppleGetThreadItemInfoHandler object should persist so that the -// UtilityFunction -// can be reused multiple times. - -namespace lldb_private { - -class AppleGetThreadItemInfoHandler { -public: - AppleGetThreadItemInfoHandler(lldb_private::Process *process); - - ~AppleGetThreadItemInfoHandler(); - - struct GetThreadItemInfoReturnInfo { - lldb::addr_t item_buffer_ptr; /* the address of the item buffer from - libBacktraceRecording */ - lldb::addr_t item_buffer_size; /* the size of the item buffer from - libBacktraceRecording */ - - GetThreadItemInfoReturnInfo() - : item_buffer_ptr(LLDB_INVALID_ADDRESS), item_buffer_size(0) {} - }; - - //---------------------------------------------------------- - /// Get the information about a work item by calling - /// __introspection_dispatch_thread_get_item_info. If there's a page of - /// memory that needs to be freed, pass in the address and size and it will - /// be freed before getting the list of queues. - /// - /// @param [in] thread_id - /// The thread to get the extended backtrace for. - /// - /// @param [in] page_to_free - /// An address of an inferior process vm page that needs to be - /// deallocated, - /// LLDB_INVALID_ADDRESS if this is not needed. - /// - /// @param [in] page_to_free_size - /// The size of the vm page that needs to be deallocated if an address was - /// passed in to page_to_free. - /// - /// @param [out] error - /// This object will be updated with the error status / error string from - /// any failures encountered. - /// - /// @returns - /// The result of the inferior function call execution. If there was a - /// failure of any kind while getting - /// the information, the item_buffer_ptr value will be - /// LLDB_INVALID_ADDRESS. - //---------------------------------------------------------- - GetThreadItemInfoReturnInfo GetThreadItemInfo(Thread &thread, - lldb::tid_t thread_id, - lldb::addr_t page_to_free, - uint64_t page_to_free_size, - lldb_private::Status &error); - - void Detach(); - -private: - lldb::addr_t - SetupGetThreadItemInfoFunction(Thread &thread, - ValueList &get_thread_item_info_arglist); - - static const char *g_get_thread_item_info_function_name; - static const char *g_get_thread_item_info_function_code; - - lldb_private::Process *m_process; - std::unique_ptr<UtilityFunction> m_get_thread_item_info_impl_code; - std::mutex m_get_thread_item_info_function_mutex; - - lldb::addr_t m_get_thread_item_info_return_buffer_addr; - std::mutex m_get_thread_item_info_retbuffer_mutex; -}; - -} // using namespace lldb_private - -#endif // lldb_AppleGetThreadItemInfoHandler_h_ diff --git a/source/Plugins/SystemRuntime/MacOSX/CMakeLists.txt b/source/Plugins/SystemRuntime/MacOSX/CMakeLists.txt deleted file mode 100644 index ac5781b98b09..000000000000 --- a/source/Plugins/SystemRuntime/MacOSX/CMakeLists.txt +++ /dev/null @@ -1,17 +0,0 @@ -add_lldb_library(lldbPluginSystemRuntimeMacOSX PLUGIN - AppleGetItemInfoHandler.cpp - AppleGetPendingItemsHandler.cpp - AppleGetQueuesHandler.cpp - AppleGetThreadItemInfoHandler.cpp - SystemRuntimeMacOSX.cpp - - LINK_LIBS - lldbBreakpoint - lldbCore - lldbExpression - lldbHost - lldbSymbol - lldbTarget - lldbUtility - lldbPluginProcessUtility - ) diff --git a/source/Plugins/SystemRuntime/MacOSX/SystemRuntimeMacOSX.cpp b/source/Plugins/SystemRuntime/MacOSX/SystemRuntimeMacOSX.cpp deleted file mode 100644 index e61f04e489e8..000000000000 --- a/source/Plugins/SystemRuntime/MacOSX/SystemRuntimeMacOSX.cpp +++ /dev/null @@ -1,1021 +0,0 @@ -//===-- SystemRuntimeMacOSX.cpp ---------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "Plugins/Process/Utility/HistoryThread.h" -#include "lldb/Breakpoint/StoppointCallbackContext.h" -#include "lldb/Core/Module.h" -#include "lldb/Core/ModuleSpec.h" -#include "lldb/Core/PluginManager.h" -#include "lldb/Core/Section.h" -#include "lldb/Symbol/ClangASTContext.h" -#include "lldb/Symbol/ObjectFile.h" -#include "lldb/Symbol/SymbolContext.h" -#include "lldb/Target/Process.h" -#include "lldb/Target/ProcessStructReader.h" -#include "lldb/Target/Queue.h" -#include "lldb/Target/QueueList.h" -#include "lldb/Target/Target.h" -#include "lldb/Target/Thread.h" -#include "lldb/Utility/DataBufferHeap.h" -#include "lldb/Utility/DataExtractor.h" -#include "lldb/Utility/FileSpec.h" -#include "lldb/Utility/Log.h" -#include "lldb/Utility/StreamString.h" - -#include "SystemRuntimeMacOSX.h" - -using namespace lldb; -using namespace lldb_private; - -//---------------------------------------------------------------------- -// Create an instance of this class. This function is filled into the plugin -// info class that gets handed out by the plugin factory and allows the lldb to -// instantiate an instance of this class. -//---------------------------------------------------------------------- -SystemRuntime *SystemRuntimeMacOSX::CreateInstance(Process *process) { - bool create = false; - if (!create) { - create = true; - Module *exe_module = process->GetTarget().GetExecutableModulePointer(); - if (exe_module) { - ObjectFile *object_file = exe_module->GetObjectFile(); - if (object_file) { - create = (object_file->GetStrata() == ObjectFile::eStrataUser); - } - } - - if (create) { - const llvm::Triple &triple_ref = - process->GetTarget().GetArchitecture().GetTriple(); - switch (triple_ref.getOS()) { - case llvm::Triple::Darwin: - case llvm::Triple::MacOSX: - case llvm::Triple::IOS: - case llvm::Triple::TvOS: - case llvm::Triple::WatchOS: - // NEED_BRIDGEOS_TRIPLE case llvm::Triple::BridgeOS: - create = triple_ref.getVendor() == llvm::Triple::Apple; - break; - default: - create = false; - break; - } - } - } - - if (create) - return new SystemRuntimeMacOSX(process); - return NULL; -} - -//---------------------------------------------------------------------- -// Constructor -//---------------------------------------------------------------------- -SystemRuntimeMacOSX::SystemRuntimeMacOSX(Process *process) - : SystemRuntime(process), m_break_id(LLDB_INVALID_BREAK_ID), m_mutex(), - m_get_queues_handler(process), m_get_pending_items_handler(process), - m_get_item_info_handler(process), m_get_thread_item_info_handler(process), - m_page_to_free(LLDB_INVALID_ADDRESS), m_page_to_free_size(0), - m_lib_backtrace_recording_info(), - m_dispatch_queue_offsets_addr(LLDB_INVALID_ADDRESS), - m_libdispatch_offsets(), - m_libpthread_layout_offsets_addr(LLDB_INVALID_ADDRESS), - m_libpthread_offsets(), m_dispatch_tsd_indexes_addr(LLDB_INVALID_ADDRESS), - m_libdispatch_tsd_indexes(), - m_dispatch_voucher_offsets_addr(LLDB_INVALID_ADDRESS), - m_libdispatch_voucher_offsets() {} - -//---------------------------------------------------------------------- -// Destructor -//---------------------------------------------------------------------- -SystemRuntimeMacOSX::~SystemRuntimeMacOSX() { Clear(true); } - -void SystemRuntimeMacOSX::Detach() { - m_get_queues_handler.Detach(); - m_get_pending_items_handler.Detach(); - m_get_item_info_handler.Detach(); - m_get_thread_item_info_handler.Detach(); -} - -//---------------------------------------------------------------------- -// Clear out the state of this class. -//---------------------------------------------------------------------- -void SystemRuntimeMacOSX::Clear(bool clear_process) { - std::lock_guard<std::recursive_mutex> guard(m_mutex); - - if (m_process->IsAlive() && LLDB_BREAK_ID_IS_VALID(m_break_id)) - m_process->ClearBreakpointSiteByID(m_break_id); - - if (clear_process) - m_process = NULL; - m_break_id = LLDB_INVALID_BREAK_ID; -} - -std::string -SystemRuntimeMacOSX::GetQueueNameFromThreadQAddress(addr_t dispatch_qaddr) { - std::string dispatch_queue_name; - if (dispatch_qaddr == LLDB_INVALID_ADDRESS || dispatch_qaddr == 0) - return ""; - - ReadLibdispatchOffsets(); - if (m_libdispatch_offsets.IsValid()) { - // dispatch_qaddr is from a thread_info(THREAD_IDENTIFIER_INFO) call for a - // thread - deref it to get the address of the dispatch_queue_t structure - // for this thread's queue. - Status error; - addr_t dispatch_queue_addr = - m_process->ReadPointerFromMemory(dispatch_qaddr, error); - if (error.Success()) { - if (m_libdispatch_offsets.dqo_version >= 4) { - // libdispatch versions 4+, pointer to dispatch name is in the queue - // structure. - addr_t pointer_to_label_address = - dispatch_queue_addr + m_libdispatch_offsets.dqo_label; - addr_t label_addr = - m_process->ReadPointerFromMemory(pointer_to_label_address, error); - if (error.Success()) { - m_process->ReadCStringFromMemory(label_addr, dispatch_queue_name, - error); - } - } else { - // libdispatch versions 1-3, dispatch name is a fixed width char array - // in the queue structure. - addr_t label_addr = - dispatch_queue_addr + m_libdispatch_offsets.dqo_label; - dispatch_queue_name.resize(m_libdispatch_offsets.dqo_label_size, '\0'); - size_t bytes_read = - m_process->ReadMemory(label_addr, &dispatch_queue_name[0], - m_libdispatch_offsets.dqo_label_size, error); - if (bytes_read < m_libdispatch_offsets.dqo_label_size) - dispatch_queue_name.erase(bytes_read); - } - } - } - return dispatch_queue_name; -} - -lldb::addr_t SystemRuntimeMacOSX::GetLibdispatchQueueAddressFromThreadQAddress( - addr_t dispatch_qaddr) { - addr_t libdispatch_queue_t_address = LLDB_INVALID_ADDRESS; - Status error; - libdispatch_queue_t_address = - m_process->ReadPointerFromMemory(dispatch_qaddr, error); - if (!error.Success()) { - libdispatch_queue_t_address = LLDB_INVALID_ADDRESS; - } - return libdispatch_queue_t_address; -} - -lldb::QueueKind SystemRuntimeMacOSX::GetQueueKind(addr_t dispatch_queue_addr) { - if (dispatch_queue_addr == LLDB_INVALID_ADDRESS || dispatch_queue_addr == 0) - return eQueueKindUnknown; - - QueueKind kind = eQueueKindUnknown; - ReadLibdispatchOffsets(); - if (m_libdispatch_offsets.IsValid() && - m_libdispatch_offsets.dqo_version >= 4) { - Status error; - uint64_t width = m_process->ReadUnsignedIntegerFromMemory( - dispatch_queue_addr + m_libdispatch_offsets.dqo_width, - m_libdispatch_offsets.dqo_width_size, 0, error); - if (error.Success()) { - if (width == 1) { - kind = eQueueKindSerial; - } - if (width > 1) { - kind = eQueueKindConcurrent; - } - } - } - return kind; -} - -void SystemRuntimeMacOSX::AddThreadExtendedInfoPacketHints( - lldb_private::StructuredData::ObjectSP dict_sp) { - StructuredData::Dictionary *dict = dict_sp->GetAsDictionary(); - if (dict) { - ReadLibpthreadOffsets(); - if (m_libpthread_offsets.IsValid()) { - dict->AddIntegerItem("plo_pthread_tsd_base_offset", - m_libpthread_offsets.plo_pthread_tsd_base_offset); - dict->AddIntegerItem( - "plo_pthread_tsd_base_address_offset", - m_libpthread_offsets.plo_pthread_tsd_base_address_offset); - dict->AddIntegerItem("plo_pthread_tsd_entry_size", - m_libpthread_offsets.plo_pthread_tsd_entry_size); - } - - ReadLibdispatchTSDIndexes(); - if (m_libdispatch_tsd_indexes.IsValid()) { - dict->AddIntegerItem("dti_queue_index", - m_libdispatch_tsd_indexes.dti_queue_index); - dict->AddIntegerItem("dti_voucher_index", - m_libdispatch_tsd_indexes.dti_voucher_index); - dict->AddIntegerItem("dti_qos_class_index", - m_libdispatch_tsd_indexes.dti_qos_class_index); - } - } -} - -bool SystemRuntimeMacOSX::SafeToCallFunctionsOnThisThread(ThreadSP thread_sp) { - if (thread_sp && thread_sp->GetStackFrameCount() > 0 && - thread_sp->GetFrameWithConcreteFrameIndex(0)) { - const SymbolContext sym_ctx( - thread_sp->GetFrameWithConcreteFrameIndex(0)->GetSymbolContext( - eSymbolContextSymbol)); - static ConstString g_select_symbol("__select"); - if (sym_ctx.GetFunctionName() == g_select_symbol) { - return false; - } - } - return true; -} - -lldb::queue_id_t -SystemRuntimeMacOSX::GetQueueIDFromThreadQAddress(lldb::addr_t dispatch_qaddr) { - queue_id_t queue_id = LLDB_INVALID_QUEUE_ID; - - if (dispatch_qaddr == LLDB_INVALID_ADDRESS || dispatch_qaddr == 0) - return queue_id; - - ReadLibdispatchOffsets(); - if (m_libdispatch_offsets.IsValid()) { - // dispatch_qaddr is from a thread_info(THREAD_IDENTIFIER_INFO) call for a - // thread - deref it to get the address of the dispatch_queue_t structure - // for this thread's queue. - Status error; - uint64_t dispatch_queue_addr = - m_process->ReadPointerFromMemory(dispatch_qaddr, error); - if (error.Success()) { - addr_t serialnum_address = - dispatch_queue_addr + m_libdispatch_offsets.dqo_serialnum; - queue_id_t serialnum = m_process->ReadUnsignedIntegerFromMemory( - serialnum_address, m_libdispatch_offsets.dqo_serialnum_size, - LLDB_INVALID_QUEUE_ID, error); - if (error.Success()) { - queue_id = serialnum; - } - } - } - - return queue_id; -} - -void SystemRuntimeMacOSX::ReadLibdispatchOffsetsAddress() { - if (m_dispatch_queue_offsets_addr != LLDB_INVALID_ADDRESS) - return; - - static ConstString g_dispatch_queue_offsets_symbol_name( - "dispatch_queue_offsets"); - const Symbol *dispatch_queue_offsets_symbol = NULL; - - // libdispatch symbols were in libSystem.B.dylib up through Mac OS X 10.6 - // ("Snow Leopard") - ModuleSpec libSystem_module_spec(FileSpec("libSystem.B.dylib")); - ModuleSP module_sp(m_process->GetTarget().GetImages().FindFirstModule( - libSystem_module_spec)); - if (module_sp) - dispatch_queue_offsets_symbol = module_sp->FindFirstSymbolWithNameAndType( - g_dispatch_queue_offsets_symbol_name, eSymbolTypeData); - - // libdispatch symbols are in their own dylib as of Mac OS X 10.7 ("Lion") - // and later - if (dispatch_queue_offsets_symbol == NULL) { - ModuleSpec libdispatch_module_spec(FileSpec("libdispatch.dylib")); - module_sp = m_process->GetTarget().GetImages().FindFirstModule( - libdispatch_module_spec); - if (module_sp) - dispatch_queue_offsets_symbol = module_sp->FindFirstSymbolWithNameAndType( - g_dispatch_queue_offsets_symbol_name, eSymbolTypeData); - } - if (dispatch_queue_offsets_symbol) - m_dispatch_queue_offsets_addr = - dispatch_queue_offsets_symbol->GetLoadAddress(&m_process->GetTarget()); -} - -void SystemRuntimeMacOSX::ReadLibdispatchOffsets() { - if (m_libdispatch_offsets.IsValid()) - return; - - ReadLibdispatchOffsetsAddress(); - - uint8_t memory_buffer[sizeof(struct LibdispatchOffsets)]; - DataExtractor data(memory_buffer, sizeof(memory_buffer), - m_process->GetByteOrder(), - m_process->GetAddressByteSize()); - - Status error; - if (m_process->ReadMemory(m_dispatch_queue_offsets_addr, memory_buffer, - sizeof(memory_buffer), - error) == sizeof(memory_buffer)) { - lldb::offset_t data_offset = 0; - - // The struct LibdispatchOffsets is a series of uint16_t's - extract them - // all in one big go. - data.GetU16(&data_offset, &m_libdispatch_offsets.dqo_version, - sizeof(struct LibdispatchOffsets) / sizeof(uint16_t)); - } -} - -void SystemRuntimeMacOSX::ReadLibpthreadOffsetsAddress() { - if (m_libpthread_layout_offsets_addr != LLDB_INVALID_ADDRESS) - return; - - static ConstString g_libpthread_layout_offsets_symbol_name( - "pthread_layout_offsets"); - const Symbol *libpthread_layout_offsets_symbol = NULL; - - ModuleSpec libpthread_module_spec(FileSpec("libsystem_pthread.dylib")); - ModuleSP module_sp(m_process->GetTarget().GetImages().FindFirstModule( - libpthread_module_spec)); - if (module_sp) { - libpthread_layout_offsets_symbol = - module_sp->FindFirstSymbolWithNameAndType( - g_libpthread_layout_offsets_symbol_name, eSymbolTypeData); - if (libpthread_layout_offsets_symbol) { - m_libpthread_layout_offsets_addr = - libpthread_layout_offsets_symbol->GetLoadAddress( - &m_process->GetTarget()); - } - } -} - -void SystemRuntimeMacOSX::ReadLibpthreadOffsets() { - if (m_libpthread_offsets.IsValid()) - return; - - ReadLibpthreadOffsetsAddress(); - - if (m_libpthread_layout_offsets_addr != LLDB_INVALID_ADDRESS) { - uint8_t memory_buffer[sizeof(struct LibpthreadOffsets)]; - DataExtractor data(memory_buffer, sizeof(memory_buffer), - m_process->GetByteOrder(), - m_process->GetAddressByteSize()); - Status error; - if (m_process->ReadMemory(m_libpthread_layout_offsets_addr, memory_buffer, - sizeof(memory_buffer), - error) == sizeof(memory_buffer)) { - lldb::offset_t data_offset = 0; - - // The struct LibpthreadOffsets is a series of uint16_t's - extract them - // all in one big go. - data.GetU16(&data_offset, &m_libpthread_offsets.plo_version, - sizeof(struct LibpthreadOffsets) / sizeof(uint16_t)); - } - } -} - -void SystemRuntimeMacOSX::ReadLibdispatchTSDIndexesAddress() { - if (m_dispatch_tsd_indexes_addr != LLDB_INVALID_ADDRESS) - return; - - static ConstString g_libdispatch_tsd_indexes_symbol_name( - "dispatch_tsd_indexes"); - const Symbol *libdispatch_tsd_indexes_symbol = NULL; - - ModuleSpec libpthread_module_spec(FileSpec("libdispatch.dylib")); - ModuleSP module_sp(m_process->GetTarget().GetImages().FindFirstModule( - libpthread_module_spec)); - if (module_sp) { - libdispatch_tsd_indexes_symbol = module_sp->FindFirstSymbolWithNameAndType( - g_libdispatch_tsd_indexes_symbol_name, eSymbolTypeData); - if (libdispatch_tsd_indexes_symbol) { - m_dispatch_tsd_indexes_addr = - libdispatch_tsd_indexes_symbol->GetLoadAddress( - &m_process->GetTarget()); - } - } -} - -void SystemRuntimeMacOSX::ReadLibdispatchTSDIndexes() { - if (m_libdispatch_tsd_indexes.IsValid()) - return; - - ReadLibdispatchTSDIndexesAddress(); - - if (m_dispatch_tsd_indexes_addr != LLDB_INVALID_ADDRESS) { - -// We don't need to check the version number right now, it will be at least 2, -// but keep this code around to fetch just the version # for the future where -// we need to fetch alternate versions of the struct. -#if 0 - uint16_t dti_version = 2; - Address dti_struct_addr; - if (m_process->GetTarget().ResolveLoadAddress (m_dispatch_tsd_indexes_addr, dti_struct_addr)) - { - Status error; - uint16_t version = m_process->GetTarget().ReadUnsignedIntegerFromMemory (dti_struct_addr, false, 2, UINT16_MAX, error); - if (error.Success() && dti_version != UINT16_MAX) - { - dti_version = version; - } - } -#endif - - ClangASTContext *ast_ctx = - m_process->GetTarget().GetScratchClangASTContext(); - if (ast_ctx->getASTContext() && - m_dispatch_tsd_indexes_addr != LLDB_INVALID_ADDRESS) { - CompilerType uint16 = - ast_ctx->GetBuiltinTypeForEncodingAndBitSize(eEncodingUint, 16); - CompilerType dispatch_tsd_indexes_s = ast_ctx->CreateRecordType( - nullptr, lldb::eAccessPublic, "__lldb_dispatch_tsd_indexes_s", - clang::TTK_Struct, lldb::eLanguageTypeC); - - ClangASTContext::StartTagDeclarationDefinition(dispatch_tsd_indexes_s); - ClangASTContext::AddFieldToRecordType(dispatch_tsd_indexes_s, - "dti_version", uint16, - lldb::eAccessPublic, 0); - ClangASTContext::AddFieldToRecordType(dispatch_tsd_indexes_s, - "dti_queue_index", uint16, - lldb::eAccessPublic, 0); - ClangASTContext::AddFieldToRecordType(dispatch_tsd_indexes_s, - "dti_voucher_index", uint16, - lldb::eAccessPublic, 0); - ClangASTContext::AddFieldToRecordType(dispatch_tsd_indexes_s, - "dti_qos_class_index", uint16, - lldb::eAccessPublic, 0); - ClangASTContext::CompleteTagDeclarationDefinition(dispatch_tsd_indexes_s); - - ProcessStructReader struct_reader(m_process, m_dispatch_tsd_indexes_addr, - dispatch_tsd_indexes_s); - - m_libdispatch_tsd_indexes.dti_version = - struct_reader.GetField<uint16_t>(ConstString("dti_version")); - m_libdispatch_tsd_indexes.dti_queue_index = - struct_reader.GetField<uint16_t>(ConstString("dti_queue_index")); - m_libdispatch_tsd_indexes.dti_voucher_index = - struct_reader.GetField<uint16_t>(ConstString("dti_voucher_index")); - m_libdispatch_tsd_indexes.dti_qos_class_index = - struct_reader.GetField<uint16_t>(ConstString("dti_qos_class_index")); - } - } -} - -ThreadSP SystemRuntimeMacOSX::GetExtendedBacktraceThread(ThreadSP real_thread, - ConstString type) { - ThreadSP originating_thread_sp; - if (BacktraceRecordingHeadersInitialized() && - type == ConstString("libdispatch")) { - Status error; - - // real_thread is either an actual, live thread (in which case we need to - // call into libBacktraceRecording to find its originator) or it is an - // extended backtrace itself, in which case we get the token from it and - // call into libBacktraceRecording to find the originator of that token. - - if (real_thread->GetExtendedBacktraceToken() != LLDB_INVALID_ADDRESS) { - originating_thread_sp = GetExtendedBacktraceFromItemRef( - real_thread->GetExtendedBacktraceToken()); - } else { - ThreadSP cur_thread_sp( - m_process->GetThreadList().GetExpressionExecutionThread()); - AppleGetThreadItemInfoHandler::GetThreadItemInfoReturnInfo ret = - m_get_thread_item_info_handler.GetThreadItemInfo( - *cur_thread_sp.get(), real_thread->GetID(), m_page_to_free, - m_page_to_free_size, error); - m_page_to_free = LLDB_INVALID_ADDRESS; - m_page_to_free_size = 0; - if (ret.item_buffer_ptr != 0 && - ret.item_buffer_ptr != LLDB_INVALID_ADDRESS && - ret.item_buffer_size > 0) { - DataBufferHeap data(ret.item_buffer_size, 0); - if (m_process->ReadMemory(ret.item_buffer_ptr, data.GetBytes(), - ret.item_buffer_size, error) && - error.Success()) { - DataExtractor extractor(data.GetBytes(), data.GetByteSize(), - m_process->GetByteOrder(), - m_process->GetAddressByteSize()); - ItemInfo item = ExtractItemInfoFromBuffer(extractor); - bool stop_id_is_valid = true; - if (item.stop_id == 0) - stop_id_is_valid = false; - originating_thread_sp.reset(new HistoryThread( - *m_process, item.enqueuing_thread_id, item.enqueuing_callstack, - item.stop_id, stop_id_is_valid)); - originating_thread_sp->SetExtendedBacktraceToken( - item.item_that_enqueued_this); - originating_thread_sp->SetQueueName( - item.enqueuing_queue_label.c_str()); - originating_thread_sp->SetQueueID(item.enqueuing_queue_serialnum); - // originating_thread_sp->SetThreadName - // (item.enqueuing_thread_label.c_str()); - } - m_page_to_free = ret.item_buffer_ptr; - m_page_to_free_size = ret.item_buffer_size; - } - } - } - return originating_thread_sp; -} - -ThreadSP -SystemRuntimeMacOSX::GetExtendedBacktraceFromItemRef(lldb::addr_t item_ref) { - ThreadSP return_thread_sp; - - AppleGetItemInfoHandler::GetItemInfoReturnInfo ret; - ThreadSP cur_thread_sp( - m_process->GetThreadList().GetExpressionExecutionThread()); - Status error; - ret = m_get_item_info_handler.GetItemInfo(*cur_thread_sp.get(), item_ref, - m_page_to_free, m_page_to_free_size, - error); - m_page_to_free = LLDB_INVALID_ADDRESS; - m_page_to_free_size = 0; - if (ret.item_buffer_ptr != 0 && ret.item_buffer_ptr != LLDB_INVALID_ADDRESS && - ret.item_buffer_size > 0) { - DataBufferHeap data(ret.item_buffer_size, 0); - if (m_process->ReadMemory(ret.item_buffer_ptr, data.GetBytes(), - ret.item_buffer_size, error) && - error.Success()) { - DataExtractor extractor(data.GetBytes(), data.GetByteSize(), - m_process->GetByteOrder(), - m_process->GetAddressByteSize()); - ItemInfo item = ExtractItemInfoFromBuffer(extractor); - bool stop_id_is_valid = true; - if (item.stop_id == 0) - stop_id_is_valid = false; - return_thread_sp.reset(new HistoryThread( - *m_process, item.enqueuing_thread_id, item.enqueuing_callstack, - item.stop_id, stop_id_is_valid)); - return_thread_sp->SetExtendedBacktraceToken(item.item_that_enqueued_this); - return_thread_sp->SetQueueName(item.enqueuing_queue_label.c_str()); - return_thread_sp->SetQueueID(item.enqueuing_queue_serialnum); - // return_thread_sp->SetThreadName - // (item.enqueuing_thread_label.c_str()); - - m_page_to_free = ret.item_buffer_ptr; - m_page_to_free_size = ret.item_buffer_size; - } - } - return return_thread_sp; -} - -ThreadSP -SystemRuntimeMacOSX::GetExtendedBacktraceForQueueItem(QueueItemSP queue_item_sp, - ConstString type) { - ThreadSP extended_thread_sp; - if (type != ConstString("libdispatch")) - return extended_thread_sp; - - bool stop_id_is_valid = true; - if (queue_item_sp->GetStopID() == 0) - stop_id_is_valid = false; - - extended_thread_sp.reset( - new HistoryThread(*m_process, queue_item_sp->GetEnqueueingThreadID(), - queue_item_sp->GetEnqueueingBacktrace(), - queue_item_sp->GetStopID(), stop_id_is_valid)); - extended_thread_sp->SetExtendedBacktraceToken( - queue_item_sp->GetItemThatEnqueuedThis()); - extended_thread_sp->SetQueueName(queue_item_sp->GetQueueLabel().c_str()); - extended_thread_sp->SetQueueID(queue_item_sp->GetEnqueueingQueueID()); - // extended_thread_sp->SetThreadName - // (queue_item_sp->GetThreadLabel().c_str()); - - return extended_thread_sp; -} - -/* Returns true if we were able to get the version / offset information - * out of libBacktraceRecording. false means we were unable to retrieve - * this; the queue_info_version field will be 0. - */ - -bool SystemRuntimeMacOSX::BacktraceRecordingHeadersInitialized() { - if (m_lib_backtrace_recording_info.queue_info_version != 0) - return true; - - addr_t queue_info_version_address = LLDB_INVALID_ADDRESS; - addr_t queue_info_data_offset_address = LLDB_INVALID_ADDRESS; - addr_t item_info_version_address = LLDB_INVALID_ADDRESS; - addr_t item_info_data_offset_address = LLDB_INVALID_ADDRESS; - Target &target = m_process->GetTarget(); - - static ConstString introspection_dispatch_queue_info_version( - "__introspection_dispatch_queue_info_version"); - SymbolContextList sc_list; - if (m_process->GetTarget().GetImages().FindSymbolsWithNameAndType( - introspection_dispatch_queue_info_version, eSymbolTypeData, sc_list) > - 0) { - SymbolContext sc; - sc_list.GetContextAtIndex(0, sc); - AddressRange addr_range; - sc.GetAddressRange(eSymbolContextSymbol, 0, false, addr_range); - queue_info_version_address = - addr_range.GetBaseAddress().GetLoadAddress(&target); - } - sc_list.Clear(); - - static ConstString introspection_dispatch_queue_info_data_offset( - "__introspection_dispatch_queue_info_data_offset"); - if (m_process->GetTarget().GetImages().FindSymbolsWithNameAndType( - introspection_dispatch_queue_info_data_offset, eSymbolTypeData, - sc_list) > 0) { - SymbolContext sc; - sc_list.GetContextAtIndex(0, sc); - AddressRange addr_range; - sc.GetAddressRange(eSymbolContextSymbol, 0, false, addr_range); - queue_info_data_offset_address = - addr_range.GetBaseAddress().GetLoadAddress(&target); - } - sc_list.Clear(); - - static ConstString introspection_dispatch_item_info_version( - "__introspection_dispatch_item_info_version"); - if (m_process->GetTarget().GetImages().FindSymbolsWithNameAndType( - introspection_dispatch_item_info_version, eSymbolTypeData, sc_list) > - 0) { - SymbolContext sc; - sc_list.GetContextAtIndex(0, sc); - AddressRange addr_range; - sc.GetAddressRange(eSymbolContextSymbol, 0, false, addr_range); - item_info_version_address = - addr_range.GetBaseAddress().GetLoadAddress(&target); - } - sc_list.Clear(); - - static ConstString introspection_dispatch_item_info_data_offset( - "__introspection_dispatch_item_info_data_offset"); - if (m_process->GetTarget().GetImages().FindSymbolsWithNameAndType( - introspection_dispatch_item_info_data_offset, eSymbolTypeData, - sc_list) > 0) { - SymbolContext sc; - sc_list.GetContextAtIndex(0, sc); - AddressRange addr_range; - sc.GetAddressRange(eSymbolContextSymbol, 0, false, addr_range); - item_info_data_offset_address = - addr_range.GetBaseAddress().GetLoadAddress(&target); - } - - if (queue_info_version_address != LLDB_INVALID_ADDRESS && - queue_info_data_offset_address != LLDB_INVALID_ADDRESS && - item_info_version_address != LLDB_INVALID_ADDRESS && - item_info_data_offset_address != LLDB_INVALID_ADDRESS) { - Status error; - m_lib_backtrace_recording_info.queue_info_version = - m_process->ReadUnsignedIntegerFromMemory(queue_info_version_address, 2, - 0, error); - if (error.Success()) { - m_lib_backtrace_recording_info.queue_info_data_offset = - m_process->ReadUnsignedIntegerFromMemory( - queue_info_data_offset_address, 2, 0, error); - if (error.Success()) { - m_lib_backtrace_recording_info.item_info_version = - m_process->ReadUnsignedIntegerFromMemory(item_info_version_address, - 2, 0, error); - if (error.Success()) { - m_lib_backtrace_recording_info.item_info_data_offset = - m_process->ReadUnsignedIntegerFromMemory( - item_info_data_offset_address, 2, 0, error); - if (!error.Success()) { - m_lib_backtrace_recording_info.queue_info_version = 0; - } - } else { - m_lib_backtrace_recording_info.queue_info_version = 0; - } - } else { - m_lib_backtrace_recording_info.queue_info_version = 0; - } - } - } - - return m_lib_backtrace_recording_info.queue_info_version != 0; -} - -const std::vector<ConstString> & -SystemRuntimeMacOSX::GetExtendedBacktraceTypes() { - if (m_types.size() == 0) { - m_types.push_back(ConstString("libdispatch")); - // We could have pthread as another type in the future if we have a way of - // gathering that information & it's useful to distinguish between them. - } - return m_types; -} - -void SystemRuntimeMacOSX::PopulateQueueList( - lldb_private::QueueList &queue_list) { - if (BacktraceRecordingHeadersInitialized()) { - AppleGetQueuesHandler::GetQueuesReturnInfo queue_info_pointer; - ThreadSP cur_thread_sp( - m_process->GetThreadList().GetExpressionExecutionThread()); - if (cur_thread_sp) { - Status error; - queue_info_pointer = m_get_queues_handler.GetCurrentQueues( - *cur_thread_sp.get(), m_page_to_free, m_page_to_free_size, error); - m_page_to_free = LLDB_INVALID_ADDRESS; - m_page_to_free_size = 0; - if (error.Success()) { - - if (queue_info_pointer.count > 0 && - queue_info_pointer.queues_buffer_size > 0 && - queue_info_pointer.queues_buffer_ptr != 0 && - queue_info_pointer.queues_buffer_ptr != LLDB_INVALID_ADDRESS) { - PopulateQueuesUsingLibBTR(queue_info_pointer.queues_buffer_ptr, - queue_info_pointer.queues_buffer_size, - queue_info_pointer.count, queue_list); - } - } - } - } - - // We either didn't have libBacktraceRecording (and need to create the queues - // list based on threads) or we did get the queues list from - // libBacktraceRecording but some special queues may not be included in its - // information. This is needed because libBacktraceRecording will only list - // queues with pending or running items by default - but the magic com.apple - // .main-thread queue on thread 1 is always around. - - for (ThreadSP thread_sp : m_process->Threads()) { - if (thread_sp->GetAssociatedWithLibdispatchQueue() != eLazyBoolNo) { - if (thread_sp->GetQueueID() != LLDB_INVALID_QUEUE_ID) { - if (queue_list.FindQueueByID(thread_sp->GetQueueID()).get() == NULL) { - QueueSP queue_sp(new Queue(m_process->shared_from_this(), - thread_sp->GetQueueID(), - thread_sp->GetQueueName())); - if (thread_sp->ThreadHasQueueInformation()) { - queue_sp->SetKind(thread_sp->GetQueueKind()); - queue_sp->SetLibdispatchQueueAddress( - thread_sp->GetQueueLibdispatchQueueAddress()); - queue_list.AddQueue(queue_sp); - } else { - queue_sp->SetKind( - GetQueueKind(thread_sp->GetQueueLibdispatchQueueAddress())); - queue_sp->SetLibdispatchQueueAddress( - thread_sp->GetQueueLibdispatchQueueAddress()); - queue_list.AddQueue(queue_sp); - } - } - } - } - } -} - -// Returns either an array of introspection_dispatch_item_info_ref's for the -// pending items on a queue or an array introspection_dispatch_item_info_ref's -// and code addresses for the pending items on a queue. The information about -// each of these pending items then needs to be fetched individually by passing -// the ref to libBacktraceRecording. - -SystemRuntimeMacOSX::PendingItemsForQueue -SystemRuntimeMacOSX::GetPendingItemRefsForQueue(lldb::addr_t queue) { - PendingItemsForQueue pending_item_refs; - AppleGetPendingItemsHandler::GetPendingItemsReturnInfo pending_items_pointer; - ThreadSP cur_thread_sp( - m_process->GetThreadList().GetExpressionExecutionThread()); - if (cur_thread_sp) { - Status error; - pending_items_pointer = m_get_pending_items_handler.GetPendingItems( - *cur_thread_sp.get(), queue, m_page_to_free, m_page_to_free_size, - error); - m_page_to_free = LLDB_INVALID_ADDRESS; - m_page_to_free_size = 0; - if (error.Success()) { - if (pending_items_pointer.count > 0 && - pending_items_pointer.items_buffer_size > 0 && - pending_items_pointer.items_buffer_ptr != 0 && - pending_items_pointer.items_buffer_ptr != LLDB_INVALID_ADDRESS) { - DataBufferHeap data(pending_items_pointer.items_buffer_size, 0); - if (m_process->ReadMemory( - pending_items_pointer.items_buffer_ptr, data.GetBytes(), - pending_items_pointer.items_buffer_size, error)) { - DataExtractor extractor(data.GetBytes(), data.GetByteSize(), - m_process->GetByteOrder(), - m_process->GetAddressByteSize()); - - // We either have an array of - // void* item_ref - // (old style) or we have a structure returned which looks like - // - // struct introspection_dispatch_pending_item_info_s { - // void *item_ref; - // void *function_or_block; - // }; - // - // struct introspection_dispatch_pending_items_array_s { - // uint32_t version; - // uint32_t size_of_item_info; - // introspection_dispatch_pending_item_info_s items[]; - // } - - offset_t offset = 0; - int i = 0; - uint32_t version = extractor.GetU32(&offset); - if (version == 1) { - pending_item_refs.new_style = true; - uint32_t item_size = extractor.GetU32(&offset); - uint32_t start_of_array_offset = offset; - while (offset < pending_items_pointer.items_buffer_size && - static_cast<size_t>(i) < pending_items_pointer.count) { - offset = start_of_array_offset + (i * item_size); - ItemRefAndCodeAddress item; - item.item_ref = extractor.GetPointer(&offset); - item.code_address = extractor.GetPointer(&offset); - pending_item_refs.item_refs_and_code_addresses.push_back(item); - i++; - } - } else { - offset = 0; - pending_item_refs.new_style = false; - while (offset < pending_items_pointer.items_buffer_size && - static_cast<size_t>(i) < pending_items_pointer.count) { - ItemRefAndCodeAddress item; - item.item_ref = extractor.GetPointer(&offset); - item.code_address = LLDB_INVALID_ADDRESS; - pending_item_refs.item_refs_and_code_addresses.push_back(item); - i++; - } - } - } - m_page_to_free = pending_items_pointer.items_buffer_ptr; - m_page_to_free_size = pending_items_pointer.items_buffer_size; - } - } - } - return pending_item_refs; -} - -void SystemRuntimeMacOSX::PopulatePendingItemsForQueue(Queue *queue) { - if (BacktraceRecordingHeadersInitialized()) { - PendingItemsForQueue pending_item_refs = - GetPendingItemRefsForQueue(queue->GetLibdispatchQueueAddress()); - for (ItemRefAndCodeAddress pending_item : - pending_item_refs.item_refs_and_code_addresses) { - Address addr; - m_process->GetTarget().ResolveLoadAddress(pending_item.code_address, - addr); - QueueItemSP queue_item_sp(new QueueItem(queue->shared_from_this(), - m_process->shared_from_this(), - pending_item.item_ref, addr)); - queue->PushPendingQueueItem(queue_item_sp); - } - } -} - -void SystemRuntimeMacOSX::CompleteQueueItem(QueueItem *queue_item, - addr_t item_ref) { - AppleGetItemInfoHandler::GetItemInfoReturnInfo ret; - - ThreadSP cur_thread_sp( - m_process->GetThreadList().GetExpressionExecutionThread()); - Status error; - ret = m_get_item_info_handler.GetItemInfo(*cur_thread_sp.get(), item_ref, - m_page_to_free, m_page_to_free_size, - error); - m_page_to_free = LLDB_INVALID_ADDRESS; - m_page_to_free_size = 0; - if (ret.item_buffer_ptr != 0 && ret.item_buffer_ptr != LLDB_INVALID_ADDRESS && - ret.item_buffer_size > 0) { - DataBufferHeap data(ret.item_buffer_size, 0); - if (m_process->ReadMemory(ret.item_buffer_ptr, data.GetBytes(), - ret.item_buffer_size, error) && - error.Success()) { - DataExtractor extractor(data.GetBytes(), data.GetByteSize(), - m_process->GetByteOrder(), - m_process->GetAddressByteSize()); - ItemInfo item = ExtractItemInfoFromBuffer(extractor); - queue_item->SetItemThatEnqueuedThis(item.item_that_enqueued_this); - queue_item->SetEnqueueingThreadID(item.enqueuing_thread_id); - queue_item->SetEnqueueingQueueID(item.enqueuing_queue_serialnum); - queue_item->SetStopID(item.stop_id); - queue_item->SetEnqueueingBacktrace(item.enqueuing_callstack); - queue_item->SetThreadLabel(item.enqueuing_thread_label); - queue_item->SetQueueLabel(item.enqueuing_queue_label); - queue_item->SetTargetQueueLabel(item.target_queue_label); - } - m_page_to_free = ret.item_buffer_ptr; - m_page_to_free_size = ret.item_buffer_size; - } -} - -void SystemRuntimeMacOSX::PopulateQueuesUsingLibBTR( - lldb::addr_t queues_buffer, uint64_t queues_buffer_size, uint64_t count, - lldb_private::QueueList &queue_list) { - Status error; - DataBufferHeap data(queues_buffer_size, 0); - Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_SYSTEM_RUNTIME)); - if (m_process->ReadMemory(queues_buffer, data.GetBytes(), queues_buffer_size, - error) == queues_buffer_size && - error.Success()) { - // We've read the information out of inferior memory; free it on the next - // call we make - m_page_to_free = queues_buffer; - m_page_to_free_size = queues_buffer_size; - - DataExtractor extractor(data.GetBytes(), data.GetByteSize(), - m_process->GetByteOrder(), - m_process->GetAddressByteSize()); - offset_t offset = 0; - uint64_t queues_read = 0; - - // The information about the queues is stored in this format (v1): typedef - // struct introspection_dispatch_queue_info_s { - // uint32_t offset_to_next; - // dispatch_queue_t queue; - // uint64_t serialnum; // queue's serialnum in the process, as - // provided by libdispatch - // uint32_t running_work_items_count; - // uint32_t pending_work_items_count; - // - // char data[]; // Starting here, we have variable-length data: - // // char queue_label[]; - // } introspection_dispatch_queue_info_s; - - while (queues_read < count && offset < queues_buffer_size) { - offset_t start_of_this_item = offset; - - uint32_t offset_to_next = extractor.GetU32(&offset); - - offset += 4; // Skip over the 4 bytes of reserved space - addr_t queue = extractor.GetPointer(&offset); - uint64_t serialnum = extractor.GetU64(&offset); - uint32_t running_work_items_count = extractor.GetU32(&offset); - uint32_t pending_work_items_count = extractor.GetU32(&offset); - - // Read the first field of the variable length data - offset = start_of_this_item + - m_lib_backtrace_recording_info.queue_info_data_offset; - const char *queue_label = extractor.GetCStr(&offset); - if (queue_label == NULL) - queue_label = ""; - - offset_t start_of_next_item = start_of_this_item + offset_to_next; - offset = start_of_next_item; - - if (log) - log->Printf("SystemRuntimeMacOSX::PopulateQueuesUsingLibBTR added " - "queue with dispatch_queue_t 0x%" PRIx64 - ", serial number 0x%" PRIx64 - ", running items %d, pending items %d, name '%s'", - queue, serialnum, running_work_items_count, - pending_work_items_count, queue_label); - - QueueSP queue_sp( - new Queue(m_process->shared_from_this(), serialnum, queue_label)); - queue_sp->SetNumRunningWorkItems(running_work_items_count); - queue_sp->SetNumPendingWorkItems(pending_work_items_count); - queue_sp->SetLibdispatchQueueAddress(queue); - queue_sp->SetKind(GetQueueKind(queue)); - queue_list.AddQueue(queue_sp); - queues_read++; - } - } -} - -SystemRuntimeMacOSX::ItemInfo SystemRuntimeMacOSX::ExtractItemInfoFromBuffer( - lldb_private::DataExtractor &extractor) { - ItemInfo item; - - offset_t offset = 0; - - item.item_that_enqueued_this = extractor.GetPointer(&offset); - item.function_or_block = extractor.GetPointer(&offset); - item.enqueuing_thread_id = extractor.GetU64(&offset); - item.enqueuing_queue_serialnum = extractor.GetU64(&offset); - item.target_queue_serialnum = extractor.GetU64(&offset); - item.enqueuing_callstack_frame_count = extractor.GetU32(&offset); - item.stop_id = extractor.GetU32(&offset); - - offset = m_lib_backtrace_recording_info.item_info_data_offset; - - for (uint32_t i = 0; i < item.enqueuing_callstack_frame_count; i++) { - item.enqueuing_callstack.push_back(extractor.GetPointer(&offset)); - } - item.enqueuing_thread_label = extractor.GetCStr(&offset); - item.enqueuing_queue_label = extractor.GetCStr(&offset); - item.target_queue_label = extractor.GetCStr(&offset); - - return item; -} - -void SystemRuntimeMacOSX::Initialize() { - PluginManager::RegisterPlugin(GetPluginNameStatic(), - GetPluginDescriptionStatic(), CreateInstance); -} - -void SystemRuntimeMacOSX::Terminate() { - PluginManager::UnregisterPlugin(CreateInstance); -} - -lldb_private::ConstString SystemRuntimeMacOSX::GetPluginNameStatic() { - static ConstString g_name("systemruntime-macosx"); - return g_name; -} - -const char *SystemRuntimeMacOSX::GetPluginDescriptionStatic() { - return "System runtime plugin for Mac OS X native libraries."; -} - -//------------------------------------------------------------------ -// PluginInterface protocol -//------------------------------------------------------------------ -lldb_private::ConstString SystemRuntimeMacOSX::GetPluginName() { - return GetPluginNameStatic(); -} - -uint32_t SystemRuntimeMacOSX::GetPluginVersion() { return 1; } diff --git a/source/Plugins/SystemRuntime/MacOSX/SystemRuntimeMacOSX.h b/source/Plugins/SystemRuntime/MacOSX/SystemRuntimeMacOSX.h deleted file mode 100644 index 5fa78cee4640..000000000000 --- a/source/Plugins/SystemRuntime/MacOSX/SystemRuntimeMacOSX.h +++ /dev/null @@ -1,299 +0,0 @@ -//===-- SystemRuntimeMacOSX.h -----------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef liblldb_SystemRuntimeMacOSX_h_ -#define liblldb_SystemRuntimeMacOSX_h_ - -#include <mutex> -#include <string> -#include <vector> - -// Other libraries and framework include -#include "lldb/Core/ModuleList.h" -#include "lldb/Target/Process.h" -#include "lldb/Target/QueueItem.h" -#include "lldb/Target/SystemRuntime.h" -#include "lldb/Utility/ConstString.h" -#include "lldb/Utility/FileSpec.h" -#include "lldb/Utility/StructuredData.h" -#include "lldb/Utility/UUID.h" - -#include "AppleGetItemInfoHandler.h" -#include "AppleGetPendingItemsHandler.h" -#include "AppleGetQueuesHandler.h" -#include "AppleGetThreadItemInfoHandler.h" - -class SystemRuntimeMacOSX : public lldb_private::SystemRuntime { -public: - SystemRuntimeMacOSX(lldb_private::Process *process); - - ~SystemRuntimeMacOSX() override; - - //------------------------------------------------------------------ - // Static Functions - //------------------------------------------------------------------ - static void Initialize(); - - static void Terminate(); - - static lldb_private::ConstString GetPluginNameStatic(); - - static const char *GetPluginDescriptionStatic(); - - static lldb_private::SystemRuntime * - CreateInstance(lldb_private::Process *process); - - //------------------------------------------------------------------ - // instance methods - //------------------------------------------------------------------ - - void Clear(bool clear_process); - - void Detach() override; - - const std::vector<lldb_private::ConstString> & - GetExtendedBacktraceTypes() override; - - lldb::ThreadSP - GetExtendedBacktraceThread(lldb::ThreadSP thread, - lldb_private::ConstString type) override; - - lldb::ThreadSP - GetExtendedBacktraceForQueueItem(lldb::QueueItemSP queue_item_sp, - lldb_private::ConstString type) override; - - lldb::ThreadSP GetExtendedBacktraceFromItemRef(lldb::addr_t item_ref); - - void PopulateQueueList(lldb_private::QueueList &queue_list) override; - - void PopulateQueuesUsingLibBTR(lldb::addr_t queues_buffer, - uint64_t queues_buffer_size, uint64_t count, - lldb_private::QueueList &queue_list); - - void PopulatePendingQueuesUsingLibBTR(lldb::addr_t items_buffer, - uint64_t items_buffer_size, - uint64_t count, - lldb_private::Queue *queue); - - std::string - GetQueueNameFromThreadQAddress(lldb::addr_t dispatch_qaddr) override; - - lldb::queue_id_t - GetQueueIDFromThreadQAddress(lldb::addr_t dispatch_qaddr) override; - - lldb::addr_t GetLibdispatchQueueAddressFromThreadQAddress( - lldb::addr_t dispatch_qaddr) override; - - void PopulatePendingItemsForQueue(lldb_private::Queue *queue) override; - - void CompleteQueueItem(lldb_private::QueueItem *queue_item, - lldb::addr_t item_ref) override; - - lldb::QueueKind GetQueueKind(lldb::addr_t dispatch_queue_addr) override; - - void AddThreadExtendedInfoPacketHints( - lldb_private::StructuredData::ObjectSP dict) override; - - bool SafeToCallFunctionsOnThisThread(lldb::ThreadSP thread_sp) override; - - //------------------------------------------------------------------ - // PluginInterface protocol - //------------------------------------------------------------------ - lldb_private::ConstString GetPluginName() override; - - uint32_t GetPluginVersion() override; - -protected: - lldb::user_id_t m_break_id; - mutable std::recursive_mutex m_mutex; - -private: - struct libBacktraceRecording_info { - uint16_t queue_info_version; - uint16_t queue_info_data_offset; - uint16_t item_info_version; - uint16_t item_info_data_offset; - - libBacktraceRecording_info() - : queue_info_version(0), queue_info_data_offset(0), - item_info_version(0), item_info_data_offset(0) {} - }; - - // A structure which reflects the data recorded in the - // libBacktraceRecording introspection_dispatch_item_info_s. - struct ItemInfo { - lldb::addr_t item_that_enqueued_this; - lldb::addr_t function_or_block; - uint64_t enqueuing_thread_id; - uint64_t enqueuing_queue_serialnum; - uint64_t target_queue_serialnum; - uint32_t enqueuing_callstack_frame_count; - uint32_t stop_id; - std::vector<lldb::addr_t> enqueuing_callstack; - std::string enqueuing_thread_label; - std::string enqueuing_queue_label; - std::string target_queue_label; - }; - - // The offsets of different fields of the dispatch_queue_t structure in - // a thread/queue process. - // Based on libdispatch src/queue_private.h, struct dispatch_queue_offsets_s - // With dqo_version 1-3, the dqo_label field is a per-queue value and cannot - // be cached. - // With dqo_version 4 (Mac OS X 10.9 / iOS 7), dqo_label is a constant value - // that can be cached. - struct LibdispatchOffsets { - uint16_t dqo_version; - uint16_t dqo_label; - uint16_t dqo_label_size; - uint16_t dqo_flags; - uint16_t dqo_flags_size; - uint16_t dqo_serialnum; - uint16_t dqo_serialnum_size; - uint16_t dqo_width; - uint16_t dqo_width_size; - uint16_t dqo_running; - uint16_t dqo_running_size; - - uint16_t dqo_suspend_cnt; // version 5 and later, starting with Mac OS X - // 10.10/iOS 8 - uint16_t dqo_suspend_cnt_size; // version 5 and later, starting with Mac OS - // X 10.10/iOS 8 - uint16_t dqo_target_queue; // version 5 and later, starting with Mac OS X - // 10.10/iOS 8 - uint16_t dqo_target_queue_size; // version 5 and later, starting with Mac OS - // X 10.10/iOS 8 - uint16_t - dqo_priority; // version 5 and later, starting with Mac OS X 10.10/iOS 8 - uint16_t dqo_priority_size; // version 5 and later, starting with Mac OS X - // 10.10/iOS 8 - - LibdispatchOffsets() { - dqo_version = UINT16_MAX; - dqo_flags = UINT16_MAX; - dqo_serialnum = UINT16_MAX; - dqo_label = UINT16_MAX; - dqo_width = UINT16_MAX; - dqo_running = UINT16_MAX; - dqo_suspend_cnt = UINT16_MAX; - dqo_target_queue = UINT16_MAX; - dqo_target_queue = UINT16_MAX; - dqo_priority = UINT16_MAX; - } - - bool IsValid() { return dqo_version != UINT16_MAX; } - - bool LabelIsValid() { return dqo_label != UINT16_MAX; } - }; - - struct LibdispatchVoucherOffsets { - uint16_t vo_version; - uint16_t vo_activity_ids_count; - uint16_t vo_activity_ids_count_size; - uint16_t vo_activity_ids_array; - uint16_t vo_activity_ids_array_entry_size; - - LibdispatchVoucherOffsets() - : vo_version(UINT16_MAX), vo_activity_ids_count(UINT16_MAX), - vo_activity_ids_count_size(UINT16_MAX), - vo_activity_ids_array(UINT16_MAX), - vo_activity_ids_array_entry_size(UINT16_MAX) {} - - bool IsValid() { return vo_version != UINT16_MAX; } - }; - - struct LibdispatchTSDIndexes { - uint16_t dti_version; - uint64_t dti_queue_index; - uint64_t dti_voucher_index; - uint64_t dti_qos_class_index; - - LibdispatchTSDIndexes() - : dti_version(UINT16_MAX), dti_queue_index(UINT64_MAX), - dti_voucher_index(UINT64_MAX), dti_qos_class_index(UINT64_MAX) {} - - bool IsValid() { return dti_version != UINT16_MAX; } - }; - - struct LibpthreadOffsets { - uint16_t plo_version; - uint16_t plo_pthread_tsd_base_offset; - uint16_t plo_pthread_tsd_base_address_offset; - uint16_t plo_pthread_tsd_entry_size; - - LibpthreadOffsets() - : plo_version(UINT16_MAX), plo_pthread_tsd_base_offset(UINT16_MAX), - plo_pthread_tsd_base_address_offset(UINT16_MAX), - plo_pthread_tsd_entry_size(UINT16_MAX) {} - - bool IsValid() { return plo_version != UINT16_MAX; } - }; - - // The libBacktraceRecording function - // __introspection_dispatch_queue_get_pending_items has - // two forms. It can either return a simple array of item_refs (void *) size - // or it can return - // a header with uint32_t version, a uint32_t size of item, and then an array - // of item_refs (void*) - // and code addresses (void*) for all the pending blocks. - - struct ItemRefAndCodeAddress { - lldb::addr_t item_ref; - lldb::addr_t code_address; - }; - - struct PendingItemsForQueue { - bool new_style; // new-style means both item_refs and code_addresses avail - // old-style means only item_refs is filled in - std::vector<ItemRefAndCodeAddress> item_refs_and_code_addresses; - }; - - bool BacktraceRecordingHeadersInitialized(); - - void ReadLibdispatchOffsetsAddress(); - - void ReadLibdispatchOffsets(); - - void ReadLibpthreadOffsetsAddress(); - - void ReadLibpthreadOffsets(); - - void ReadLibdispatchTSDIndexesAddress(); - - void ReadLibdispatchTSDIndexes(); - - PendingItemsForQueue GetPendingItemRefsForQueue(lldb::addr_t queue); - - ItemInfo ExtractItemInfoFromBuffer(lldb_private::DataExtractor &extractor); - - lldb_private::AppleGetQueuesHandler m_get_queues_handler; - lldb_private::AppleGetPendingItemsHandler m_get_pending_items_handler; - lldb_private::AppleGetItemInfoHandler m_get_item_info_handler; - lldb_private::AppleGetThreadItemInfoHandler m_get_thread_item_info_handler; - - lldb::addr_t m_page_to_free; - uint64_t m_page_to_free_size; - libBacktraceRecording_info m_lib_backtrace_recording_info; - - lldb::addr_t m_dispatch_queue_offsets_addr; - struct LibdispatchOffsets m_libdispatch_offsets; - - lldb::addr_t m_libpthread_layout_offsets_addr; - struct LibpthreadOffsets m_libpthread_offsets; - - lldb::addr_t m_dispatch_tsd_indexes_addr; - struct LibdispatchTSDIndexes m_libdispatch_tsd_indexes; - - lldb::addr_t m_dispatch_voucher_offsets_addr; - struct LibdispatchVoucherOffsets m_libdispatch_voucher_offsets; - - DISALLOW_COPY_AND_ASSIGN(SystemRuntimeMacOSX); -}; - -#endif // liblldb_SystemRuntimeMacOSX_h_ |
