2014-05-16 18:51:01 +08:00
|
|
|
//===-- MICmnLLDBDebugger.cpp -----------------------------------*- C++ -*-===//
|
|
|
|
//
|
|
|
|
// The LLVM Compiler Infrastructure
|
|
|
|
//
|
|
|
|
// This file is distributed under the University of Illinois Open Source
|
|
|
|
// License. See LICENSE.TXT for details.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
// Third party headers:
|
2015-01-20 08:04:26 +08:00
|
|
|
#include "lldb/API/SBTarget.h"
|
|
|
|
#include "lldb/API/SBThread.h"
|
|
|
|
#include "lldb/API/SBProcess.h"
|
|
|
|
#include "lldb/API/SBCommandInterpreter.h"
|
2015-10-23 08:23:53 +08:00
|
|
|
#include "lldb/API/SBTypeSummary.h"
|
|
|
|
#include "lldb/API/SBTypeCategory.h"
|
|
|
|
#include "lldb/API/SBTypeNameSpecifier.h"
|
|
|
|
#include "lldb/API/SBStream.h"
|
|
|
|
#include "lldb/API/SBType.h"
|
2014-05-16 18:51:01 +08:00
|
|
|
|
|
|
|
// In-house headers:
|
|
|
|
#include "MICmnLLDBDebugger.h"
|
|
|
|
#include "MICmnResources.h"
|
|
|
|
#include "MICmnLog.h"
|
|
|
|
#include "MIDriverBase.h"
|
|
|
|
#include "MICmnThreadMgrStd.h"
|
|
|
|
#include "MICmnLLDBDebuggerHandleEvents.h"
|
|
|
|
#include "MICmnLLDBDebugSessionInfo.h"
|
|
|
|
#include "MIUtilSingletonHelper.h"
|
|
|
|
|
2015-10-23 08:23:53 +08:00
|
|
|
//++ ------------------------------------------------------------------------------------
|
|
|
|
// 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(), value.GetValue());
|
|
|
|
else if (type_code == lldb::eBasicTypeUnsignedChar)
|
|
|
|
stream.Printf("%u %s", (unsigned)value.GetValueAsUnsigned(), 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)
|
|
|
|
{
|
2015-10-23 18:27:16 +08:00
|
|
|
#if defined(LLDB_DISABLE_PYTHON)
|
|
|
|
return false;
|
|
|
|
#else
|
2015-10-23 08:23:53 +08:00
|
|
|
lldb::SBTypeSummary summary = lldb::SBTypeSummary::CreateWithCallback(cb, options);
|
|
|
|
return summary.IsValid() ? category.AddTypeSummary(lldb::SBTypeNameSpecifier(typeName, regex), summary) : false;
|
2015-10-23 18:27:16 +08:00
|
|
|
#endif
|
2015-10-23 08:23:53 +08:00
|
|
|
}
|
|
|
|
|
2014-05-16 18:51:01 +08:00
|
|
|
//++ ------------------------------------------------------------------------------------
|
2014-11-18 02:06:21 +08:00
|
|
|
// Details: CMICmnLLDBDebugger constructor.
|
|
|
|
// Type: Method.
|
|
|
|
// Args: None.
|
|
|
|
// Return: None.
|
|
|
|
// Throws: None.
|
2014-05-16 18:51:01 +08:00
|
|
|
//--
|
2015-08-04 18:24:20 +08:00
|
|
|
CMICmnLLDBDebugger::CMICmnLLDBDebugger()
|
2014-11-18 02:06:21 +08:00
|
|
|
: m_constStrThisThreadId("MI debugger event")
|
2014-05-16 18:51:01 +08:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
//++ ------------------------------------------------------------------------------------
|
2014-11-18 02:06:21 +08:00
|
|
|
// Details: CMICmnLLDBDebugger destructor.
|
|
|
|
// Type: Overridable.
|
|
|
|
// Args: None.
|
|
|
|
// Return: None.
|
|
|
|
// Throws: None.
|
2014-05-16 18:51:01 +08:00
|
|
|
//--
|
2015-08-04 18:24:20 +08:00
|
|
|
CMICmnLLDBDebugger::~CMICmnLLDBDebugger()
|
2014-05-16 18:51:01 +08:00
|
|
|
{
|
2014-11-18 02:06:21 +08:00
|
|
|
Shutdown();
|
2014-05-16 18:51:01 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
//++ ------------------------------------------------------------------------------------
|
2014-11-18 02:06:21 +08:00
|
|
|
// Details: Initialize resources for *this debugger object.
|
|
|
|
// Type: Method.
|
|
|
|
// Args: None.
|
|
|
|
// Return: MIstatus::success - Functionality succeeded.
|
|
|
|
// MIstatus::failure - Functionality failed.
|
|
|
|
// Throws: None.
|
2014-05-16 18:51:01 +08:00
|
|
|
//--
|
2014-11-18 02:06:21 +08:00
|
|
|
bool
|
2015-08-04 18:24:20 +08:00
|
|
|
CMICmnLLDBDebugger::Initialize()
|
2014-05-16 18:51:01 +08:00
|
|
|
{
|
2014-11-18 02:06:21 +08:00
|
|
|
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();
|
2015-10-23 08:23:53 +08:00
|
|
|
bOk = bOk && RegisterMISummaryProviders();
|
2014-11-18 02:06:21 +08:00
|
|
|
m_bInitialized = bOk;
|
|
|
|
|
|
|
|
if (!bOk && !HaveErrorDescription())
|
|
|
|
{
|
|
|
|
CMIUtilString strInitError(CMIUtilString::Format(MIRSRC(IDS_MI_INIT_ERR_LLDBDEBUGGER), errMsg.c_str()));
|
|
|
|
SetErrorDescription(strInitError);
|
|
|
|
}
|
|
|
|
|
|
|
|
return bOk;
|
2014-05-16 18:51:01 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
//++ ------------------------------------------------------------------------------------
|
2014-11-18 02:06:21 +08:00
|
|
|
// Details: Release resources for *this debugger object.
|
|
|
|
// Type: Method.
|
|
|
|
// Args: None.
|
|
|
|
// Return: MIstatus::success - Functionality succeeded.
|
|
|
|
// MIstatus::failure - Functionality failed.
|
|
|
|
// Throws: None.
|
2014-05-16 18:51:01 +08:00
|
|
|
//--
|
2014-11-18 02:06:21 +08:00
|
|
|
bool
|
2015-08-04 18:24:20 +08:00
|
|
|
CMICmnLLDBDebugger::Shutdown()
|
2014-05-16 18:51:01 +08:00
|
|
|
{
|
2014-11-18 02:06:21 +08:00
|
|
|
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
|
2015-02-03 18:05:54 +08:00
|
|
|
lldb::SBTarget sbTarget = CMICmnLLDBDebugSessionInfo::Instance().GetTarget();
|
|
|
|
m_lldbDebugger.DeleteTarget(sbTarget);
|
2014-11-18 02:06:21 +08:00
|
|
|
|
|
|
|
// 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;
|
|
|
|
}
|
2014-05-16 18:51:01 +08:00
|
|
|
|
|
|
|
//++ ------------------------------------------------------------------------------------
|
2014-11-18 02:06:21 +08:00
|
|
|
// Details: Return the LLDB debugger instance created for this debug session.
|
|
|
|
// Type: Method.
|
|
|
|
// Args: None.
|
|
|
|
// Return: lldb::SBDebugger & - LLDB debugger object reference.
|
|
|
|
// Throws: None.
|
2014-05-16 18:51:01 +08:00
|
|
|
//--
|
2014-11-18 02:06:21 +08:00
|
|
|
lldb::SBDebugger &
|
2015-08-04 18:24:20 +08:00
|
|
|
CMICmnLLDBDebugger::GetTheDebugger()
|
2014-05-16 18:51:01 +08:00
|
|
|
{
|
2014-11-18 02:06:21 +08:00
|
|
|
return m_lldbDebugger;
|
2014-05-16 18:51:01 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
//++ ------------------------------------------------------------------------------------
|
2014-11-18 02:06:21 +08:00
|
|
|
// Details: Return the LLDB listener instance created for this debug session.
|
|
|
|
// Type: Method.
|
|
|
|
// Args: None.
|
|
|
|
// Return: lldb::SBListener & - LLDB listener object reference.
|
|
|
|
// Throws: None.
|
2014-05-16 18:51:01 +08:00
|
|
|
//--
|
2014-11-18 02:06:21 +08:00
|
|
|
lldb::SBListener &
|
2015-08-04 18:24:20 +08:00
|
|
|
CMICmnLLDBDebugger::GetTheListener()
|
2014-05-16 18:51:01 +08:00
|
|
|
{
|
2014-11-18 02:06:21 +08:00
|
|
|
return m_lldbListener;
|
2014-05-16 18:51:01 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
//++ ------------------------------------------------------------------------------------
|
2014-11-18 02:06:21 +08:00
|
|
|
// 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.
|
2014-05-16 18:51:01 +08:00
|
|
|
//--
|
2014-11-18 02:06:21 +08:00
|
|
|
bool
|
|
|
|
CMICmnLLDBDebugger::SetDriver(const CMIDriverBase &vClientDriver)
|
2014-05-16 18:51:01 +08:00
|
|
|
{
|
2014-11-18 02:06:21 +08:00
|
|
|
m_pClientDriver = const_cast<CMIDriverBase *>(&vClientDriver);
|
2014-05-16 18:51:01 +08:00
|
|
|
|
2014-11-18 02:06:21 +08:00
|
|
|
return MIstatus::success;
|
2014-05-16 18:51:01 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
//++ ------------------------------------------------------------------------------------
|
2014-11-18 02:06:21 +08:00
|
|
|
// 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.
|
2014-05-16 18:51:01 +08:00
|
|
|
//--
|
2014-11-18 02:06:21 +08:00
|
|
|
CMIDriverBase &
|
2015-08-04 18:24:20 +08:00
|
|
|
CMICmnLLDBDebugger::GetDriver() const
|
2014-05-16 18:51:01 +08:00
|
|
|
{
|
2014-11-18 02:06:21 +08:00
|
|
|
return *m_pClientDriver;
|
2014-05-16 18:51:01 +08:00
|
|
|
}
|
2014-11-18 02:06:21 +08:00
|
|
|
|
2015-05-07 14:45:42 +08:00
|
|
|
//++ ------------------------------------------------------------------------------------
|
|
|
|
// 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
|
2015-08-04 18:24:20 +08:00
|
|
|
CMICmnLLDBDebugger::WaitForHandleEvent()
|
2015-05-07 14:45:42 +08:00
|
|
|
{
|
|
|
|
std::unique_lock<std::mutex> lock(m_mutexEventQueue);
|
|
|
|
|
|
|
|
lldb::SBEvent event;
|
|
|
|
if (ThreadIsActive() && m_lldbListener.PeekAtNextEvent(event))
|
|
|
|
m_conditionEventQueueEmpty.wait(lock);
|
|
|
|
}
|
|
|
|
|
2015-05-20 18:15:47 +08:00
|
|
|
//++ ------------------------------------------------------------------------------------
|
|
|
|
// 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
|
2015-08-04 18:24:20 +08:00
|
|
|
CMICmnLLDBDebugger::CheckIfNeedToRebroadcastStopEvent()
|
2015-05-20 18:15:47 +08:00
|
|
|
{
|
|
|
|
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
|
2015-08-04 18:24:20 +08:00
|
|
|
CMICmnLLDBDebugger::RebroadcastStopEvent()
|
2015-05-20 18:15:47 +08:00
|
|
|
{
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-05-16 18:51:01 +08:00
|
|
|
//++ ------------------------------------------------------------------------------------
|
2014-11-18 02:06:21 +08:00
|
|
|
// Details: Initialize the LLDB Debugger object.
|
|
|
|
// Type: Method.
|
|
|
|
// Args: None.
|
|
|
|
// Return: MIstatus::success - Functionality succeeded.
|
|
|
|
// MIstatus::failure - Functionality failed.
|
|
|
|
// Throws: None.
|
2014-05-16 18:51:01 +08:00
|
|
|
//--
|
2014-11-18 02:06:21 +08:00
|
|
|
bool
|
2015-08-04 18:24:20 +08:00
|
|
|
CMICmnLLDBDebugger::InitSBDebugger()
|
2014-05-16 18:51:01 +08:00
|
|
|
{
|
2014-11-18 02:06:21 +08:00
|
|
|
m_lldbDebugger = lldb::SBDebugger::Create(false);
|
2015-03-24 06:45:13 +08:00
|
|
|
if (!m_lldbDebugger.IsValid())
|
|
|
|
{
|
|
|
|
SetErrorDescription(MIRSRC(IDS_LLDBDEBUGGER_ERR_INVALIDDEBUGGER));
|
|
|
|
return MIstatus::failure;
|
|
|
|
}
|
2014-05-16 18:51:01 +08:00
|
|
|
|
2015-03-24 06:45:13 +08:00
|
|
|
m_lldbDebugger.GetCommandInterpreter().SetPromptOnQuit(false);
|
|
|
|
|
|
|
|
return MIstatus::success;
|
2014-05-16 18:51:01 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
//++ ------------------------------------------------------------------------------------
|
2014-11-18 02:06:21 +08:00
|
|
|
// 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.
|
2014-05-16 18:51:01 +08:00
|
|
|
//--
|
2014-11-18 02:06:21 +08:00
|
|
|
bool
|
2015-08-04 18:24:20 +08:00
|
|
|
CMICmnLLDBDebugger::InitStdStreams()
|
2014-05-16 18:51:01 +08:00
|
|
|
{
|
2014-11-18 02:06:21 +08:00
|
|
|
// 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;
|
2014-05-16 18:51:01 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
//++ ------------------------------------------------------------------------------------
|
2015-06-18 13:27:05 +08:00
|
|
|
// Details: Set up the events from the SBDebugger's we would like to listen to.
|
2014-11-18 02:06:21 +08:00
|
|
|
// Type: Method.
|
|
|
|
// Args: None.
|
|
|
|
// Return: MIstatus::success - Functionality succeeded.
|
|
|
|
// MIstatus::failure - Functionality failed.
|
|
|
|
// Throws: None.
|
2014-05-16 18:51:01 +08:00
|
|
|
//--
|
2014-11-18 02:06:21 +08:00
|
|
|
bool
|
2015-08-04 18:24:20 +08:00
|
|
|
CMICmnLLDBDebugger::InitSBListener()
|
2014-05-16 18:51:01 +08:00
|
|
|
{
|
2014-11-18 02:06:21 +08:00
|
|
|
m_lldbListener = m_lldbDebugger.GetListener();
|
|
|
|
if (!m_lldbListener.IsValid())
|
|
|
|
{
|
|
|
|
SetErrorDescription(MIRSRC(IDS_LLDBDEBUGGER_ERR_INVALIDLISTENER));
|
|
|
|
return MIstatus::failure;
|
|
|
|
}
|
|
|
|
|
|
|
|
const CMIUtilString strDbgId("CMICmnLLDBDebugger1");
|
Add =shlibs-added/=shlibs-removed notifications (MI)
Summary:
This patch adds =shlibs-added/=shlibs-removed notifications in lldb-mi. In more detail:
# Add Target::ModulesDidLoad/ModulesDidUnload notifications
# Improve Target::TargetEventData:
## Refactoring
## Move it back to include/lldb/Target/Target.h
## Add Target::{GetModuleListFromEvent,GetModuleList}; Add Target::m_module_list
# Add SBModule::{GetSymbolVendorMainFileSpec,GetObjectFileHeaderAddress}
# Add SBTarget::{EventIsTaretEvent,GetTargetFromEvent,GetNumModulesFromEvent,GetModuleAtIndexFromEvent}
All tests pass on OS X.
Reviewers: abidh, zturner, jingham, clayborg
Reviewed By: clayborg
Subscribers: jingham, zturner, lldb-commits, clayborg, abidh
Differential Revision: http://reviews.llvm.org/D8201
llvm-svn: 231858
2015-03-11 05:59:55 +08:00
|
|
|
MIuint eventMask = lldb::SBTarget::eBroadcastBitBreakpointChanged | lldb::SBTarget::eBroadcastBitModulesLoaded |
|
|
|
|
lldb::SBTarget::eBroadcastBitModulesUnloaded | lldb::SBTarget::eBroadcastBitWatchpointChanged |
|
|
|
|
lldb::SBTarget::eBroadcastBitSymbolsLoaded;
|
2014-11-18 02:06:21 +08:00
|
|
|
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 |
|
2016-08-19 12:21:48 +08:00
|
|
|
lldb::SBProcess::eBroadcastBitSTDOUT | lldb::SBProcess::eBroadcastBitSTDERR | lldb::SBProcess::eBroadcastBitProfileData |
|
|
|
|
lldb::SBProcess::eBroadcastBitStructuredData;
|
2014-11-18 02:06:21 +08:00
|
|
|
bOk = bOk && RegisterForEvent(strDbgId, CMIUtilString(lldb::SBProcess::GetBroadcasterClassName()), eventMask);
|
|
|
|
|
|
|
|
eventMask = lldb::SBCommandInterpreter::eBroadcastBitQuitCommandReceived | lldb::SBCommandInterpreter::eBroadcastBitThreadShouldExit |
|
|
|
|
lldb::SBCommandInterpreter::eBroadcastBitAsynchronousOutputData |
|
|
|
|
lldb::SBCommandInterpreter::eBroadcastBitAsynchronousErrorData;
|
Fix handling of CommandInterpreter's events in lldb-mi
Summary:
Previously lldb-mi contains a stub for that but it didn't work and all CommanInterpreter's events were ignored.
This commit adds a handling of CommandInterpreter's events in lldb-mi.
Steps:
# Fix CMICmnLLDBDebugger::InitSBListener
# Add SBCommandInterpreter::EventIsCommandInterpreterEvent
# Exit on lldb::SBCommandInterpreter::eBroadcastBitQuitCommandReceived
All tests pass on OS X.
In further we can remove "quit" hack in lldb-mi.
Test Plan:
# Create start_script file:
```
target create ~/p/hello
b main
r
quit
```
# Run lldb-mi --interpreter
# Execute start_script file by following command:
```
-interpreter-exec console "command source start_script"
```
Log:
```
$ bin/lldb-mi --interpreter
(gdb)
-interpreter-exec console "command source start_script"
Executing commands in '/Users/IliaK/p/llvm/build_ninja/start_script'.
(lldb) target create ~/p/hello
Current executable set to '~/p/hello' (x86_64).
(lldb) b main
Breakpoint 1: where = hello`main + 29 at hello.cpp:12, address = 0x0000000100000e2d
(lldb) r
Process 1582 launched: '/Users/IliaK/p/hello' (x86_64)
(lldb) quit
^done
(gdb)
=thread-created,id="1",group-id="i1"
=thread-selected,id="1"
(gdb)
=shlibs-added,shlib-info=[num="1",name="hello",dyld-addr="-",reason="dyld",path="/Users/IliaK/p/hello",loaded_addr="-",dsym-objpath="/Users/IliaK/p/hello.dSYM/Contents/Resources/DWARF/hello"]
...
=shlibs-added,shlib-info=[num="132",name="libDiagnosticMessagesClient.dylib",dyld-addr="0x7fff91705000",reason="dyld",path="/usr/lib/libDiagnosticMessagesClient.dylib",loaded_addr="0x7fff91705000"]
(gdb)
*stopped,reason="breakpoint-hit",disp="del",bkptno="1",frame={addr="0x100000e2d",func="main",args=[{name="argc",value="1"},{name="argv",value="0x00007fff5fbffc88"}],file="hello.cpp",fullname="/Users/IliaK/p/hello.cpp",line="12"},thread-id="1",stopped-threads="all"
(gdb)<press Enter>
MI: Program exited OK
```
Reviewers: abidh, clayborg
Reviewed By: abidh
Subscribers: jingham, lldb-commits, clayborg, abidh
Differential Revision: http://reviews.llvm.org/D8382
llvm-svn: 232891
2015-03-21 18:53:37 +08:00
|
|
|
bOk = bOk && RegisterForEvent(strDbgId, m_lldbDebugger.GetCommandInterpreter().GetBroadcaster(), eventMask);
|
2014-11-18 02:06:21 +08:00
|
|
|
|
|
|
|
return bOk;
|
2014-05-16 18:51:01 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
//++ ------------------------------------------------------------------------------------
|
2014-11-18 02:06:21 +08:00
|
|
|
// 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.
|
2014-05-16 18:51:01 +08:00
|
|
|
//--
|
2014-11-18 02:06:21 +08:00
|
|
|
bool
|
|
|
|
CMICmnLLDBDebugger::RegisterForEvent(const CMIUtilString &vClientName, const CMIUtilString &vBroadcasterClass, const MIuint vEventMask)
|
2014-05-16 18:51:01 +08:00
|
|
|
{
|
2014-11-18 02:06:21 +08:00
|
|
|
MIuint existingMask = 0;
|
|
|
|
if (!BroadcasterGetMask(vBroadcasterClass, existingMask))
|
|
|
|
return MIstatus::failure;
|
|
|
|
|
|
|
|
if (!ClientSaveMask(vClientName, vBroadcasterClass, vEventMask))
|
|
|
|
return MIstatus::failure;
|
|
|
|
|
2015-07-03 21:45:34 +08:00
|
|
|
const char *pBroadCasterName = vBroadcasterClass.c_str();
|
2014-11-18 02:06:21 +08:00
|
|
|
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);
|
2014-05-16 18:51:01 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
//++ ------------------------------------------------------------------------------------
|
2014-11-18 02:06:21 +08:00
|
|
|
// 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.
|
2014-05-16 18:51:01 +08:00
|
|
|
//--
|
2014-11-18 02:06:21 +08:00
|
|
|
bool
|
|
|
|
CMICmnLLDBDebugger::RegisterForEvent(const CMIUtilString &vClientName, const lldb::SBBroadcaster &vBroadcaster, const MIuint vEventMask)
|
2014-05-16 18:51:01 +08:00
|
|
|
{
|
2015-07-03 21:45:34 +08:00
|
|
|
const char *pBroadcasterName = vBroadcaster.GetName();
|
2014-11-18 02:06:21 +08:00
|
|
|
if (pBroadcasterName == nullptr)
|
|
|
|
{
|
2015-07-07 22:54:07 +08:00
|
|
|
SetErrorDescription(CMIUtilString::Format(MIRSRC(IDS_LLDBDEBUGGER_ERR_BROADCASTER_NAME), MIRSRC(IDS_WORD_INVALIDNULLPTR)));
|
2014-11-18 02:06:21 +08:00
|
|
|
return MIstatus::failure;
|
|
|
|
}
|
|
|
|
CMIUtilString broadcasterName(pBroadcasterName);
|
|
|
|
if (broadcasterName.length() == 0)
|
|
|
|
{
|
2015-07-07 22:54:07 +08:00
|
|
|
SetErrorDescription(CMIUtilString::Format(MIRSRC(IDS_LLDBDEBUGGER_ERR_BROADCASTER_NAME), MIRSRC(IDS_WORD_INVALIDEMPTY)));
|
2014-11-18 02:06:21 +08:00
|
|
|
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);
|
2014-05-16 18:51:01 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
//++ ------------------------------------------------------------------------------------
|
2014-11-18 02:06:21 +08:00
|
|
|
// 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.
|
2014-05-16 18:51:01 +08:00
|
|
|
//--
|
2014-11-18 02:06:21 +08:00
|
|
|
bool
|
|
|
|
CMICmnLLDBDebugger::UnregisterForEvent(const CMIUtilString &vClientName, const CMIUtilString &vBroadcasterClass)
|
2014-05-16 18:51:01 +08:00
|
|
|
{
|
2014-11-18 02:06:21 +08:00
|
|
|
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 = 1 << i;
|
|
|
|
const MIuint clientBit = bit & clientsEventMask;
|
|
|
|
const MIuint othersBit = bit & otherClientsEventMask;
|
|
|
|
if ((clientBit != 0) && (othersBit == 0))
|
|
|
|
{
|
|
|
|
newEventMask += clientBit;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-07-03 21:45:34 +08:00
|
|
|
const char *pBroadCasterName = vBroadcasterClass.c_str();
|
2014-11-18 02:06:21 +08:00
|
|
|
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);
|
2014-05-16 18:51:01 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
//++ ------------------------------------------------------------------------------------
|
2014-11-18 02:06:21 +08:00
|
|
|
// 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.
|
2014-05-16 18:51:01 +08:00
|
|
|
//--
|
2014-11-18 02:06:21 +08:00
|
|
|
bool
|
|
|
|
CMICmnLLDBDebugger::BroadcasterGetMask(const CMIUtilString &vBroadcasterClass, MIuint &vwEventMask) const
|
2014-05-16 18:51:01 +08:00
|
|
|
{
|
2014-11-18 02:06:21 +08:00
|
|
|
vwEventMask = 0;
|
2014-06-25 00:35:50 +08:00
|
|
|
|
2014-11-18 02:06:21 +08:00
|
|
|
if (vBroadcasterClass.empty())
|
|
|
|
{
|
|
|
|
SetErrorDescription(CMIUtilString::Format(MIRSRC(IDS_LLDBDEBUGGER_ERR_INVALIDBROADCASTER), vBroadcasterClass.c_str()));
|
|
|
|
return MIstatus::failure;
|
|
|
|
}
|
2014-05-16 18:51:01 +08:00
|
|
|
|
2014-11-18 02:06:21 +08:00
|
|
|
const MapBroadcastClassNameToEventMask_t::const_iterator it = m_mapBroadcastClassNameToEventMask.find(vBroadcasterClass);
|
|
|
|
if (it != m_mapBroadcastClassNameToEventMask.end())
|
|
|
|
{
|
|
|
|
vwEventMask = (*it).second;
|
|
|
|
}
|
2014-05-16 18:51:01 +08:00
|
|
|
|
2014-11-18 02:06:21 +08:00
|
|
|
return MIstatus::success;
|
2014-05-16 18:51:01 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
//++ ------------------------------------------------------------------------------------
|
2014-11-18 02:06:21 +08:00
|
|
|
// 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.
|
2014-05-16 18:51:01 +08:00
|
|
|
//--
|
2014-11-18 02:06:21 +08:00
|
|
|
bool
|
|
|
|
CMICmnLLDBDebugger::BroadcasterRemoveMask(const CMIUtilString &vBroadcasterClass)
|
2014-05-16 18:51:01 +08:00
|
|
|
{
|
2014-11-18 02:06:21 +08:00
|
|
|
MapBroadcastClassNameToEventMask_t::const_iterator it = m_mapBroadcastClassNameToEventMask.find(vBroadcasterClass);
|
|
|
|
if (it != m_mapBroadcastClassNameToEventMask.end())
|
|
|
|
{
|
|
|
|
m_mapBroadcastClassNameToEventMask.erase(it);
|
|
|
|
}
|
2014-05-16 18:51:01 +08:00
|
|
|
|
2014-11-18 02:06:21 +08:00
|
|
|
return MIstatus::success;
|
2014-05-16 18:51:01 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
//++ ------------------------------------------------------------------------------------
|
2014-11-18 02:06:21 +08:00
|
|
|
// 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.
|
2014-05-16 18:51:01 +08:00
|
|
|
//--
|
2014-11-18 02:06:21 +08:00
|
|
|
bool
|
|
|
|
CMICmnLLDBDebugger::BroadcasterSaveMask(const CMIUtilString &vBroadcasterClass, const MIuint vEventMask)
|
2014-05-16 18:51:01 +08:00
|
|
|
{
|
2014-11-18 02:06:21 +08:00
|
|
|
if (vBroadcasterClass.empty())
|
|
|
|
{
|
|
|
|
SetErrorDescription(CMIUtilString::Format(MIRSRC(IDS_LLDBDEBUGGER_ERR_INVALIDBROADCASTER), vBroadcasterClass.c_str()));
|
|
|
|
return MIstatus::failure;
|
|
|
|
}
|
2014-05-16 18:51:01 +08:00
|
|
|
|
2014-11-18 02:06:21 +08:00
|
|
|
BroadcasterRemoveMask(vBroadcasterClass);
|
|
|
|
MapPairBroadcastClassNameToEventMask_t pr(vBroadcasterClass, vEventMask);
|
|
|
|
m_mapBroadcastClassNameToEventMask.insert(pr);
|
2014-05-16 18:51:01 +08:00
|
|
|
|
2014-11-18 02:06:21 +08:00
|
|
|
return MIstatus::success;
|
2014-05-16 18:51:01 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
//++ ------------------------------------------------------------------------------------
|
2014-11-18 02:06:21 +08:00
|
|
|
// 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.
|
2014-05-16 18:51:01 +08:00
|
|
|
//--
|
2014-11-18 02:06:21 +08:00
|
|
|
MIuint
|
|
|
|
CMICmnLLDBDebugger::ClientGetMaskForAllClients(const CMIUtilString &vBroadcasterClass) const
|
2014-05-16 18:51:01 +08:00
|
|
|
{
|
2014-11-18 02:06:21 +08:00
|
|
|
MIuint mask = 0;
|
|
|
|
MapIdToEventMask_t::const_iterator it = m_mapIdToEventMask.begin();
|
|
|
|
while (it != m_mapIdToEventMask.end())
|
|
|
|
{
|
|
|
|
const CMIUtilString &rId((*it).first);
|
2015-09-25 16:28:58 +08:00
|
|
|
if (rId.find(vBroadcasterClass) != std::string::npos)
|
2014-11-18 02:06:21 +08:00
|
|
|
{
|
|
|
|
const MIuint clientsMask = (*it).second;
|
|
|
|
mask |= clientsMask;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Next
|
|
|
|
++it;
|
|
|
|
}
|
|
|
|
|
|
|
|
return mask;
|
2014-05-16 18:51:01 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
//++ ------------------------------------------------------------------------------------
|
2014-11-18 02:06:21 +08:00
|
|
|
// 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.
|
2014-05-16 18:51:01 +08:00
|
|
|
//--
|
2014-11-18 02:06:21 +08:00
|
|
|
bool
|
|
|
|
CMICmnLLDBDebugger::ClientSaveMask(const CMIUtilString &vClientName, const CMIUtilString &vBroadcasterClass, const MIuint vEventMask)
|
2014-05-16 18:51:01 +08:00
|
|
|
{
|
2014-11-18 02:06:21 +08:00
|
|
|
if (vClientName.empty())
|
|
|
|
{
|
|
|
|
SetErrorDescription(CMIUtilString::Format(MIRSRC(IDS_LLDBDEBUGGER_ERR_INVALIDCLIENTNAME), vClientName.c_str()));
|
|
|
|
return MIstatus::failure;
|
|
|
|
}
|
2014-05-16 18:51:01 +08:00
|
|
|
|
2014-11-18 02:06:21 +08:00
|
|
|
CMIUtilString strId(vBroadcasterClass);
|
|
|
|
strId += vClientName;
|
2014-05-16 18:51:01 +08:00
|
|
|
|
2014-11-18 02:06:21 +08:00
|
|
|
ClientRemoveTheirMask(vClientName, vBroadcasterClass);
|
|
|
|
MapPairIdToEventMask_t pr(strId, vEventMask);
|
|
|
|
m_mapIdToEventMask.insert(pr);
|
2014-05-16 18:51:01 +08:00
|
|
|
|
2014-11-18 02:06:21 +08:00
|
|
|
return MIstatus::success;
|
2014-05-16 18:51:01 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
//++ ------------------------------------------------------------------------------------
|
2014-11-18 02:06:21 +08:00
|
|
|
// 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.
|
2014-05-16 18:51:01 +08:00
|
|
|
//--
|
2014-11-18 02:06:21 +08:00
|
|
|
bool
|
|
|
|
CMICmnLLDBDebugger::ClientRemoveTheirMask(const CMIUtilString &vClientName, const CMIUtilString &vBroadcasterClass)
|
2014-05-16 18:51:01 +08:00
|
|
|
{
|
2014-11-18 02:06:21 +08:00
|
|
|
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;
|
2014-05-16 18:51:01 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
//++ ------------------------------------------------------------------------------------
|
2014-11-18 02:06:21 +08:00
|
|
|
// 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.
|
2014-05-16 18:51:01 +08:00
|
|
|
//--
|
2014-11-18 02:06:21 +08:00
|
|
|
bool
|
|
|
|
CMICmnLLDBDebugger::ClientGetTheirMask(const CMIUtilString &vClientName, const CMIUtilString &vBroadcasterClass, MIuint &vwEventMask)
|
2014-05-16 18:51:01 +08:00
|
|
|
{
|
2014-11-18 02:06:21 +08:00
|
|
|
vwEventMask = 0;
|
2014-05-16 18:51:01 +08:00
|
|
|
|
2014-11-18 02:06:21 +08:00
|
|
|
if (vClientName.empty())
|
|
|
|
{
|
|
|
|
SetErrorDescription(CMIUtilString::Format(MIRSRC(IDS_LLDBDEBUGGER_ERR_INVALIDCLIENTNAME), vClientName.c_str()));
|
|
|
|
return MIstatus::failure;
|
|
|
|
}
|
2014-05-16 18:51:01 +08:00
|
|
|
|
2015-09-25 16:28:58 +08:00
|
|
|
const CMIUtilString strId(vBroadcasterClass + vClientName);
|
2014-11-18 02:06:21 +08:00
|
|
|
const MapIdToEventMask_t::const_iterator it = m_mapIdToEventMask.find(strId);
|
|
|
|
if (it != m_mapIdToEventMask.end())
|
|
|
|
{
|
|
|
|
vwEventMask = (*it).second;
|
|
|
|
}
|
2014-05-16 18:51:01 +08:00
|
|
|
|
2015-06-18 13:27:05 +08:00
|
|
|
SetErrorDescription(CMIUtilString::Format(MIRSRC(IDS_LLDBDEBUGGER_ERR_CLIENTNOTREGISTERED), vClientName.c_str()));
|
2014-06-25 00:35:50 +08:00
|
|
|
|
2014-11-18 02:06:21 +08:00
|
|
|
return MIstatus::failure;
|
2014-05-16 18:51:01 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
//++ ------------------------------------------------------------------------------------
|
2014-11-18 02:06:21 +08:00
|
|
|
// 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
|
2015-06-18 13:27:05 +08:00
|
|
|
// Out-of-band handler to further determine what kind of event arrived.
|
2014-11-18 02:06:21 +08:00
|
|
|
// 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.
|
2014-05-16 18:51:01 +08:00
|
|
|
//--
|
2014-11-18 02:06:21 +08:00
|
|
|
bool
|
|
|
|
CMICmnLLDBDebugger::MonitorSBListenerEvents(bool &vrbIsAlive)
|
2014-05-16 18:51:01 +08:00
|
|
|
{
|
2014-11-18 02:06:21 +08:00
|
|
|
vrbIsAlive = true;
|
|
|
|
|
2015-05-07 14:45:42 +08:00
|
|
|
// 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);
|
|
|
|
|
2014-11-18 02:06:21 +08:00
|
|
|
lldb::SBEvent event;
|
|
|
|
const bool bGotEvent = m_lldbListener.GetNextEvent(event);
|
2015-05-07 14:45:42 +08:00
|
|
|
if (!bGotEvent)
|
2014-11-18 02:06:21 +08:00
|
|
|
{
|
2015-05-07 14:45:42 +08:00
|
|
|
// 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
|
2014-11-18 02:06:21 +08:00
|
|
|
const std::chrono::milliseconds time(1);
|
|
|
|
std::this_thread::sleep_for(time);
|
|
|
|
return MIstatus::success;
|
|
|
|
}
|
2015-05-07 14:45:42 +08:00
|
|
|
assert(event.IsValid());
|
|
|
|
assert(event.GetBroadcaster().IsValid());
|
2014-11-18 02:06:21 +08:00
|
|
|
|
|
|
|
// Debugging
|
|
|
|
m_pLog->WriteLog(CMIUtilString::Format("##### An event occurred: %s", event.GetBroadcasterClass()));
|
|
|
|
|
|
|
|
bool bHandledEvent = false;
|
2015-02-04 17:59:23 +08:00
|
|
|
bool bOk = false;
|
|
|
|
{
|
|
|
|
// Lock Mutex before handling events so that we don't disturb a running cmd
|
|
|
|
CMIUtilThreadLock lock(CMICmnLLDBDebugSessionInfo::Instance().GetSessionMutex());
|
Add -exec-abort command (MI); Don't exit on eStateExited
Summary:
Add -exec-abort command + test.
Also, I had fixed an error, when lldb-mi exits on eStateExited. With current patch we can re-run target:
```
-file-exec-and-symbols hello
^done
-exec-run
^running
*stopped,reason="breakpoint-hit"...
-exec-abort
^done
*stopped,reason="exited-normally"... <- program exits
-exec-run <- run again
^running
*stopped,reason="breakpoint-hit"...
```
All tests pass on OS X.
Reviewers: zturner, emaste, abidh, clayborg
Reviewed By: abidh, clayborg
Subscribers: lldb-commits, emaste, zturner, clayborg, abidh
Differential Revision: http://reviews.llvm.org/D7794
llvm-svn: 230321
2015-02-24 18:40:45 +08:00
|
|
|
bOk = CMICmnLLDBDebuggerHandleEvents::Instance().HandleEvent(event, bHandledEvent);
|
2015-02-04 17:59:23 +08:00
|
|
|
}
|
2015-05-07 14:45:42 +08:00
|
|
|
|
2014-11-18 02:06:21 +08:00
|
|
|
if (!bHandledEvent)
|
|
|
|
{
|
|
|
|
const CMIUtilString msg(CMIUtilString::Format(MIRSRC(IDS_LLDBDEBUGGER_WRN_UNKNOWN_EVENT), event.GetBroadcasterClass()));
|
|
|
|
m_pLog->WriteLog(msg);
|
|
|
|
}
|
2015-05-07 14:45:42 +08:00
|
|
|
|
2014-11-18 02:06:21 +08:00
|
|
|
if (!bOk)
|
|
|
|
m_pLog->WriteLog(CMICmnLLDBDebuggerHandleEvents::Instance().GetErrorDescription());
|
|
|
|
|
2015-05-07 14:45:42 +08:00
|
|
|
return MIstatus::success;
|
2014-05-16 18:51:01 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
//++ ------------------------------------------------------------------------------------
|
2014-11-18 02:06:21 +08:00
|
|
|
// 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.
|
2014-05-16 18:51:01 +08:00
|
|
|
//--
|
2014-11-18 02:06:21 +08:00
|
|
|
bool
|
|
|
|
CMICmnLLDBDebugger::ThreadRun(bool &vrbIsAlive)
|
2014-05-16 18:51:01 +08:00
|
|
|
{
|
2014-11-18 02:06:21 +08:00
|
|
|
return MonitorSBListenerEvents(vrbIsAlive);
|
2014-05-16 18:51:01 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
//++ ------------------------------------------------------------------------------------
|
2014-11-18 02:06:21 +08:00
|
|
|
// Details: Let this thread clean up after itself.
|
|
|
|
// Type: Method.
|
|
|
|
// Args:
|
|
|
|
// Return: MIstatus::success - Functionality succeeded.
|
|
|
|
// MIstatus::failure - Functionality failed.
|
|
|
|
// Throws: None.
|
2014-05-16 18:51:01 +08:00
|
|
|
//--
|
2014-11-18 02:06:21 +08:00
|
|
|
bool
|
2015-08-04 18:24:20 +08:00
|
|
|
CMICmnLLDBDebugger::ThreadFinish()
|
2014-05-16 18:51:01 +08:00
|
|
|
{
|
2014-11-18 02:06:21 +08:00
|
|
|
return MIstatus::success;
|
2014-05-16 18:51:01 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
//++ ------------------------------------------------------------------------------------
|
2014-11-18 02:06:21 +08:00
|
|
|
// Details: Retrieve *this thread object's name.
|
|
|
|
// Type: Overridden.
|
|
|
|
// Args: None.
|
|
|
|
// Return: CMIUtilString & - Text.
|
|
|
|
// Throws: None.
|
2014-05-16 18:51:01 +08:00
|
|
|
//--
|
2014-11-18 02:06:21 +08:00
|
|
|
const CMIUtilString &
|
2015-08-04 18:24:20 +08:00
|
|
|
CMICmnLLDBDebugger::ThreadGetName() const
|
2014-05-16 18:51:01 +08:00
|
|
|
{
|
2014-11-18 02:06:21 +08:00
|
|
|
return m_constStrThisThreadId;
|
2014-05-16 18:51:01 +08:00
|
|
|
}
|
2015-10-23 08:23:53 +08:00
|
|
|
|
|
|
|
//++ ------------------------------------------------------------------------------------
|
|
|
|
// 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;
|
|
|
|
}
|