diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2019-10-23 17:53:01 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2019-10-23 17:53:01 +0000 |
commit | ead246455adf1a215ec2715dad6533073a6beb4e (patch) | |
tree | f3f97a47d77053bf96fe74cdbd6fae74380e8a92 /tools/lldb-mi/MICmnLLDBDebugger.cpp | |
parent | fdb00c4408990a0a63ef7f496d809ce59f263bc5 (diff) |
Notes
Diffstat (limited to 'tools/lldb-mi/MICmnLLDBDebugger.cpp')
-rw-r--r-- | tools/lldb-mi/MICmnLLDBDebugger.cpp | 905 |
1 files changed, 0 insertions, 905 deletions
diff --git a/tools/lldb-mi/MICmnLLDBDebugger.cpp b/tools/lldb-mi/MICmnLLDBDebugger.cpp deleted file mode 100644 index b22e7d9a1fe6..000000000000 --- a/tools/lldb-mi/MICmnLLDBDebugger.cpp +++ /dev/null @@ -1,905 +0,0 @@ -//===-- MICmnLLDBDebugger.cpp -----------------------------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -// Third party headers: -#include "lldb/API/SBCommandInterpreter.h" -#include "lldb/API/SBProcess.h" -#include "lldb/API/SBStream.h" -#include "lldb/API/SBTarget.h" -#include "lldb/API/SBThread.h" -#include "lldb/API/SBType.h" -#include "lldb/API/SBTypeCategory.h" -#include "lldb/API/SBTypeNameSpecifier.h" -#include "lldb/API/SBTypeSummary.h" -#include <cassert> - -// In-house headers: -#include "MICmnLLDBDebugSessionInfo.h" -#include "MICmnLLDBDebugger.h" -#include "MICmnLLDBDebuggerHandleEvents.h" -#include "MICmnLog.h" -#include "MICmnResources.h" -#include "MICmnThreadMgrStd.h" -#include "MIDriverBase.h" -#include "MIUtilSingletonHelper.h" - -//++ -// MI private summary providers -static inline bool MI_char_summary_provider(lldb::SBValue value, - lldb::SBTypeSummaryOptions options, - lldb::SBStream &stream) { - if (!value.IsValid()) - return false; - - lldb::SBType value_type = value.GetType(); - if (!value_type.IsValid()) - return false; - - lldb::BasicType type_code = value_type.GetBasicType(); - if (type_code == lldb::eBasicTypeSignedChar) - stream.Printf("%d %s", (int)value.GetValueAsSigned(), - CMIUtilString::WithNullAsEmpty(value.GetValue())); - else if (type_code == lldb::eBasicTypeUnsignedChar) - stream.Printf("%u %s", (unsigned)value.GetValueAsUnsigned(), - CMIUtilString::WithNullAsEmpty(value.GetValue())); - else - return false; - - return true; -} - -//++ -// MI summary helper routines -static inline bool MI_add_summary(lldb::SBTypeCategory category, - const char *typeName, - lldb::SBTypeSummary::FormatCallback cb, - uint32_t options, bool regex = false) { -#if defined(LLDB_DISABLE_PYTHON) - return false; -#else - lldb::SBTypeSummary summary = - lldb::SBTypeSummary::CreateWithCallback(cb, options); - return summary.IsValid() - ? category.AddTypeSummary( - lldb::SBTypeNameSpecifier(typeName, regex), summary) - : false; -#endif -} - -//++ -// Details: CMICmnLLDBDebugger constructor. -// Type: Method. -// Args: None. -// Return: None. -// Throws: None. -//-- -CMICmnLLDBDebugger::CMICmnLLDBDebugger() - : m_constStrThisThreadId("MI debugger event") {} - -//++ -// Details: CMICmnLLDBDebugger destructor. -// Type: Overridable. -// Args: None. -// Return: None. -// Throws: None. -//-- -CMICmnLLDBDebugger::~CMICmnLLDBDebugger() { Shutdown(); } - -//++ -// Details: Initialize resources for *this debugger object. -// Type: Method. -// Args: None. -// Return: MIstatus::success - Functionality succeeded. -// MIstatus::failure - Functionality failed. -// Throws: None. -//-- -bool CMICmnLLDBDebugger::Initialize() { - m_clientUsageRefCnt++; - - if (m_bInitialized) - return MIstatus::success; - - bool bOk = MIstatus::success; - CMIUtilString errMsg; - ClrErrorDescription(); - - if (m_pClientDriver == nullptr) { - bOk = false; - errMsg = MIRSRC(IDS_LLDBDEBUGGER_ERR_CLIENTDRIVER); - } - - // Note initialization order is important here as some resources depend on - // previous - MI::ModuleInit<CMICmnLog>(IDS_MI_INIT_ERR_LOG, bOk, errMsg); - MI::ModuleInit<CMICmnResources>(IDS_MI_INIT_ERR_RESOURCES, bOk, errMsg); - MI::ModuleInit<CMICmnThreadMgrStd>(IDS_MI_INIT_ERR_THREADMGR, bOk, errMsg); - MI::ModuleInit<CMICmnLLDBDebuggerHandleEvents>( - IDS_MI_INIT_ERR_OUTOFBANDHANDLER, bOk, errMsg); - MI::ModuleInit<CMICmnLLDBDebugSessionInfo>(IDS_MI_INIT_ERR_DEBUGSESSIONINFO, - bOk, errMsg); - - // Note order is important here! - if (bOk) - lldb::SBDebugger::Initialize(); - if (bOk && !InitSBDebugger()) { - bOk = false; - if (!errMsg.empty()) - errMsg += ", "; - errMsg += GetErrorDescription().c_str(); - } - if (bOk && !InitSBListener()) { - bOk = false; - if (!errMsg.empty()) - errMsg += ", "; - errMsg += GetErrorDescription().c_str(); - } - bOk = bOk && InitStdStreams(); - bOk = bOk && RegisterMISummaryProviders(); - m_bInitialized = bOk; - - if (!bOk && !HaveErrorDescription()) { - CMIUtilString strInitError(CMIUtilString::Format( - MIRSRC(IDS_MI_INIT_ERR_LLDBDEBUGGER), errMsg.c_str())); - SetErrorDescription(strInitError); - } - - return bOk; -} - -//++ -// Details: Release resources for *this debugger object. -// Type: Method. -// Args: None. -// Return: MIstatus::success - Functionality succeeded. -// MIstatus::failure - Functionality failed. -// Throws: None. -//-- -bool CMICmnLLDBDebugger::Shutdown() { - if (--m_clientUsageRefCnt > 0) - return MIstatus::success; - - if (!m_bInitialized) - return MIstatus::success; - - m_bInitialized = false; - - ClrErrorDescription(); - - bool bOk = MIstatus::success; - CMIUtilString errMsg; - - // Explicitly delete the remote target in case MI needs to exit prematurely - // otherwise - // LLDB debugger may hang in its Destroy() fn waiting on events - lldb::SBTarget sbTarget = CMICmnLLDBDebugSessionInfo::Instance().GetTarget(); - m_lldbDebugger.DeleteTarget(sbTarget); - - // Debug: May need this but does seem to work without it so commented out the - // fudge 19/06/2014 - // It appears we need to wait as hang does not occur when hitting a debug - // breakpoint here - // const std::chrono::milliseconds time( 1000 ); - // std::this_thread::sleep_for( time ); - - lldb::SBDebugger::Destroy(m_lldbDebugger); - lldb::SBDebugger::Terminate(); - m_pClientDriver = nullptr; - m_mapBroadcastClassNameToEventMask.clear(); - m_mapIdToEventMask.clear(); - - // Note shutdown order is important here - MI::ModuleShutdown<CMICmnLLDBDebugSessionInfo>( - IDS_MI_INIT_ERR_DEBUGSESSIONINFO, bOk, errMsg); - MI::ModuleShutdown<CMICmnLLDBDebuggerHandleEvents>( - IDS_MI_INIT_ERR_OUTOFBANDHANDLER, bOk, errMsg); - MI::ModuleShutdown<CMICmnThreadMgrStd>(IDS_MI_INIT_ERR_THREADMGR, bOk, - errMsg); - MI::ModuleShutdown<CMICmnResources>(IDS_MI_INIT_ERR_RESOURCES, bOk, errMsg); - MI::ModuleShutdown<CMICmnLog>(IDS_MI_INIT_ERR_LOG, bOk, errMsg); - - if (!bOk) { - SetErrorDescriptionn(MIRSRC(IDS_MI_SHTDWN_ERR_LLDBDEBUGGER), - errMsg.c_str()); - } - - return MIstatus::success; -} - -//++ -// Details: Return the LLDB debugger instance created for this debug session. -// Type: Method. -// Args: None. -// Return: lldb::SBDebugger & - LLDB debugger object reference. -// Throws: None. -//-- -lldb::SBDebugger &CMICmnLLDBDebugger::GetTheDebugger() { - return m_lldbDebugger; -} - -//++ -// Details: Return the LLDB listener instance created for this debug session. -// Type: Method. -// Args: None. -// Return: lldb::SBListener & - LLDB listener object reference. -// Throws: None. -//-- -lldb::SBListener &CMICmnLLDBDebugger::GetTheListener() { - return m_lldbListener; -} - -//++ -// Details: Set the client driver that wants to use *this LLDB debugger. Call -// this function -// prior to Initialize(). -// Type: Method. -// Args: vClientDriver - (R) A driver. -// Return: MIstatus::success - Functionality succeeded. -// MIstatus::failure - Functionality failed. -// Throws: None. -//-- -bool CMICmnLLDBDebugger::SetDriver(const CMIDriverBase &vClientDriver) { - m_pClientDriver = const_cast<CMIDriverBase *>(&vClientDriver); - - return MIstatus::success; -} - -//++ -// Details: Get the client driver that is use *this LLDB debugger. -// Type: Method. -// Args: vClientDriver - (R) A driver. -// Return: CMIDriverBase & - A driver instance. -// Throws: None. -//-- -CMIDriverBase &CMICmnLLDBDebugger::GetDriver() const { - return *m_pClientDriver; -} - -//++ -// Details: Wait until all events have been handled. -// This function works in pair with -// CMICmnLLDBDebugger::MonitorSBListenerEvents -// that handles events from queue. When all events were handled and -// queue is -// empty the MonitorSBListenerEvents notifies this function that it's -// ready to -// go on. To synchronize them the m_mutexEventQueue and -// m_conditionEventQueueEmpty are used. -// Type: Method. -// Args: None. -// Return: None. -// Throws: None. -//-- -void CMICmnLLDBDebugger::WaitForHandleEvent() { - std::unique_lock<std::mutex> lock(m_mutexEventQueue); - - lldb::SBEvent event; - if (ThreadIsActive() && m_lldbListener.PeekAtNextEvent(event)) - m_conditionEventQueueEmpty.wait(lock); -} - -//++ -// Details: Check if need to rebroadcast stop event. This function will return -// true if -// debugger is in synchronouse mode. In such case the -// CMICmnLLDBDebugger::RebroadcastStopEvent should be called to -// rebroadcast -// a new stop event (if any). -// Type: Method. -// Args: None. -// Return: bool - True = Need to rebroadcast stop event, false = otherwise. -// Throws: None. -//-- -bool CMICmnLLDBDebugger::CheckIfNeedToRebroadcastStopEvent() { - CMICmnLLDBDebugSessionInfo &rSessionInfo( - CMICmnLLDBDebugSessionInfo::Instance()); - if (!rSessionInfo.GetDebugger().GetAsync()) { - const bool include_expression_stops = false; - m_nLastStopId = - CMICmnLLDBDebugSessionInfo::Instance().GetProcess().GetStopID( - include_expression_stops); - return true; - } - - return false; -} - -//++ -// Details: Rebroadcast stop event if needed. This function should be called -// only if the -// CMICmnLLDBDebugger::CheckIfNeedToRebroadcastStopEvent() returned -// true. -// Type: Method. -// Args: None. -// Return: None. -// Throws: None. -//-- -void CMICmnLLDBDebugger::RebroadcastStopEvent() { - lldb::SBProcess process = CMICmnLLDBDebugSessionInfo::Instance().GetProcess(); - const bool include_expression_stops = false; - const uint32_t nStopId = process.GetStopID(include_expression_stops); - if (m_nLastStopId != nStopId) { - lldb::SBEvent event = process.GetStopEventForStopID(nStopId); - process.GetBroadcaster().BroadcastEvent(event); - } -} - -//++ -// Details: Initialize the LLDB Debugger object. -// Type: Method. -// Args: None. -// Return: MIstatus::success - Functionality succeeded. -// MIstatus::failure - Functionality failed. -// Throws: None. -//-- -bool CMICmnLLDBDebugger::InitSBDebugger() { - m_lldbDebugger = lldb::SBDebugger::Create(false); - if (!m_lldbDebugger.IsValid()) { - SetErrorDescription(MIRSRC(IDS_LLDBDEBUGGER_ERR_INVALIDDEBUGGER)); - return MIstatus::failure; - } - - m_lldbDebugger.GetCommandInterpreter().SetPromptOnQuit(false); - - return MIstatus::success; -} - -//++ -// Details: Set the LLDB Debugger's std in, err and out streams. (Not -// implemented left -// here for reference. Was called in the -// CMICmnLLDBDebugger::Initialize() ) -// Type: Method. -// Args: None. -// Return: MIstatus::success - Functionality succeeded. -// MIstatus::failure - Functionality failed. -// Throws: None. -//-- -bool CMICmnLLDBDebugger::InitStdStreams() { - // This is not required when operating the MI driver's code as it has its own - // streams. Setting the Stdin for the lldbDebugger especially on LINUX will - // cause - // another thread to run and partially consume stdin data meant for MI stdin - // handler - // m_lldbDebugger.SetErrorFileHandle( m_pClientDriver->GetStderr(), false ); - // m_lldbDebugger.SetOutputFileHandle( m_pClientDriver->GetStdout(), false ); - // m_lldbDebugger.SetInputFileHandle( m_pClientDriver->GetStdin(), false ); - - return MIstatus::success; -} - -//++ -// Details: Set up the events from the SBDebugger's we would like to listen to. -// Type: Method. -// Args: None. -// Return: MIstatus::success - Functionality succeeded. -// MIstatus::failure - Functionality failed. -// Throws: None. -//-- -bool CMICmnLLDBDebugger::InitSBListener() { - m_lldbListener = m_lldbDebugger.GetListener(); - if (!m_lldbListener.IsValid()) { - SetErrorDescription(MIRSRC(IDS_LLDBDEBUGGER_ERR_INVALIDLISTENER)); - return MIstatus::failure; - } - - const CMIUtilString strDbgId("CMICmnLLDBDebugger1"); - MIuint eventMask = lldb::SBTarget::eBroadcastBitBreakpointChanged | - lldb::SBTarget::eBroadcastBitModulesLoaded | - lldb::SBTarget::eBroadcastBitModulesUnloaded | - lldb::SBTarget::eBroadcastBitWatchpointChanged | - lldb::SBTarget::eBroadcastBitSymbolsLoaded; - bool bOk = RegisterForEvent( - strDbgId, CMIUtilString(lldb::SBTarget::GetBroadcasterClassName()), - eventMask); - - eventMask = lldb::SBThread::eBroadcastBitStackChanged; - bOk = bOk && - RegisterForEvent( - strDbgId, CMIUtilString(lldb::SBThread::GetBroadcasterClassName()), - eventMask); - - eventMask = lldb::SBProcess::eBroadcastBitStateChanged | - lldb::SBProcess::eBroadcastBitInterrupt | - lldb::SBProcess::eBroadcastBitSTDOUT | - lldb::SBProcess::eBroadcastBitSTDERR | - lldb::SBProcess::eBroadcastBitProfileData | - lldb::SBProcess::eBroadcastBitStructuredData; - bOk = bOk && - RegisterForEvent( - strDbgId, CMIUtilString(lldb::SBProcess::GetBroadcasterClassName()), - eventMask); - - eventMask = lldb::SBCommandInterpreter::eBroadcastBitQuitCommandReceived | - lldb::SBCommandInterpreter::eBroadcastBitThreadShouldExit | - lldb::SBCommandInterpreter::eBroadcastBitAsynchronousOutputData | - lldb::SBCommandInterpreter::eBroadcastBitAsynchronousErrorData; - bOk = bOk && - RegisterForEvent( - strDbgId, m_lldbDebugger.GetCommandInterpreter().GetBroadcaster(), - eventMask); - - return bOk; -} - -//++ -// Details: Register with the debugger, the SBListener, the type of events you -// are interested -// in. Others, like commands, may have already set the mask. -// Type: Method. -// Args: vClientName - (R) ID of the client who wants these events -// set. -// vBroadcasterClass - (R) The SBBroadcaster's class name. -// vEventMask - (R) The mask of events to listen for. -// Return: MIstatus::success - Functionality succeeded. -// MIstatus::failure - Functionality failed. -// Throws: None. -//-- -bool CMICmnLLDBDebugger::RegisterForEvent( - const CMIUtilString &vClientName, const CMIUtilString &vBroadcasterClass, - const MIuint vEventMask) { - MIuint existingMask = 0; - if (!BroadcasterGetMask(vBroadcasterClass, existingMask)) - return MIstatus::failure; - - if (!ClientSaveMask(vClientName, vBroadcasterClass, vEventMask)) - return MIstatus::failure; - - const char *pBroadCasterName = vBroadcasterClass.c_str(); - MIuint eventMask = vEventMask; - eventMask += existingMask; - const MIuint result = m_lldbListener.StartListeningForEventClass( - m_lldbDebugger, pBroadCasterName, eventMask); - if (result == 0) { - SetErrorDescription(CMIUtilString::Format( - MIRSRC(IDS_LLDBDEBUGGER_ERR_STARTLISTENER), pBroadCasterName)); - return MIstatus::failure; - } - - return BroadcasterSaveMask(vBroadcasterClass, eventMask); -} - -//++ -// Details: Register with the debugger, the SBListener, the type of events you -// are interested -// in. Others, like commands, may have already set the mask. -// Type: Method. -// Args: vClientName - (R) ID of the client who wants these events set. -// vBroadcaster - (R) An SBBroadcaster's derived class. -// vEventMask - (R) The mask of events to listen for. -// Return: MIstatus::success - Functionality succeeded. -// MIstatus::failure - Functionality failed. -// Throws: None. -//-- -bool CMICmnLLDBDebugger::RegisterForEvent( - const CMIUtilString &vClientName, const lldb::SBBroadcaster &vBroadcaster, - const MIuint vEventMask) { - const char *pBroadcasterName = vBroadcaster.GetName(); - if (pBroadcasterName == nullptr) { - SetErrorDescription( - CMIUtilString::Format(MIRSRC(IDS_LLDBDEBUGGER_ERR_BROADCASTER_NAME), - MIRSRC(IDS_WORD_INVALIDNULLPTR))); - return MIstatus::failure; - } - CMIUtilString broadcasterName(pBroadcasterName); - if (broadcasterName.length() == 0) { - SetErrorDescription( - CMIUtilString::Format(MIRSRC(IDS_LLDBDEBUGGER_ERR_BROADCASTER_NAME), - MIRSRC(IDS_WORD_INVALIDEMPTY))); - return MIstatus::failure; - } - - MIuint existingMask = 0; - if (!BroadcasterGetMask(broadcasterName, existingMask)) - return MIstatus::failure; - - if (!ClientSaveMask(vClientName, broadcasterName, vEventMask)) - return MIstatus::failure; - - MIuint eventMask = vEventMask; - eventMask += existingMask; - const MIuint result = - m_lldbListener.StartListeningForEvents(vBroadcaster, eventMask); - if (result == 0) { - SetErrorDescription(CMIUtilString::Format( - MIRSRC(IDS_LLDBDEBUGGER_ERR_STARTLISTENER), pBroadcasterName)); - return MIstatus::failure; - } - - return BroadcasterSaveMask(broadcasterName, eventMask); -} - -//++ -// Details: Unregister with the debugger, the SBListener, the type of events you -// are no -// longer interested in. Others, like commands, may still remain -// interested so -// an event may not necessarily be stopped. -// Type: Method. -// Args: vClientName - (R) ID of the client who no longer requires -// these events. -// vBroadcasterClass - (R) The SBBroadcaster's class name. -// Return: MIstatus::success - Functionality succeeded. -// MIstatus::failure - Functionality failed. -// Throws: None. -//-- -bool CMICmnLLDBDebugger::UnregisterForEvent( - const CMIUtilString &vClientName, const CMIUtilString &vBroadcasterClass) { - MIuint clientsEventMask = 0; - if (!ClientGetTheirMask(vClientName, vBroadcasterClass, clientsEventMask)) - return MIstatus::failure; - if (!ClientRemoveTheirMask(vClientName, vBroadcasterClass)) - return MIstatus::failure; - - const MIuint otherClientsEventMask = - ClientGetMaskForAllClients(vBroadcasterClass); - MIuint newEventMask = 0; - for (MIuint i = 0; i < 32; i++) { - const MIuint bit = MIuint(1) << i; - const MIuint clientBit = bit & clientsEventMask; - const MIuint othersBit = bit & otherClientsEventMask; - if ((clientBit != 0) && (othersBit == 0)) { - newEventMask += clientBit; - } - } - - const char *pBroadCasterName = vBroadcasterClass.c_str(); - if (!m_lldbListener.StopListeningForEventClass( - m_lldbDebugger, pBroadCasterName, newEventMask)) { - SetErrorDescription( - CMIUtilString::Format(MIRSRC(IDS_LLDBDEBUGGER_ERR_STOPLISTENER), - vClientName.c_str(), pBroadCasterName)); - return MIstatus::failure; - } - - return BroadcasterSaveMask(vBroadcasterClass, otherClientsEventMask); -} - -//++ -// Details: Given the SBBroadcaster class name retrieve it's current event mask. -// Type: Method. -// Args: vBroadcasterClass - (R) The SBBroadcaster's class name. -// vEventMask - (W) The mask of events to listen for. -// Return: MIstatus::success - Functionality succeeded. -// MIstatus::failure - Functionality failed. -// Throws: None. -//-- -bool CMICmnLLDBDebugger::BroadcasterGetMask( - const CMIUtilString &vBroadcasterClass, MIuint &vwEventMask) const { - vwEventMask = 0; - - if (vBroadcasterClass.empty()) { - SetErrorDescription( - CMIUtilString::Format(MIRSRC(IDS_LLDBDEBUGGER_ERR_INVALIDBROADCASTER), - vBroadcasterClass.c_str())); - return MIstatus::failure; - } - - const MapBroadcastClassNameToEventMask_t::const_iterator it = - m_mapBroadcastClassNameToEventMask.find(vBroadcasterClass); - if (it != m_mapBroadcastClassNameToEventMask.end()) { - vwEventMask = (*it).second; - } - - return MIstatus::success; -} - -//++ -// Details: Remove the event mask for the specified SBBroadcaster class name. -// Type: Method. -// Args: vBroadcasterClass - (R) The SBBroadcaster's class name. -// Return: MIstatus::success - Functionality succeeded. -// MIstatus::failure - Functionality failed. -// Throws: None. -//-- -bool CMICmnLLDBDebugger::BroadcasterRemoveMask( - const CMIUtilString &vBroadcasterClass) { - MapBroadcastClassNameToEventMask_t::const_iterator it = - m_mapBroadcastClassNameToEventMask.find(vBroadcasterClass); - if (it != m_mapBroadcastClassNameToEventMask.end()) { - m_mapBroadcastClassNameToEventMask.erase(it); - } - - return MIstatus::success; -} - -//++ -// Details: Given the SBBroadcaster class name save it's current event mask. -// Type: Method. -// Args: vBroadcasterClass - (R) The SBBroadcaster's class name. -// vEventMask - (R) The mask of events to listen for. -// Return: MIstatus::success - Functionality succeeded. -// MIstatus::failure - Functionality failed. -// Throws: None. -//-- -bool CMICmnLLDBDebugger::BroadcasterSaveMask( - const CMIUtilString &vBroadcasterClass, const MIuint vEventMask) { - if (vBroadcasterClass.empty()) { - SetErrorDescription( - CMIUtilString::Format(MIRSRC(IDS_LLDBDEBUGGER_ERR_INVALIDBROADCASTER), - vBroadcasterClass.c_str())); - return MIstatus::failure; - } - - BroadcasterRemoveMask(vBroadcasterClass); - MapPairBroadcastClassNameToEventMask_t pr(vBroadcasterClass, vEventMask); - m_mapBroadcastClassNameToEventMask.insert(pr); - - return MIstatus::success; -} - -//++ -// Details: Iterate all the clients who have registered event masks against -// particular -// SBBroadcasters and build up the mask that is for all of them. -// Type: Method. -// Args: vBroadcasterClass - (R) The broadcaster to retrieve the mask for. -// Return: MIuint - Event mask. -// Throws: None. -//-- -MIuint CMICmnLLDBDebugger::ClientGetMaskForAllClients( - const CMIUtilString &vBroadcasterClass) const { - MIuint mask = 0; - MapIdToEventMask_t::const_iterator it = m_mapIdToEventMask.begin(); - while (it != m_mapIdToEventMask.end()) { - const CMIUtilString &rId((*it).first); - if (rId.find(vBroadcasterClass) != std::string::npos) { - const MIuint clientsMask = (*it).second; - mask |= clientsMask; - } - - // Next - ++it; - } - - return mask; -} - -//++ -// Details: Given the client save its particular event requirements. -// Type: Method. -// Args: vClientName - (R) The Client's unique ID. -// vBroadcasterClass - (R) The SBBroadcaster's class name targeted for -// the events. -// vEventMask - (R) The mask of events to listen for. -// Return: MIstatus::success - Functionality succeeded. -// MIstatus::failure - Functionality failed. -// Throws: None. -//-- -bool CMICmnLLDBDebugger::ClientSaveMask(const CMIUtilString &vClientName, - const CMIUtilString &vBroadcasterClass, - const MIuint vEventMask) { - if (vClientName.empty()) { - SetErrorDescription(CMIUtilString::Format( - MIRSRC(IDS_LLDBDEBUGGER_ERR_INVALIDCLIENTNAME), vClientName.c_str())); - return MIstatus::failure; - } - - CMIUtilString strId(vBroadcasterClass); - strId += vClientName; - - ClientRemoveTheirMask(vClientName, vBroadcasterClass); - MapPairIdToEventMask_t pr(strId, vEventMask); - m_mapIdToEventMask.insert(pr); - - return MIstatus::success; -} - -//++ -// Details: Given the client remove it's particular event requirements. -// Type: Method. -// Args: vClientName - (R) The Client's unique ID. -// vBroadcasterClass - (R) The SBBroadcaster's class name. -// Return: MIstatus::success - Functionality succeeded. -// MIstatus::failure - Functionality failed. -// Throws: None. -//-- -bool CMICmnLLDBDebugger::ClientRemoveTheirMask( - const CMIUtilString &vClientName, const CMIUtilString &vBroadcasterClass) { - if (vClientName.empty()) { - SetErrorDescription(CMIUtilString::Format( - MIRSRC(IDS_LLDBDEBUGGER_ERR_INVALIDCLIENTNAME), vClientName.c_str())); - return MIstatus::failure; - } - - CMIUtilString strId(vBroadcasterClass); - strId += vClientName; - - const MapIdToEventMask_t::const_iterator it = m_mapIdToEventMask.find(strId); - if (it != m_mapIdToEventMask.end()) { - m_mapIdToEventMask.erase(it); - } - - return MIstatus::success; -} - -//++ -// Details: Retrieve the client's event mask used for on a particular -// SBBroadcaster. -// Type: Method. -// Args: vClientName - (R) The Client's unique ID. -// vBroadcasterClass - (R) The SBBroadcaster's class name. -// vwEventMask - (W) The client's mask. -// Return: MIstatus::success - Functionality succeeded. -// MIstatus::failure - Functionality failed. -// Throws: None. -//-- -bool CMICmnLLDBDebugger::ClientGetTheirMask( - const CMIUtilString &vClientName, const CMIUtilString &vBroadcasterClass, - MIuint &vwEventMask) { - vwEventMask = 0; - - if (vClientName.empty()) { - SetErrorDescription(CMIUtilString::Format( - MIRSRC(IDS_LLDBDEBUGGER_ERR_INVALIDCLIENTNAME), vClientName.c_str())); - return MIstatus::failure; - } - - const CMIUtilString strId(vBroadcasterClass + vClientName); - const MapIdToEventMask_t::const_iterator it = m_mapIdToEventMask.find(strId); - if (it != m_mapIdToEventMask.end()) { - vwEventMask = (*it).second; - } - - SetErrorDescription(CMIUtilString::Format( - MIRSRC(IDS_LLDBDEBUGGER_ERR_CLIENTNOTREGISTERED), vClientName.c_str())); - - return MIstatus::failure; -} - -//++ -// Details: Momentarily wait for an events being broadcast and inspect those -// that do -// come this way. Check if the target should exit event if so start -// shutting -// down this thread and the application. Any other events pass on to -// the -// Out-of-band handler to further determine what kind of event arrived. -// This function runs in the thread "MI debugger event". -// Type: Method. -// Args: vrbIsAlive - (W) False = yes exit event monitoring thread, true = -// continue. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. -//-- -bool CMICmnLLDBDebugger::MonitorSBListenerEvents(bool &vrbIsAlive) { - vrbIsAlive = true; - - // Lock the mutex of event queue - // Note that it should be locked while we are in - // CMICmnLLDBDebugger::MonitorSBListenerEvents to - // avoid a race condition with CMICmnLLDBDebugger::WaitForHandleEvent - std::unique_lock<std::mutex> lock(m_mutexEventQueue); - - lldb::SBEvent event; - const bool bGotEvent = m_lldbListener.GetNextEvent(event); - if (!bGotEvent) { - // Notify that we are finished and unlock the mutex of event queue before - // sleeping - m_conditionEventQueueEmpty.notify_one(); - lock.unlock(); - - // Wait a bit to reduce CPU load - const std::chrono::milliseconds time(1); - std::this_thread::sleep_for(time); - return MIstatus::success; - } - assert(event.IsValid()); - assert(event.GetBroadcaster().IsValid()); - - // Debugging - m_pLog->WriteLog(CMIUtilString::Format("##### An event occurred: %s", - event.GetBroadcasterClass())); - - bool bHandledEvent = false; - bool bOk = false; - { - // Lock Mutex before handling events so that we don't disturb a running cmd - CMIUtilThreadLock lock( - CMICmnLLDBDebugSessionInfo::Instance().GetSessionMutex()); - bOk = CMICmnLLDBDebuggerHandleEvents::Instance().HandleEvent(event, - bHandledEvent); - } - - if (!bHandledEvent) { - const CMIUtilString msg( - CMIUtilString::Format(MIRSRC(IDS_LLDBDEBUGGER_WRN_UNKNOWN_EVENT), - event.GetBroadcasterClass())); - m_pLog->WriteLog(msg); - } - - if (!bOk) - m_pLog->WriteLog( - CMICmnLLDBDebuggerHandleEvents::Instance().GetErrorDescription()); - - return MIstatus::success; -} - -//++ -// Details: The main worker method for this thread. -// Type: Method. -// Args: vrbIsAlive - (W) True = *this thread is working, false = thread has -// exited. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. -//-- -bool CMICmnLLDBDebugger::ThreadRun(bool &vrbIsAlive) { - return MonitorSBListenerEvents(vrbIsAlive); -} - -//++ -// Details: Let this thread clean up after itself. -// Type: Method. -// Args: -// Return: MIstatus::success - Functionality succeeded. -// MIstatus::failure - Functionality failed. -// Throws: None. -//-- -bool CMICmnLLDBDebugger::ThreadFinish() { return MIstatus::success; } - -//++ -// Details: Retrieve *this thread object's name. -// Type: Overridden. -// Args: None. -// Return: CMIUtilString & - Text. -// Throws: None. -//-- -const CMIUtilString &CMICmnLLDBDebugger::ThreadGetName() const { - return m_constStrThisThreadId; -} - -//++ -// Details: Loads lldb-mi formatters -// Type: Method. -// Args: None. -// Return: true - Functionality succeeded. -// false - Functionality failed. -// Throws: None. -//-- -bool CMICmnLLDBDebugger::LoadMIFormatters(lldb::SBTypeCategory miCategory) { - if (!MI_add_summary(miCategory, "char", MI_char_summary_provider, - lldb::eTypeOptionHideValue | - lldb::eTypeOptionSkipPointers)) - return false; - - if (!MI_add_summary(miCategory, "unsigned char", MI_char_summary_provider, - lldb::eTypeOptionHideValue | - lldb::eTypeOptionSkipPointers)) - return false; - - if (!MI_add_summary(miCategory, "signed char", MI_char_summary_provider, - lldb::eTypeOptionHideValue | - lldb::eTypeOptionSkipPointers)) - return false; - - return true; -} - -//++ -// Details: Registers lldb-mi custom summary providers -// Type: Method. -// Args: None. -// Return: true - Functionality succeeded. -// false - Functionality failed. -// Throws: None. -//-- -bool CMICmnLLDBDebugger::RegisterMISummaryProviders() { - static const char *miCategoryName = "lldb-mi"; - lldb::SBTypeCategory miCategory = - m_lldbDebugger.CreateCategory(miCategoryName); - if (!miCategory.IsValid()) - return false; - - if (!LoadMIFormatters(miCategory)) { - m_lldbDebugger.DeleteCategory(miCategoryName); - return false; - } - miCategory.SetEnabled(true); - return true; -} |