diff options
-rw-r--r-- | lldb/include/lldb/Target/Thread.h | 32 | ||||
-rw-r--r-- | lldb/lldb.xcodeproj/project.pbxproj | 24 | ||||
-rw-r--r-- | lldb/source/CMakeLists.txt | 1 | ||||
-rw-r--r-- | lldb/source/Plugins/Process/Utility/HistoryThread.cpp | 3 | ||||
-rw-r--r-- | lldb/source/Plugins/Process/Utility/HistoryThread.h | 27 | ||||
-rw-r--r-- | lldb/source/Plugins/SystemRuntime/CMakeLists.txt | 3 | ||||
-rw-r--r-- | lldb/source/Plugins/SystemRuntime/MacOSX/CMakeLists.txt | 5 | ||||
-rw-r--r-- | lldb/source/Plugins/SystemRuntime/MacOSX/SystemRuntimeMacOSX.cpp | 422 | ||||
-rw-r--r-- | lldb/source/Plugins/SystemRuntime/MacOSX/SystemRuntimeMacOSX.h | 174 | ||||
-rw-r--r-- | lldb/source/Target/Process.cpp | 1 | ||||
-rw-r--r-- | lldb/source/lldb.cpp | 3 |
11 files changed, 694 insertions, 1 deletions
diff --git a/lldb/include/lldb/Target/Thread.h b/lldb/include/lldb/Target/Thread.h index a5962bb284a..cf084dd059c 100644 --- a/lldb/include/lldb/Target/Thread.h +++ b/lldb/include/lldb/Target/Thread.h @@ -285,6 +285,11 @@ public: return NULL; } + virtual void + SetQueueName (const char *name) + { + } + virtual uint32_t GetStackFrameCount() { @@ -912,6 +917,33 @@ public: void SetShouldReportStop (Vote vote); + //---------------------------------------------------------------------- + /// Sets the extended backtrace token for this thread + /// + /// Some Thread subclasses may maintain a token to help with providing + /// an extended backtrace. The SystemRuntime plugin will set/request this. + /// + /// @param [in] token + //---------------------------------------------------------------------- + virtual void + SetExtendedBacktraceToken (uint64_t token) { } + + //---------------------------------------------------------------------- + /// Gets the extended backtrace token for this thread + /// + /// Some Thread subclasses may maintain a token to help with providing + /// an extended backtrace. The SystemRuntime plugin will set/request this. + /// + /// @return + /// The token needed by the SystemRuntime to create an extended backtrace. + /// LLDB_INVALID_ADDRESS is returned if no token is available. + //---------------------------------------------------------------------- + virtual uint64_t + GetExtendedBacktraceToken () + { + return LLDB_INVALID_ADDRESS; + } + protected: friend class ThreadPlan; diff --git a/lldb/lldb.xcodeproj/project.pbxproj b/lldb/lldb.xcodeproj/project.pbxproj index 89bc003bc28..b7702d70b41 100644 --- a/lldb/lldb.xcodeproj/project.pbxproj +++ b/lldb/lldb.xcodeproj/project.pbxproj @@ -611,6 +611,8 @@ AF37E10A17C861F20061E18E /* ProcessRunLock.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AF37E10917C861F20061E18E /* ProcessRunLock.cpp */; }; AF81DEFA1828A23F0042CF19 /* SystemRuntime.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AF81DEF91828A23F0042CF19 /* SystemRuntime.cpp */; }; AF90106515AB7D3600FF120D /* lldb.1 in CopyFiles */ = {isa = PBXBuildFile; fileRef = AF90106315AB7C5700FF120D /* lldb.1 */; }; + AF9B8F33182DB52900DA866F /* SystemRuntimeMacOSX.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AF9B8F31182DB52900DA866F /* SystemRuntimeMacOSX.cpp */; }; + AF9B8F34182DB52900DA866F /* SystemRuntimeMacOSX.h in Headers */ = {isa = PBXBuildFile; fileRef = AF9B8F32182DB52900DA866F /* SystemRuntimeMacOSX.h */; }; AFF87C87150FF669000E1742 /* com.apple.debugserver.plist in CopyFiles */ = {isa = PBXBuildFile; fileRef = AFF87C86150FF669000E1742 /* com.apple.debugserver.plist */; }; AFF87C89150FF672000E1742 /* com.apple.debugserver-secure.plist in CopyFiles */ = {isa = PBXBuildFile; fileRef = AFF87C88150FF672000E1742 /* com.apple.debugserver-secure.plist */; }; AFF87C8F150FF688000E1742 /* com.apple.debugserver.applist.plist in CopyFiles */ = {isa = PBXBuildFile; fileRef = AFF87C8E150FF688000E1742 /* com.apple.debugserver.applist.plist */; }; @@ -1761,6 +1763,8 @@ AF81DEF91828A23F0042CF19 /* SystemRuntime.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SystemRuntime.cpp; path = source/Target/SystemRuntime.cpp; sourceTree = "<group>"; }; AF90106315AB7C5700FF120D /* lldb.1 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.man; name = lldb.1; path = docs/lldb.1; sourceTree = "<group>"; }; AF94005711C03F6500085DB9 /* SymbolVendor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SymbolVendor.cpp; path = source/Symbol/SymbolVendor.cpp; sourceTree = "<group>"; }; + AF9B8F31182DB52900DA866F /* SystemRuntimeMacOSX.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SystemRuntimeMacOSX.cpp; sourceTree = "<group>"; }; + AF9B8F32182DB52900DA866F /* SystemRuntimeMacOSX.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SystemRuntimeMacOSX.h; sourceTree = "<group>"; }; AFF87C86150FF669000E1742 /* com.apple.debugserver.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = com.apple.debugserver.plist; path = tools/debugserver/source/com.apple.debugserver.plist; sourceTree = "<group>"; }; AFF87C88150FF672000E1742 /* com.apple.debugserver-secure.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = "com.apple.debugserver-secure.plist"; path = "tools/debugserver/source/com.apple.debugserver-secure.plist"; sourceTree = "<group>"; }; AFF87C8A150FF677000E1742 /* com.apple.debugserver.applist.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = com.apple.debugserver.applist.plist; path = tools/debugserver/source/com.apple.debugserver.applist.plist; sourceTree = "<group>"; }; @@ -1935,6 +1939,7 @@ 266DFE9013FD64D200D0C574 /* OperatingSystem */, 26C5577E132575B6008FD8FE /* Platform */, 260C898A10F57C5600BB2B04 /* Process */, + AF11CB34182CA85A00D9B618 /* SystemRuntime */, 260C89B110F57C5600BB2B04 /* SymbolFile */, 260C89E010F57C5600BB2B04 /* SymbolVendor */, 26AC3F441365F40E0065C7EF /* UnwindAssembly */, @@ -3518,6 +3523,23 @@ name = DataFormatters; sourceTree = "<group>"; }; + AF11CB34182CA85A00D9B618 /* SystemRuntime */ = { + isa = PBXGroup; + children = ( + AF11CB35182CA85A00D9B618 /* MacOSX */, + ); + path = SystemRuntime; + sourceTree = "<group>"; + }; + AF11CB35182CA85A00D9B618 /* MacOSX */ = { + isa = PBXGroup; + children = ( + AF9B8F31182DB52900DA866F /* SystemRuntimeMacOSX.cpp */, + AF9B8F32182DB52900DA866F /* SystemRuntimeMacOSX.h */, + ); + path = MacOSX; + sourceTree = "<group>"; + }; EDC6D49114E5C15C001B75F8 /* launcherXPCService */ = { isa = PBXGroup; children = ( @@ -3626,6 +3648,7 @@ 260CC63215D04377002BF2E0 /* OptionValueDictionary.h in Headers */, 260CC63315D04377002BF2E0 /* OptionValueEnumeration.h in Headers */, 260CC63415D04377002BF2E0 /* OptionValueFileSpec.h in Headers */, + AF9B8F34182DB52900DA866F /* SystemRuntimeMacOSX.h in Headers */, 26D1804716CEE12C00EDFB5B /* TimeSpecTimeout.h in Headers */, 260CC63515D04377002BF2E0 /* OptionValueFileSpecList.h in Headers */, 490A36C2180F0E9300BA31F8 /* PlatformWindows.h in Headers */, @@ -4150,6 +4173,7 @@ 2689007D13353E2200698AC0 /* Args.cpp in Sources */, 2689007F13353E2200698AC0 /* CommandCompletions.cpp in Sources */, 2689008013353E2200698AC0 /* CommandInterpreter.cpp in Sources */, + AF9B8F33182DB52900DA866F /* SystemRuntimeMacOSX.cpp in Sources */, 2689008113353E2200698AC0 /* CommandObject.cpp in Sources */, 2689008313353E2200698AC0 /* CommandObjectMultiword.cpp in Sources */, 2689008413353E2200698AC0 /* CommandObjectRegexCommand.cpp in Sources */, diff --git a/lldb/source/CMakeLists.txt b/lldb/source/CMakeLists.txt index 4cf7e2b9c64..9e112cf09c3 100644 --- a/lldb/source/CMakeLists.txt +++ b/lldb/source/CMakeLists.txt @@ -119,6 +119,7 @@ if ( CMAKE_SYSTEM_NAME MATCHES "Darwin" ) lldbPluginDynamicLoaderDarwinKernel lldbPluginProcessMacOSXKernel lldbPluginSymbolVendorMacOSX + lldbPluginSystemRuntimeMacOSX ) endif() diff --git a/lldb/source/Plugins/Process/Utility/HistoryThread.cpp b/lldb/source/Plugins/Process/Utility/HistoryThread.cpp index e612b6f3bf2..b63b61f7772 100644 --- a/lldb/source/Plugins/Process/Utility/HistoryThread.cpp +++ b/lldb/source/Plugins/Process/Utility/HistoryThread.cpp @@ -29,7 +29,8 @@ HistoryThread::HistoryThread (lldb_private::Process &process, m_framelist(), m_pcs (pcs), m_stop_id (stop_id), - m_stop_id_is_valid (stop_id_is_valid) + m_stop_id_is_valid (stop_id_is_valid), + m_extended_unwind_token (LLDB_INVALID_ADDRESS) { m_unwinder_ap.reset (new HistoryUnwind (*this, pcs, stop_id, stop_id_is_valid)); Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT)); diff --git a/lldb/source/Plugins/Process/Utility/HistoryThread.h b/lldb/source/Plugins/Process/Utility/HistoryThread.h index ba87ffa07d9..1a646c7da34 100644 --- a/lldb/source/Plugins/Process/Utility/HistoryThread.h +++ b/lldb/source/Plugins/Process/Utility/HistoryThread.h @@ -41,6 +41,30 @@ public: bool CalculateStopInfo () { return false; } + void + SetExtendedBacktraceToken (uint64_t token) + { + m_extended_unwind_token = token; + } + + uint64_t + GetExtendedBacktraceToken () + { + return m_extended_unwind_token; + } + + const char * + GetQueueName () + { + return m_queue_name.c_str(); + } + + void + SetQueueName (const char *name) + { + m_queue_name = name; + } + protected: virtual lldb::StackFrameListSP GetStackFrameList (); @@ -50,6 +74,9 @@ protected: std::vector<lldb::addr_t> m_pcs; uint32_t m_stop_id; bool m_stop_id_is_valid; + + uint64_t m_extended_unwind_token; + std::string m_queue_name; }; } // namespace lldb_private diff --git a/lldb/source/Plugins/SystemRuntime/CMakeLists.txt b/lldb/source/Plugins/SystemRuntime/CMakeLists.txt new file mode 100644 index 00000000000..3b7b1bf6565 --- /dev/null +++ b/lldb/source/Plugins/SystemRuntime/CMakeLists.txt @@ -0,0 +1,3 @@ +if (CMAKE_SYSTEM_NAME MATCHES "Darwin") + add_subdirectory(MacOSX) +endif() diff --git a/lldb/source/Plugins/SystemRuntime/MacOSX/CMakeLists.txt b/lldb/source/Plugins/SystemRuntime/MacOSX/CMakeLists.txt new file mode 100644 index 00000000000..4fc1356f70f --- /dev/null +++ b/lldb/source/Plugins/SystemRuntime/MacOSX/CMakeLists.txt @@ -0,0 +1,5 @@ +set(LLVM_NO_RTTI 1) + +add_lldb_library(lldbPluginSystemRuntimeMacOSX + SystemRuntimeMacOSX.cpp + ) diff --git a/lldb/source/Plugins/SystemRuntime/MacOSX/SystemRuntimeMacOSX.cpp b/lldb/source/Plugins/SystemRuntime/MacOSX/SystemRuntimeMacOSX.cpp new file mode 100644 index 00000000000..ba52ce55f1f --- /dev/null +++ b/lldb/source/Plugins/SystemRuntime/MacOSX/SystemRuntimeMacOSX.cpp @@ -0,0 +1,422 @@ +//===-- 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 "lldb/Breakpoint/StoppointCallbackContext.h" +#include "lldb/Core/Log.h" +#include "lldb/Core/Module.h" +#include "lldb/Core/ModuleSpec.h" +#include "lldb/Core/PluginManager.h" +#include "lldb/Core/DataExtractor.h" +#include "lldb/Core/DataBufferHeap.h" +#include "lldb/Core/Section.h" +#include "lldb/Expression/ClangFunction.h" +#include "lldb/Expression/ClangUtilityFunction.h" +#include "lldb/Host/FileSpec.h" +#include "lldb/Symbol/ObjectFile.h" +#include "lldb/Symbol/SymbolContext.h" +#include "Plugins/Process/Utility/HistoryThread.h" +#include "lldb/Target/Target.h" +#include "lldb/Target/Thread.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: + 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(Mutex::eMutexTypeRecursive) +{ + m_ldi_header.initialized = 0; +} + +//---------------------------------------------------------------------- +// Destructor +//---------------------------------------------------------------------- +SystemRuntimeMacOSX::~SystemRuntimeMacOSX() +{ + Clear (true); +} + +//---------------------------------------------------------------------- +// Clear out the state of this class. +//---------------------------------------------------------------------- +void +SystemRuntimeMacOSX::Clear (bool clear_process) +{ + Mutex::Locker locker(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; + m_ldi_header.initialized = 0; +} + + +void +SystemRuntimeMacOSX::DidAttach () +{ +} + +void +SystemRuntimeMacOSX::DidLaunch () +{ +} + +void +SystemRuntimeMacOSX::ModulesDidLoad (ModuleList &module_list) +{ +} + +bool +SystemRuntimeMacOSX::LdiHeadersInitialized () +{ + ParseLdiHeaders(); + return m_ldi_header.initialized; +} + +void +SystemRuntimeMacOSX::ParseLdiHeaders () +{ + if (m_ldi_header.initialized) + return; + static ConstString ldi_header_symbol ("ldi_infos"); + SymbolContextList sc_list; + if (m_process->GetTarget().GetImages().FindSymbolsWithNameAndType (ldi_header_symbol, eSymbolTypeData, sc_list) > 0) + { + SymbolContext sc; + sc_list.GetContextAtIndex (0, sc); + AddressRange addr_range; + sc.GetAddressRange (eSymbolContextSymbol, 0, false, addr_range); + + Error error; + Address ldi_header_addr = addr_range.GetBaseAddress(); + uint8_t version_buf[6]; // version, ldi_header_size, initialized fields + DataExtractor data (version_buf, sizeof(version_buf), m_process->GetByteOrder(), m_process->GetAddressByteSize()); + const size_t count = sizeof (version_buf); + const bool prefer_file_cache = false; + if (m_process->GetTarget().ReadMemory (ldi_header_addr, prefer_file_cache, version_buf, count, error) == sizeof (version_buf)) + { + int version, initialized, ldi_header_size; + offset_t offset = 0; + version = data.GetU16(&offset); + ldi_header_size = data.GetU16(&offset); + initialized = data.GetU16(&offset); + if (initialized) + { + DataBufferHeap ldi_header (ldi_header_size, 0); + DataExtractor ldi_extractor (ldi_header.GetBytes(), ldi_header.GetByteSize(), m_process->GetByteOrder(), m_process->GetAddressByteSize()); + if (m_process->GetTarget().ReadMemory (ldi_header_addr, prefer_file_cache, ldi_header.GetBytes(), ldi_header.GetByteSize(), error) == ldi_header.GetByteSize()) + { + offset = 0; + m_ldi_header.version = ldi_extractor.GetU16(&offset); + m_ldi_header.ldi_header_size = ldi_extractor.GetU16(&offset); + m_ldi_header.initialized = ldi_extractor.GetU16(&offset); + m_ldi_header.queue_size = ldi_extractor.GetU16(&offset); + m_ldi_header.item_size = ldi_extractor.GetU16(&offset); + + // 6 bytes of padding here + offset += 6; + + m_ldi_header.queues_head_ptr_address = ldi_extractor.GetU64(&offset); + m_ldi_header.items_head_ptr_address = ldi_extractor.GetU64(&offset); + + m_ldi_header.queue_offsets.next = ldi_extractor.GetU16(&offset); + m_ldi_header.queue_offsets.prev = ldi_extractor.GetU16(&offset); + m_ldi_header.queue_offsets.queue_id = ldi_extractor.GetU16(&offset); + m_ldi_header.queue_offsets.current_item_ptr = ldi_extractor.GetU16(&offset); + + m_ldi_header.item_offsets.next = ldi_extractor.GetU16(&offset); + m_ldi_header.item_offsets.prev = ldi_extractor.GetU16(&offset); + m_ldi_header.item_offsets.type = ldi_extractor.GetU16(&offset); + m_ldi_header.item_offsets.identifier = ldi_extractor.GetU16(&offset); + m_ldi_header.item_offsets.stop_id = ldi_extractor.GetU16(&offset); + m_ldi_header.item_offsets.backtrace_length = ldi_extractor.GetU16(&offset); + m_ldi_header.item_offsets.backtrace_ptr = ldi_extractor.GetU16(&offset); + m_ldi_header.item_offsets.thread_name_ptr = ldi_extractor.GetU16(&offset); + m_ldi_header.item_offsets.queue_name_ptr = ldi_extractor.GetU16(&offset); + m_ldi_header.item_offsets.unique_thread_id = ldi_extractor.GetU16(&offset); + m_ldi_header.item_offsets.pthread_id = ldi_extractor.GetU16(&offset); + m_ldi_header.item_offsets.enqueueing_thread_dispatch_queue_t = ldi_extractor.GetU16(&offset); + m_ldi_header.item_offsets.enqueueing_thread_dispatch_block_ptr = ldi_extractor.GetU16(&offset); + + } + } + } + } +} + +lldb::addr_t +SystemRuntimeMacOSX::GetQueuesHead () +{ + if (!LdiHeadersInitialized()) + return LLDB_INVALID_ADDRESS; + + Error error; + addr_t queues_head = m_process->ReadPointerFromMemory (m_ldi_header.queues_head_ptr_address, error); + if (error.Success() == false || queues_head == LLDB_INVALID_ADDRESS || queues_head == 0) + return LLDB_INVALID_ADDRESS; + + return queues_head; +} + +lldb::addr_t +SystemRuntimeMacOSX::GetItemsHead () +{ + if (!LdiHeadersInitialized()) + return LLDB_INVALID_ADDRESS; + + Error error; + addr_t items_head = m_process->ReadPointerFromMemory (m_ldi_header.items_head_ptr_address, error); + if (error.Success() == false || items_head == LLDB_INVALID_ADDRESS || items_head == 0) + return LLDB_INVALID_ADDRESS; + + return items_head; +} + +addr_t +SystemRuntimeMacOSX::GetThreadCreatorItem (ThreadSP thread_sp) +{ + addr_t enqueued_item_ptr = thread_sp->GetExtendedBacktraceToken(); + if (enqueued_item_ptr == LLDB_INVALID_ADDRESS) + { + if (thread_sp->GetQueueID() == LLDB_INVALID_QUEUE_ID || thread_sp->GetQueueID() == 0) + return LLDB_INVALID_ADDRESS; + + Error error; + uint64_t this_thread_queue_id = thread_sp->GetQueueID(); + + addr_t queues_head = GetQueuesHead(); + if (queues_head == LLDB_INVALID_ADDRESS) + return LLDB_INVALID_ADDRESS; + + // Step through the queues_head linked list looking for a queue matching this thread, if any + uint64_t queue_obj_ptr = queues_head; + enqueued_item_ptr = LLDB_INVALID_ADDRESS; + + while (queue_obj_ptr != 0) + { + uint64_t queue_id = m_process->ReadUnsignedIntegerFromMemory (queue_obj_ptr + m_ldi_header.queue_offsets.queue_id, 8, LLDB_INVALID_ADDRESS, error); + if (error.Success() && queue_id != LLDB_INVALID_ADDRESS) + { + if (queue_id == this_thread_queue_id) + { + enqueued_item_ptr = m_process->ReadPointerFromMemory (queue_obj_ptr + m_ldi_header.queue_offsets.current_item_ptr, error); + break; + } + } + queue_obj_ptr = m_process->ReadPointerFromMemory (queue_obj_ptr + m_ldi_header.queue_offsets.next, error); + if (error.Success() == false || queue_obj_ptr == LLDB_INVALID_ADDRESS) + { + break; + } + } + } + + return enqueued_item_ptr; +} + +SystemRuntimeMacOSX::ArchivedBacktrace +SystemRuntimeMacOSX::GetLibdispatchExtendedBacktrace (ThreadSP thread_sp) +{ + ArchivedBacktrace bt; + bt.stop_id = 0; + bt.stop_id_is_valid = false; + bt.libdispatch_queue_id = LLDB_INVALID_QUEUE_ID; + + addr_t enqueued_item_ptr = GetThreadCreatorItem (thread_sp); + + if (enqueued_item_ptr == LLDB_INVALID_ADDRESS) + return bt; + + Error error; + uint32_t ptr_size = m_process->GetTarget().GetArchitecture().GetAddressByteSize(); + + uint32_t backtrace_length = m_process->ReadUnsignedIntegerFromMemory (enqueued_item_ptr + m_ldi_header.item_offsets.backtrace_length, 4, 0, error); + addr_t pc_array_address = m_process->ReadPointerFromMemory (enqueued_item_ptr + m_ldi_header.item_offsets.backtrace_ptr, error); + + if (backtrace_length == 0 || pc_array_address == LLDB_INVALID_ADDRESS) + return bt; + + for (uint32_t idx = 0; idx < backtrace_length; idx++) + { + addr_t pc_val = m_process->ReadPointerFromMemory (pc_array_address + (ptr_size * idx), error); + if (error.Success() && pc_val != LLDB_INVALID_ADDRESS) + { + bt.pcs.push_back (pc_val); + } + } + + return bt; +} + +const std::vector<ConstString> & +SystemRuntimeMacOSX::GetExtendedBacktraceTypes () +{ + if (m_types.size () == 0) + { + m_types.push_back(ConstString("libdispatch")); + m_types.push_back(ConstString("pthread")); + } + return m_types; +} + +void +SystemRuntimeMacOSX::SetNewThreadQueueName (ThreadSP original_thread_sp, ThreadSP new_extended_thread_sp) +{ + addr_t enqueued_item_ptr = GetThreadCreatorItem (original_thread_sp); + + if (enqueued_item_ptr != LLDB_INVALID_ADDRESS) + { + Error error; + addr_t queue_name_ptr = m_process->ReadPointerFromMemory (enqueued_item_ptr + m_ldi_header.item_offsets.queue_name_ptr, error); + if (queue_name_ptr != LLDB_INVALID_ADDRESS && error.Success()) + { + char namebuf[256]; + if (m_process->ReadCStringFromMemory (queue_name_ptr, namebuf, sizeof (namebuf), error) > 0 && error.Success()) + { + new_extended_thread_sp->SetQueueName (namebuf); + } + } + } +} + +void +SystemRuntimeMacOSX::SetNewThreadExtendedBacktraceToken (ThreadSP original_thread_sp, ThreadSP new_extended_thread_sp) +{ + addr_t enqueued_item_ptr = GetThreadCreatorItem (original_thread_sp); + if (enqueued_item_ptr != LLDB_INVALID_ADDRESS) + { + Error error; + uint64_t further_extended_backtrace = m_process->ReadPointerFromMemory (enqueued_item_ptr + m_ldi_header.item_offsets.enqueueing_thread_dispatch_block_ptr, error); + if (error.Success() && further_extended_backtrace != 0 && further_extended_backtrace != LLDB_INVALID_ADDRESS) + { + new_extended_thread_sp->SetExtendedBacktraceToken (further_extended_backtrace); + } + } +} + +ThreadSP +SystemRuntimeMacOSX::GetExtendedBacktraceThread (ThreadSP original_thread_sp, ConstString type) +{ + ThreadSP new_extended_thread_sp; + + if (type != ConstString("libdispatch")) + return new_extended_thread_sp; + + ArchivedBacktrace bt = GetLibdispatchExtendedBacktrace (original_thread_sp); + + if (bt.pcs.size() == 0) + return new_extended_thread_sp; + + new_extended_thread_sp.reset (new HistoryThread (*m_process, bt.pcs, bt.stop_id, bt.stop_id_is_valid)); + + SetNewThreadQueueName(original_thread_sp, new_extended_thread_sp); + SetNewThreadExtendedBacktraceToken(original_thread_sp, new_extended_thread_sp); + + return new_extended_thread_sp; +} + + +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/lldb/source/Plugins/SystemRuntime/MacOSX/SystemRuntimeMacOSX.h b/lldb/source/Plugins/SystemRuntime/MacOSX/SystemRuntimeMacOSX.h new file mode 100644 index 00000000000..e8862d6166b --- /dev/null +++ b/lldb/source/Plugins/SystemRuntime/MacOSX/SystemRuntimeMacOSX.h @@ -0,0 +1,174 @@ +//===-- 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_ + +// C Includes +// C++ Includes +#include <map> +#include <vector> +#include <string> + +// Other libraries and framework includes +#include "llvm/Support/MachO.h" + +#include "lldb/Target/SystemRuntime.h" +#include "lldb/Host/FileSpec.h" +#include "lldb/Core/ConstString.h" +#include "lldb/Core/ModuleList.h" +#include "lldb/Core/UUID.h" +#include "lldb/Host/Mutex.h" +#include "lldb/Target/Process.h" + +class SystemRuntimeMacOSX : public lldb_private::SystemRuntime +{ +public: + //------------------------------------------------------------------ + // 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); + + SystemRuntimeMacOSX (lldb_private::Process *process); + + virtual + ~SystemRuntimeMacOSX (); + + void + Clear (bool clear_process); + + void + DidAttach (); + + void + DidLaunch(); + + void + ModulesDidLoad (lldb_private::ModuleList &module_list); + + const std::vector<lldb_private::ConstString> & + GetExtendedBacktraceTypes (); + + lldb::ThreadSP + GetExtendedBacktraceThread (lldb::ThreadSP thread, lldb_private::ConstString type); + + // REMOVE THE FOLLOWING 4 + bool + SetItemEnqueuedBreakpoint (); + + bool + DidSetItemEnqueuedBreakpoint () const; + + static bool + ItemEnqueuedCallback (void *baton, lldb_private::StoppointCallbackContext *context, lldb::user_id_t break_id, lldb::user_id_t break_loc_id); + + bool + ItemEnqueuedBreakpointHit (lldb_private::StoppointCallbackContext *context, lldb::user_id_t break_id, lldb::user_id_t break_loc_id); + + //------------------------------------------------------------------ + // PluginInterface protocol + //------------------------------------------------------------------ + virtual lldb_private::ConstString + GetPluginName(); + + virtual uint32_t + GetPluginVersion(); + +private: + struct ArchivedBacktrace { + uint32_t stop_id; + bool stop_id_is_valid; + lldb::queue_id_t libdispatch_queue_id; // LLDB_INVALID_QUEUE_ID if unavailable + std::vector<lldb::addr_t> pcs; + }; + + SystemRuntimeMacOSX::ArchivedBacktrace + GetLibdispatchExtendedBacktrace (lldb::ThreadSP thread); + +protected: + lldb::user_id_t m_break_id; + mutable lldb_private::Mutex m_mutex; + +private: + + void + ParseLdiHeaders (); + + bool + LdiHeadersInitialized (); + + lldb::addr_t + GetQueuesHead (); + + lldb::addr_t + GetItemsHead (); + + lldb::addr_t + GetThreadCreatorItem (lldb::ThreadSP thread); + + void + SetNewThreadQueueName (lldb::ThreadSP original_thread_sp, lldb::ThreadSP new_extended_thread_sp); + + void + SetNewThreadExtendedBacktraceToken (lldb::ThreadSP original_thread_sp, lldb::ThreadSP new_extended_thread_sp); + + struct ldi_queue_offsets { + uint16_t next; + uint16_t prev; + uint16_t queue_id; + uint16_t current_item_ptr; + }; + + struct ldi_item_offsets { + uint16_t next; + uint16_t prev; + uint16_t type; + uint16_t identifier; + uint16_t stop_id; + uint16_t backtrace_length; + uint16_t backtrace_ptr; + uint16_t thread_name_ptr; + uint16_t queue_name_ptr; + uint16_t unique_thread_id; + uint16_t pthread_id; + uint16_t enqueueing_thread_dispatch_queue_t; + uint16_t enqueueing_thread_dispatch_block_ptr; + }; + + struct ldi_header { + uint16_t version; + uint16_t ldi_header_size; + uint16_t initialized; // 0 means uninitialized + uint16_t queue_size; + uint16_t item_size; + uint64_t queues_head_ptr_address; // Address of queues head structure + uint64_t items_head_ptr_address; // Address of items_head + struct ldi_queue_offsets queue_offsets; + struct ldi_item_offsets item_offsets; + }; + + struct ldi_header m_ldi_header; + + DISALLOW_COPY_AND_ASSIGN (SystemRuntimeMacOSX); +}; + +#endif // liblldb_SystemRuntimeMacOSX_h_ diff --git a/lldb/source/Target/Process.cpp b/lldb/source/Target/Process.cpp index 1fe9ae9ca76..950df69152f 100644 --- a/lldb/source/Target/Process.cpp +++ b/lldb/source/Target/Process.cpp @@ -2354,6 +2354,7 @@ Process::DisableSoftwareBreakpoint (BreakpointSite *bp_site) size_t Process::ReadMemory (addr_t addr, void *buf, size_t size, Error &error) { + error.Clear(); if (!GetDisableMemoryCache()) { #if defined (VERIFY_MEMORY_READS) diff --git a/lldb/source/lldb.cpp b/lldb/source/lldb.cpp index c6956377391..78e8208e091 100644 --- a/lldb/source/lldb.cpp +++ b/lldb/source/lldb.cpp @@ -60,6 +60,7 @@ #include "Plugins/Platform/MacOSX/PlatformRemoteiOS.h" #include "Plugins/Platform/MacOSX/PlatformDarwinKernel.h" #include "Plugins/Platform/MacOSX/PlatformiOSSimulator.h" +#include "Plugins/SystemRuntime/MacOSX/SystemRuntimeMacOSX.h" #endif #include "Plugins/Process/mach-core/ProcessMachCore.h" @@ -139,6 +140,7 @@ lldb_private::Initialize () PlatformRemoteiOS::Initialize(); PlatformMacOSX::Initialize(); PlatformiOSSimulator::Initialize(); + SystemRuntimeMacOSX::Initialize(); #endif #if defined (__linux__) //---------------------------------------------------------------------- @@ -220,6 +222,7 @@ lldb_private::Terminate () PlatformDarwinKernel::Terminate(); PlatformRemoteiOS::Terminate(); PlatformiOSSimulator::Terminate(); + SystemRuntimeMacOSX::Terminate(); #endif Debugger::SettingsTerminate (); |