aboutsummaryrefslogtreecommitdiff
path: root/tools/lldb-mi/MICmnLLDBDebuggerHandleEvents.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'tools/lldb-mi/MICmnLLDBDebuggerHandleEvents.cpp')
-rw-r--r--tools/lldb-mi/MICmnLLDBDebuggerHandleEvents.cpp1566
1 files changed, 1566 insertions, 0 deletions
diff --git a/tools/lldb-mi/MICmnLLDBDebuggerHandleEvents.cpp b/tools/lldb-mi/MICmnLLDBDebuggerHandleEvents.cpp
new file mode 100644
index 000000000000..08218a2e87e4
--- /dev/null
+++ b/tools/lldb-mi/MICmnLLDBDebuggerHandleEvents.cpp
@@ -0,0 +1,1566 @@
+//===-- MICmnLLDBDebuggerHandleEvents.cpp --------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+//++
+// File: MICmnLLDBDebuggerHandleEvents.cpp
+//
+// Overview: CMICmnLLDBDebuggerHandleEvents implementation.
+//
+// Environment: Compilers: Visual C++ 12.
+// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1
+// Libraries: See MIReadmetxt.
+//
+// Copyright: None.
+//--
+
+// Third party headers:
+#include <lldb/API/SBEvent.h>
+#include <lldb/API/SBProcess.h>
+#include <lldb/API/SBBreakpoint.h>
+#include <lldb/API/SBStream.h>
+#include <lldb/API/SBThread.h>
+#include <lldb/API/SBCommandInterpreter.h>
+#include <lldb/API/SBCommandReturnObject.h>
+#ifdef _WIN32
+ #include <io.h> // For the ::_access()
+#else
+ #include <unistd.h> // For the ::access()
+#endif // _WIN32
+#include <limits.h>
+
+// In-house headers:
+#include "MICmnLLDBDebuggerHandleEvents.h"
+#include "MICmnResources.h"
+#include "MICmnLog.h"
+#include "MICmnLLDBDebugSessionInfo.h"
+#include "MICmnMIResultRecord.h"
+#include "MICmnMIValueConst.h"
+#include "MICmnMIValueList.h"
+#include "MICmnMIOutOfBandRecord.h"
+#include "MICmnStreamStdout.h"
+#include "MICmnStreamStderr.h"
+#include "MIUtilDebug.h"
+#include "MIDriver.h"
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmnLLDBDebuggerHandleEvents constructor.
+// Type: Method.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMICmnLLDBDebuggerHandleEvents::CMICmnLLDBDebuggerHandleEvents( void )
+{
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmnLLDBDebuggerHandleEvents destructor.
+// Type: Overridable.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMICmnLLDBDebuggerHandleEvents::~CMICmnLLDBDebuggerHandleEvents( void )
+{
+ Shutdown();
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Initialize resources for *this broardcaster object.
+// Type: Method.
+// Args: None.
+// Return: MIstatus::success - Functionality succeeded.
+// MIstatus::failure - Functionality failed.
+// Throws: None.
+//--
+bool CMICmnLLDBDebuggerHandleEvents::Initialize( void )
+{
+ m_clientUsageRefCnt++;
+
+ if( m_bInitialized )
+ return MIstatus::success;
+
+ m_bInitialized = MIstatus::success;
+
+ return m_bInitialized;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Release resources for *this broardcaster object.
+// Type: Method.
+// Args: None.
+// Return: MIstatus::success - Functionality succeeded.
+// MIstatus::failure - Functionality failed.
+// Throws: None.
+//--
+bool CMICmnLLDBDebuggerHandleEvents::Shutdown( void )
+{
+ if( --m_clientUsageRefCnt > 0 )
+ return MIstatus::success;
+
+ if( !m_bInitialized )
+ return MIstatus::success;
+
+ m_bInitialized = false;
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Interpret the event object to asscertain the action to take or information to
+// to form and put in a MI Out-of-band record object which is given to stdout.
+// Type: Method.
+// Args: vEvent - (R) An LLDB broadcast event.
+// vrbHandledEvent - (W) True - event handled, false = not handled.
+// vrbExitAppEvent - (W) True - Received LLDB exit app event, false = did not.
+// Return: MIstatus::success - Functionality succeeded.
+// MIstatus::failure - Functionality failed.
+// Throws: None.
+//--
+bool CMICmnLLDBDebuggerHandleEvents::HandleEvent( const lldb::SBEvent & vEvent, bool & vrbHandledEvent, bool & vrbExitAppEvent )
+{
+ bool bOk = MIstatus::success;
+ vrbHandledEvent = false;
+ vrbExitAppEvent = false;
+
+ if( lldb::SBProcess::EventIsProcessEvent( vEvent ) )
+ {
+ vrbHandledEvent = true;
+ bOk = HandleEventSBProcess( vEvent, vrbExitAppEvent );
+ }
+ else if( lldb::SBBreakpoint::EventIsBreakpointEvent( vEvent ) )
+ {
+ vrbHandledEvent = true;
+ bOk = HandleEventSBBreakPoint( vEvent );
+ }
+ else if( lldb::SBThread::EventIsThreadEvent( vEvent ) )
+ {
+ vrbHandledEvent = true;
+ bOk = HandleEventSBThread( vEvent );
+ }
+
+ return bOk;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Handle a LLDB SBProcess event.
+// Type: Method.
+// Args: vEvent - (R) An LLDB broadcast event.
+// vrbExitAppEvent - (W) True - Received LLDB exit app event, false = did not.
+// Return: MIstatus::success - Functionality succeeded.
+// MIstatus::failure - Functionality failed.
+// Throws: None.
+//--
+bool CMICmnLLDBDebuggerHandleEvents::HandleEventSBProcess( const lldb::SBEvent & vEvent, bool & vrbExitAppEvent )
+{
+ bool bOk = MIstatus::success;
+
+ const MIchar * pEventType = "";
+ const MIuint nEventType = vEvent.GetType();
+ switch( nEventType )
+ {
+ case lldb::SBProcess::eBroadcastBitInterrupt:
+ pEventType = "eBroadcastBitInterrupt";
+ break;
+ case lldb::SBProcess::eBroadcastBitProfileData:
+ pEventType = "eBroadcastBitProfileData";
+ break;
+ case lldb::SBProcess::eBroadcastBitStateChanged:
+ pEventType = "eBroadcastBitStateChanged";
+ bOk = HandleProcessEventBroadcastBitStateChanged( vEvent, vrbExitAppEvent );
+ break;
+ case lldb::SBProcess::eBroadcastBitSTDERR:
+ pEventType = "eBroadcastBitSTDERR";
+ bOk = GetProcessStderr();
+ break;
+ case lldb::SBProcess::eBroadcastBitSTDOUT:
+ pEventType = "eBroadcastBitSTDOUT";
+ bOk = GetProcessStdout();
+ break;
+ default:
+ {
+ const CMIUtilString msg( CMIUtilString::Format( MIRSRC( IDS_LLDBOUTOFBAND_ERR_UNKNOWN_EVENT ), "SBProcess", (MIuint) nEventType ) );
+ SetErrorDescription( msg );
+ return MIstatus::failure;
+ }
+ }
+ m_pLog->WriteLog( CMIUtilString::Format( "##### An SB Process event occurred: %s", pEventType ) );
+
+ return bOk;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Handle a LLDB SBBreakpoint event.
+// Type: Method.
+// Args: vEvent - (R) An LLDB broadcast event.
+// Return: MIstatus::success - Functionality succeeded.
+// MIstatus::failure - Functionality failed.
+// Throws: None.
+//--
+bool CMICmnLLDBDebuggerHandleEvents::HandleEventSBBreakPoint( const lldb::SBEvent & vEvent )
+{
+ bool bOk = MIstatus::success;
+
+ const MIchar * pEventType ="";
+ const lldb::BreakpointEventType eEvent = lldb::SBBreakpoint::GetBreakpointEventTypeFromEvent( vEvent );
+ switch( eEvent )
+ {
+ case lldb::eBreakpointEventTypeThreadChanged:
+ pEventType = "eBreakpointEventTypeThreadChanged";
+ break;
+ case lldb::eBreakpointEventTypeLocationsRemoved:
+ pEventType = "eBreakpointEventTypeLocationsRemoved";
+ break;
+ case lldb::eBreakpointEventTypeInvalidType:
+ pEventType = "eBreakpointEventTypeInvalidType";
+ break;
+ case lldb::eBreakpointEventTypeLocationsAdded:
+ pEventType = "eBreakpointEventTypeLocationsAdded";
+ bOk = HandleEventSBBreakpointLocationsAdded( vEvent );
+ break;
+ case lldb::eBreakpointEventTypeAdded:
+ pEventType = "eBreakpointEventTypeAdded";
+ bOk = HandleEventSBBreakpointAdded( vEvent );
+ break;
+ case lldb::eBreakpointEventTypeRemoved:
+ pEventType = "eBreakpointEventTypeRemoved";
+ bOk = HandleEventSBBreakpointCmn( vEvent );
+ break;
+ case lldb::eBreakpointEventTypeLocationsResolved:
+ pEventType = "eBreakpointEventTypeLocationsResolved";
+ break;
+ case lldb::eBreakpointEventTypeEnabled:
+ pEventType ="eBreakpointEventTypeEnabled";
+ bOk = HandleEventSBBreakpointCmn( vEvent );
+ break;
+ case lldb::eBreakpointEventTypeDisabled:
+ pEventType = "eBreakpointEventTypeDisabled";
+ bOk = HandleEventSBBreakpointCmn( vEvent );
+ break;
+ case lldb::eBreakpointEventTypeCommandChanged:
+ pEventType = "eBreakpointEventTypeCommandChanged";
+ bOk = HandleEventSBBreakpointCmn( vEvent );
+ break;
+ case lldb::eBreakpointEventTypeConditionChanged:
+ pEventType ="eBreakpointEventTypeConditionChanged";
+ bOk = HandleEventSBBreakpointCmn( vEvent );
+ break;
+ case lldb::eBreakpointEventTypeIgnoreChanged:
+ pEventType = "eBreakpointEventTypeIgnoreChanged";
+ bOk = HandleEventSBBreakpointCmn( vEvent );
+ break;
+ default:
+ {
+ const CMIUtilString msg( CMIUtilString::Format( MIRSRC( IDS_LLDBOUTOFBAND_ERR_UNKNOWN_EVENT ), "SBBreakPoint", (MIuint) eEvent ) );
+ SetErrorDescription( msg );
+ return MIstatus::failure;
+ }
+ }
+ m_pLog->WriteLog( CMIUtilString::Format( "##### An SB Breakpoint event occurred: %s", pEventType ) );
+
+ return bOk;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Handle a LLDB SBBreakpoint event.
+// Type: Method.
+// Args: vEvent - (R) An LLDB broadcast event.
+// Return: MIstatus::success - Functionality succeeded.
+// MIstatus::failure - Functionality failed.
+// Throws: None.
+//--
+bool CMICmnLLDBDebuggerHandleEvents::HandleEventSBBreakpointLocationsAdded( const lldb::SBEvent & vEvent )
+{
+ const MIuint nLoc = lldb::SBBreakpoint::GetNumBreakpointLocationsFromEvent( vEvent );
+ if( nLoc == 0 )
+ return MIstatus::success;
+
+ lldb::SBBreakpoint brkPt = lldb::SBBreakpoint::GetBreakpointFromEvent( vEvent );
+ const CMIUtilString plural( (nLoc == 1) ? "" : "s" );
+ const CMIUtilString msg( CMIUtilString::Format( "%d location%s added to breakpoint %d", nLoc, plural.c_str(), brkPt.GetID() ) );
+
+ return TextToStdout( msg );
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Handle a LLDB SBBreakpoint event.
+// Type: Method.
+// Args: vEvent - (R) An LLDB broadcast event.
+// Return: MIstatus::success - Functionality succeeded.
+// MIstatus::failure - Functionality failed.
+// Throws: None.
+//--
+bool CMICmnLLDBDebuggerHandleEvents::HandleEventSBBreakpointCmn( const lldb::SBEvent & vEvent )
+{
+ lldb::SBBreakpoint brkPt = lldb::SBBreakpoint::GetBreakpointFromEvent( vEvent );
+ if( !brkPt.IsValid() )
+ return MIstatus::success;
+
+ CMICmnLLDBDebugSessionInfo & rSessionInfo( CMICmnLLDBDebugSessionInfo::Instance() );
+ CMICmnLLDBDebugSessionInfo::SBrkPtInfo sBrkPtInfo;
+ if( !rSessionInfo.GetBrkPtInfo( brkPt, sBrkPtInfo ) )
+ {
+ SetErrorDescription( CMIUtilString::Format( MIRSRC( IDS_LLDBOUTOFBAND_ERR_BRKPT_INFO_GET ), "HandleEventSBBreakpointCmn()", brkPt.GetID() ) );
+ return MIstatus::failure;
+ }
+
+ // CODETAG_LLDB_BREAKPOINT_CREATION
+ // This is in a worker thread
+ // Add more breakpoint information or overwrite existing information
+ CMICmnLLDBDebugSessionInfo::SBrkPtInfo sBrkPtInfoRec;
+ if( !rSessionInfo.RecordBrkPtInfoGet( brkPt.GetID(), sBrkPtInfoRec ) )
+ {
+ SetErrorDescription( CMIUtilString::Format( MIRSRC( IDS_LLDBOUTOFBAND_ERR_BRKPT_NOTFOUND ), "HandleEventSBBreakpointCmn()", brkPt.GetID() ) );
+ return MIstatus::failure;
+ }
+ sBrkPtInfo.m_bDisp = sBrkPtInfoRec.m_bDisp;
+ sBrkPtInfo.m_bEnabled = brkPt.IsEnabled();
+ sBrkPtInfo.m_bHaveArgOptionThreadGrp = false;
+ sBrkPtInfo.m_strOptThrdGrp = "";
+ sBrkPtInfo.m_nTimes = brkPt.GetHitCount();
+ sBrkPtInfo.m_strOrigLoc = sBrkPtInfoRec.m_strOrigLoc;
+ sBrkPtInfo.m_nIgnore = sBrkPtInfoRec.m_nIgnore;
+ sBrkPtInfo.m_bPending = sBrkPtInfoRec.m_bPending;
+ sBrkPtInfo.m_bCondition = sBrkPtInfoRec.m_bCondition;
+ sBrkPtInfo.m_strCondition = sBrkPtInfoRec.m_strCondition;
+ sBrkPtInfo.m_bBrkPtThreadId = sBrkPtInfoRec.m_bBrkPtThreadId;
+ sBrkPtInfo.m_nBrkPtThreadId = sBrkPtInfoRec.m_nBrkPtThreadId;
+
+ // MI print "=breakpoint-modified,bkpt={number=\"%d\",type=\"breakpoint\",disp=\"%s\",enabled=\"%c\",addr=\"0x%08x\", func=\"%s\",file=\"%s\",fullname=\"%s/%s\",line=\"%d\",times=\"%d\",original-location=\"%s\"}"
+ CMICmnMIValueTuple miValueTuple;
+ if( !rSessionInfo.MIResponseFormBrkPtInfo( sBrkPtInfo, miValueTuple ) )
+ {
+ SetErrorDescription( CMIUtilString::Format( MIRSRC( IDS_LLDBOUTOFBAND_ERR_FORM_MI_RESPONSE ), "HandleEventSBBreakpointCmn()" ) );
+ return MIstatus::failure;
+ }
+
+ const CMICmnMIValueResult miValueResultC( "bkpt", miValueTuple );
+ const CMICmnMIOutOfBandRecord miOutOfBandRecord( CMICmnMIOutOfBandRecord::eOutOfBand_BreakPointModified, miValueResultC );
+ const bool bOk = MiOutOfBandRecordToStdout( miOutOfBandRecord );
+
+ return bOk;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Handle a LLDB SBBreakpoint added event.
+// Add more breakpoint information or overwrite existing information.
+// Normally a break point session info objects exists by now when an MI command
+// was issued to insert a break so the retrieval would normally always succeed
+// however should a user type "b main" into a console then LLDB will create a
+// breakpoint directly, hence no MI command, hence no previous record of the
+// breakpoint so RecordBrkPtInfoGet() will fail. We still get the event though
+// so need to create a breakpoint info object here and send appropriate MI
+// response.
+// Type: Method.
+// Args: vEvent - (R) An LLDB broadcast event.
+// Return: MIstatus::success - Functionality succeeded.
+// MIstatus::failure - Functionality failed.
+// Throws: None.
+//--
+bool CMICmnLLDBDebuggerHandleEvents::HandleEventSBBreakpointAdded( const lldb::SBEvent & vEvent )
+{
+ lldb::SBBreakpoint brkPt = lldb::SBBreakpoint::GetBreakpointFromEvent( vEvent );
+ if( !brkPt.IsValid() )
+ return MIstatus::success;
+
+ CMICmnLLDBDebugSessionInfo & rSessionInfo( CMICmnLLDBDebugSessionInfo::Instance() );
+ CMICmnLLDBDebugSessionInfo::SBrkPtInfo sBrkPtInfo;
+ if( !rSessionInfo.GetBrkPtInfo( brkPt, sBrkPtInfo ) )
+ {
+ SetErrorDescription( CMIUtilString::Format( MIRSRC( IDS_LLDBOUTOFBAND_ERR_BRKPT_INFO_GET ), "HandleEventSBBreakpointAdded()", brkPt.GetID() ) );
+ return MIstatus::failure;
+ }
+
+ // CODETAG_LLDB_BREAKPOINT_CREATION
+ // This is in a worker thread
+ CMICmnLLDBDebugSessionInfo::SBrkPtInfo sBrkPtInfoRec;
+ const bool bBrkPtExistAlready = rSessionInfo.RecordBrkPtInfoGet( brkPt.GetID(), sBrkPtInfoRec );
+ if( bBrkPtExistAlready )
+ {
+ // Update breakpoint information object
+ sBrkPtInfo.m_bDisp = sBrkPtInfoRec.m_bDisp;
+ sBrkPtInfo.m_bEnabled = brkPt.IsEnabled();
+ sBrkPtInfo.m_bHaveArgOptionThreadGrp = false;
+ sBrkPtInfo.m_strOptThrdGrp.clear();
+ sBrkPtInfo.m_nTimes = brkPt.GetHitCount();
+ sBrkPtInfo.m_strOrigLoc = sBrkPtInfoRec.m_strOrigLoc;
+ sBrkPtInfo.m_nIgnore = sBrkPtInfoRec.m_nIgnore;
+ sBrkPtInfo.m_bPending = sBrkPtInfoRec.m_bPending;
+ sBrkPtInfo.m_bCondition = sBrkPtInfoRec.m_bCondition;
+ sBrkPtInfo.m_strCondition = sBrkPtInfoRec.m_strCondition;
+ sBrkPtInfo.m_bBrkPtThreadId = sBrkPtInfoRec.m_bBrkPtThreadId;
+ sBrkPtInfo.m_nBrkPtThreadId = sBrkPtInfoRec.m_nBrkPtThreadId;
+ }
+ else
+ {
+ // Create a breakpoint information object
+ sBrkPtInfo.m_bDisp = brkPt.IsOneShot();
+ sBrkPtInfo.m_bEnabled = brkPt.IsEnabled();
+ sBrkPtInfo.m_bHaveArgOptionThreadGrp = false;
+ sBrkPtInfo.m_strOptThrdGrp.clear();
+ sBrkPtInfo.m_strOrigLoc = CMIUtilString::Format( "%s:%d", sBrkPtInfo.m_fileName.c_str(), sBrkPtInfo.m_nLine );
+ sBrkPtInfo.m_nIgnore = brkPt.GetIgnoreCount();
+ sBrkPtInfo.m_bPending = false;
+ const MIchar * pStrCondition = brkPt.GetCondition();
+ sBrkPtInfo.m_bCondition = (pStrCondition != nullptr) ? true : false;
+ sBrkPtInfo.m_strCondition = (pStrCondition != nullptr) ? pStrCondition : "??";
+ sBrkPtInfo.m_bBrkPtThreadId = (brkPt.GetThreadID() != 0) ? true : false;
+ sBrkPtInfo.m_nBrkPtThreadId = brkPt.GetThreadID();
+ }
+
+ CMICmnMIValueTuple miValueTuple;
+ if( !rSessionInfo.MIResponseFormBrkPtInfo( sBrkPtInfo, miValueTuple ) )
+ {
+ SetErrorDescription( CMIUtilString::Format( MIRSRC( IDS_LLDBOUTOFBAND_ERR_FORM_MI_RESPONSE ), "HandleEventSBBreakpointAdded()" ) );
+ return MIstatus::failure;
+ }
+
+ bool bOk = MIstatus::success;
+ if( bBrkPtExistAlready )
+ {
+ // MI print "=breakpoint-modified,bkpt={number=\"%d\",type=\"breakpoint\",disp=\"%s\",enabled=\"%c\",addr=\"0x%08x\",func=\"%s\",file=\"%s\",fullname=\"%s/%s\",line=\"%d\",times=\"%d\",original-location=\"%s\"}"
+ const CMICmnMIValueResult miValueResult( "bkpt", miValueTuple );
+ const CMICmnMIOutOfBandRecord miOutOfBandRecord( CMICmnMIOutOfBandRecord::eOutOfBand_BreakPointModified, miValueResult );
+ bOk = MiOutOfBandRecordToStdout( miOutOfBandRecord );
+ }
+ else
+ {
+ // CODETAG_LLDB_BRKPT_ID_MAX
+ if( brkPt.GetID() > (lldb::break_id_t) rSessionInfo.m_nBrkPointCntMax )
+ {
+ SetErrorDescription( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_BRKPT_CNT_EXCEEDED ), "HandleEventSBBreakpointAdded()", rSessionInfo.m_nBrkPointCntMax, sBrkPtInfo.m_id ) );
+ return MIstatus::failure;
+ }
+ if( !rSessionInfo.RecordBrkPtInfo( brkPt.GetID(), sBrkPtInfo ) )
+ {
+ SetErrorDescription( CMIUtilString::Format( MIRSRC( IDS_LLDBOUTOFBAND_ERR_BRKPT_INFO_SET ), "HandleEventSBBreakpointAdded()", sBrkPtInfo.m_id ) );
+ return MIstatus::failure;
+ }
+
+ // MI print "=breakpoint-created,bkpt={number=\"%d\",type=\"breakpoint\",disp=\"%s\",enabled=\"%c\",addr=\"0x%08x\",func=\"%s\",file=\"%s\",fullname=\"%s/%s\",line=\"%d\",times=\"%d\",original-location=\"%s\"}"
+ const CMICmnMIValueResult miValueResult( "bkpt", miValueTuple );
+ const CMICmnMIOutOfBandRecord miOutOfBandRecord( CMICmnMIOutOfBandRecord::eOutOfBand_BreakPointCreated, miValueResult );
+ bOk = MiOutOfBandRecordToStdout( miOutOfBandRecord );
+ }
+
+ return bOk;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Handle a LLDB SBThread event.
+// Type: Method.
+// Args: vEvent - (R) An LLDB broadcast event.
+// Return: MIstatus::success - Functionality succeeded.
+// MIstatus::failure - Functionality failed.
+// Throws: None.
+//--
+bool CMICmnLLDBDebuggerHandleEvents::HandleEventSBThread( const lldb::SBEvent & vEvent )
+{
+ if( !ChkForStateChanges() )
+ return MIstatus::failure;
+
+ bool bOk = MIstatus::success;
+ const MIchar * pEventType = "";
+ const MIuint nEventType = vEvent.GetType();
+ switch( nEventType )
+ {
+ case lldb::SBThread::eBroadcastBitStackChanged:
+ pEventType = "eBroadcastBitStackChanged";
+ bOk = HandleEventSBThreadBitStackChanged( vEvent );
+ break;
+ case lldb::SBThread::eBroadcastBitThreadSuspended:
+ pEventType = "eBroadcastBitThreadSuspended";
+ bOk = HandleEventSBThreadSuspended( vEvent );
+ break;
+ case lldb::SBThread::eBroadcastBitThreadResumed:
+ pEventType = "eBroadcastBitThreadResumed";
+ break;
+ case lldb::SBThread::eBroadcastBitSelectedFrameChanged:
+ pEventType = "eBroadcastBitSelectedFrameChanged";
+ break;
+ case lldb::SBThread::eBroadcastBitThreadSelected:
+ pEventType = "eBroadcastBitThreadSelected";
+ break;
+ default:
+ {
+ const CMIUtilString msg( CMIUtilString::Format( MIRSRC( IDS_LLDBOUTOFBAND_ERR_UNKNOWN_EVENT ), "SBThread", (MIuint) nEventType ) );
+ SetErrorDescription( msg );
+ return MIstatus::failure;
+ }
+ }
+ m_pLog->WriteLog( CMIUtilString::Format( "##### An SBThread event occurred: %s", pEventType ) );
+
+ return bOk;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Handle a LLDB SBThread event.
+// Type: Method.
+// Args: vEvent - (R) An LLDB broadcast event.
+// Return: MIstatus::success - Functionality succeeded.
+// MIstatus::failure - Functionality failed.
+// Throws: None.
+//--
+bool CMICmnLLDBDebuggerHandleEvents::HandleEventSBThreadSuspended( const lldb::SBEvent & vEvent )
+{
+ lldb::SBThread thread = lldb::SBThread::GetThreadFromEvent( vEvent );
+ if( !thread.IsValid() )
+ return MIstatus::success;
+
+ const lldb::StopReason eStopReason = thread.GetStopReason();
+ if( eStopReason != lldb::eStopReasonSignal )
+ return MIstatus::success;
+
+ // MI print "@thread=%d,signal=%lld"
+ const MIuint64 nId = thread.GetStopReasonDataAtIndex( 0 );
+ const CMIUtilString strThread( CMIUtilString::Format( "%d", thread.GetThreadID() ) );
+ const CMICmnMIValueConst miValueConst( strThread );
+ const CMICmnMIValueResult miValueResult( "thread", miValueConst );
+ CMICmnMIOutOfBandRecord miOutOfBandRecord( CMICmnMIOutOfBandRecord::eOutOfBand_Thread, miValueResult );
+ const CMIUtilString strSignal( CMIUtilString::Format( "%lld", nId ) );
+ const CMICmnMIValueConst miValueConst2( strSignal );
+ const CMICmnMIValueResult miValueResult2( "signal", miValueConst2 );
+ bool bOk = miOutOfBandRecord.Add( miValueResult2 );
+ bOk = bOk && MiOutOfBandRecordToStdout( miOutOfBandRecord );
+
+ return bOk;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Handle a LLDB SBThread event.
+// Type: Method.
+// Args: vEvent - (R) An LLDB broadcast event.
+// Return: MIstatus::success - Functionality succeeded.
+// MIstatus::failure - Functionality failed.
+// Throws: None.
+//--
+bool CMICmnLLDBDebuggerHandleEvents::HandleEventSBThreadBitStackChanged( const lldb::SBEvent & vEvent )
+{
+ lldb::SBThread thread = lldb::SBThread::GetThreadFromEvent( vEvent );
+ if( !thread.IsValid() )
+ return MIstatus::success;
+
+ lldb::SBStream streamOut;
+ const bool bOk = thread.GetStatus( streamOut );
+ return bOk && TextToStdout( streamOut.GetData() );
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Handle a LLDB SBCommandInterpreter event.
+// Type: Method.
+// Args: vEvent - (R) An LLDB command interpreter event.
+// Return: MIstatus::success - Functionality succeeded.
+// MIstatus::failure - Functionality failed.
+// Throws: None.
+//--
+bool CMICmnLLDBDebuggerHandleEvents::HandleEventSBCommandInterpreter( const lldb::SBEvent & vEvent )
+{
+ // This function is not used
+ // *** This function is under development
+
+ const MIchar * pEventType = "";
+ const MIuint nEventType = vEvent.GetType();
+ switch( nEventType )
+ {
+ case lldb::SBCommandInterpreter::eBroadcastBitThreadShouldExit:
+ pEventType ="eBroadcastBitThreadShouldExit";
+ // ToDo: IOR: Reminder to maybe handle this here
+ //const MIuint nEventType = event.GetType();
+ //if( nEventType & lldb::SBCommandInterpreter::eBroadcastBitThreadShouldExit )
+ //{
+ // m_pClientDriver->SetExitApplicationFlag();
+ // vrbYesExit = true;
+ // return MIstatus::success;
+ //} break;
+ case lldb::SBCommandInterpreter::eBroadcastBitResetPrompt:
+ pEventType = "eBroadcastBitResetPrompt";
+ break;
+ case lldb::SBCommandInterpreter::eBroadcastBitQuitCommandReceived:
+ pEventType = "eBroadcastBitQuitCommandReceived";
+ break;
+ case lldb::SBCommandInterpreter::eBroadcastBitAsynchronousOutputData:
+ pEventType = "eBroadcastBitAsynchronousOutputData";
+ break;
+ case lldb::SBCommandInterpreter::eBroadcastBitAsynchronousErrorData:
+ pEventType = "eBroadcastBitAsynchronousErrorData";
+ break;
+ default:
+ {
+ const CMIUtilString msg( CMIUtilString::Format( MIRSRC( IDS_LLDBOUTOFBAND_ERR_UNKNOWN_EVENT ), "SBCommandInterpreter", (MIuint) nEventType ) );
+ SetErrorDescription( msg );
+ return MIstatus::failure;
+ }
+ }
+ m_pLog->WriteLog( CMIUtilString::Format( "##### An SBCommandInterpreter event occurred: %s", pEventType ) );
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Handle SBProcess event eBroadcastBitStateChanged.
+// Type: Method.
+// Args: vEvent - (R) An LLDB event object.
+// vrbExitAppEvent - (W) True - Received LLDB exit app event, false = did not.
+// Return: MIstatus::success - Functionality succeeded.
+// MIstatus::failure - Functionality failed.
+// Throws: None.
+//--
+bool CMICmnLLDBDebuggerHandleEvents::HandleProcessEventBroadcastBitStateChanged( const lldb::SBEvent & vEvent, bool & vrbExitAppEvent )
+{
+ bool bOk = ChkForStateChanges();
+ bOk = bOk && GetProcessStdout();
+ bOk = bOk && GetProcessStderr();
+ if( !bOk )
+ return MIstatus::failure;
+
+ // Something changed in the process; get the event and report the process's current
+ // status and location
+ const lldb::StateType eEventState = lldb::SBProcess::GetStateFromEvent( vEvent );
+ if( eEventState == lldb::eStateInvalid )
+ return MIstatus::success;
+
+ lldb::SBProcess process = lldb::SBProcess::GetProcessFromEvent( vEvent );
+ if( !process.IsValid() )
+ {
+ const CMIUtilString msg( CMIUtilString::Format( MIRSRC( IDS_LLDBOUTOFBAND_ERR_PROCESS_INVALID ), "SBProcess", "HandleProcessEventBroadcastBitStateChanged()" ) );
+ SetErrorDescription( msg );
+ return MIstatus::failure;
+ }
+
+ bool bShouldBrk = true;
+ const MIchar * pEventType = "";
+ switch( eEventState )
+ {
+ case lldb::eStateUnloaded:
+ pEventType = "eStateUnloaded";
+ break;
+ case lldb::eStateConnected:
+ pEventType = "eStateConnected";
+ break;
+ case lldb::eStateAttaching:
+ pEventType = "eStateAttaching";
+ break;
+ case lldb::eStateLaunching:
+ pEventType ="eStateLaunching";
+ break;
+ case lldb::eStateStopped:
+ pEventType = "eStateStopped";
+ bOk = HandleProcessEventStateStopped( bShouldBrk );
+ if( bShouldBrk )
+ break;
+ case lldb::eStateCrashed:
+ case lldb::eStateSuspended:
+ pEventType = "eStateSuspended";
+ bOk = HandleProcessEventStateSuspended( vEvent );
+ break;
+ case lldb::eStateRunning:
+ pEventType = "eStateRunning";
+ bOk = HandleProcessEventStateRunning();
+ break;
+ case lldb::eStateStepping:
+ pEventType = "eStateStepping";
+ break;
+ case lldb::eStateDetached:
+ pEventType = "eStateDetached";
+ break;
+ case lldb::eStateExited:
+ pEventType = "eStateExited";
+ vrbExitAppEvent = true;
+ bOk = HandleProcessEventStateExited();
+ break;
+ default:
+ {
+ const CMIUtilString msg( CMIUtilString::Format( MIRSRC( IDS_LLDBOUTOFBAND_ERR_UNKNOWN_EVENT ), "SBProcess BroadcastBitStateChanged", (MIuint) eEventState ) );
+ SetErrorDescription( msg );
+ return MIstatus::failure;
+ }
+ }
+
+ // ToDo: Remove when finished coding application
+ m_pLog->WriteLog( CMIUtilString::Format( "##### An SB Process event BroadcastBitStateChanged occurred: %s", pEventType ) );
+
+ return bOk;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Asynchronous event handler for LLDB Process state suspended.
+// Type: Method.
+// Args: vEvent - (R) An LLDB event object.
+// Return: MIstatus::success - Functionality succeeded.
+// MIstatus::failure - Functionality failed.
+// Throws: None.
+//--
+bool CMICmnLLDBDebuggerHandleEvents::HandleProcessEventStateSuspended( const lldb::SBEvent & vEvent )
+{
+ // Make sure the program hasn't been auto-restarted:
+ if( lldb::SBProcess::GetRestartedFromEvent( vEvent ) )
+ return MIstatus::success;
+
+ bool bOk = MIstatus::success;
+ lldb::SBDebugger & rDebugger = CMICmnLLDBDebugSessionInfo::Instance().m_rLldbDebugger;
+ lldb::SBProcess & rProcess = CMICmnLLDBDebugSessionInfo::Instance().m_lldbProcess;
+ lldb::SBTarget target = rProcess.GetTarget();
+ if( rDebugger.GetSelectedTarget() == target )
+ {
+ if( !UpdateSelectedThread() )
+ return MIstatus::failure;
+
+ lldb::SBCommandReturnObject result;
+ const lldb::ReturnStatus status = rDebugger.GetCommandInterpreter().HandleCommand( "process status", result, false ); MIunused( status );
+ bOk = TextToStderr( result.GetError() );
+ bOk = bOk && TextToStdout( result.GetOutput() );
+ }
+ else
+ {
+ lldb::SBStream streamOut;
+ const MIuint nTargetIndex = rDebugger.GetIndexOfTarget( target );
+ if( nTargetIndex != UINT_MAX )
+ streamOut.Printf( "Target %d: (", nTargetIndex );
+ else
+ streamOut.Printf( "Target <unknown index>: (" );
+ target.GetDescription( streamOut, lldb::eDescriptionLevelBrief );
+ streamOut.Printf( ") stopped.\n" );
+ bOk = TextToStdout( streamOut.GetData() );
+ }
+
+ return bOk;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Print to stdout MI formatted text to indicate process stopped.
+// Type: Method.
+// Args: vwrbShouldBrk - (W) True = Yes break, false = do not.
+// Return: MIstatus::success - Functionality succeeded.
+// MIstatus::failure - Functionality failed.
+// Throws: None.
+//--
+bool CMICmnLLDBDebuggerHandleEvents::HandleProcessEventStateStopped( bool & vwrbShouldBrk )
+{
+ if( !UpdateSelectedThread() )
+ return MIstatus::failure;
+
+ const MIchar * pEventType = "";
+ bool bOk = MIstatus::success;
+ lldb::SBProcess & rProcess = CMICmnLLDBDebugSessionInfo::Instance().m_lldbProcess;
+ const lldb::StopReason eStoppedReason = rProcess.GetSelectedThread().GetStopReason();
+ switch( eStoppedReason )
+ {
+ case lldb::eStopReasonInvalid:
+ pEventType = "eStopReasonInvalid";
+ vwrbShouldBrk = false;
+ break;
+ case lldb::eStopReasonNone:
+ pEventType = "eStopReasonNone";
+ break;
+ case lldb::eStopReasonTrace:
+ pEventType = "eStopReasonTrace";
+ bOk = HandleProcessEventStopReasonTrace();
+ break;
+ case lldb::eStopReasonBreakpoint:
+ pEventType = "eStopReasonBreakpoint";
+ bOk = HandleProcessEventStopReasonBreakpoint();
+ break;
+ case lldb::eStopReasonWatchpoint:
+ pEventType = "eStopReasonWatchpoint";
+ break;
+ case lldb::eStopReasonSignal:
+ pEventType = "eStopReasonSignal";
+ bOk = HandleProcessEventStopSignal( vwrbShouldBrk );
+ break;
+ case lldb::eStopReasonException:
+ pEventType ="eStopReasonException";
+ break;
+ case lldb::eStopReasonExec:
+ pEventType = "eStopReasonExec";
+ break;
+ case lldb::eStopReasonPlanComplete:
+ pEventType = "eStopReasonPlanComplete";
+ bOk = HandleProcessEventStopReasonTrace();
+ break;
+ case lldb::eStopReasonThreadExiting:
+ pEventType = "eStopReasonThreadExiting";
+ break;
+ default:
+ {
+ vwrbShouldBrk = false;
+
+ // MI print "*stopped,reason=\"%d\",stopped-threads=\"all\",from-thread=\"%u\""
+ const CMIUtilString strReason( CMIUtilString::Format( "%d", eStoppedReason ) );
+ const CMICmnMIValueConst miValueConst( strReason );
+ const CMICmnMIValueResult miValueResult( "reason", miValueConst );
+ CMICmnMIOutOfBandRecord miOutOfBandRecord( CMICmnMIOutOfBandRecord::eOutOfBand_Stopped, miValueResult );
+ const CMICmnMIValueConst miValueConst2( "all" );
+ const CMICmnMIValueResult miValueResult2( "stopped-threads", miValueConst2 );
+ bOk = miOutOfBandRecord.Add( miValueResult2 );
+ const CMIUtilString strFromThread( CMIUtilString::Format( "%u", rProcess.GetSelectedThread().GetIndexID() ) );
+ const CMICmnMIValueConst miValueConst3( strFromThread );
+ const CMICmnMIValueResult miValueResult3( "from-thread", miValueConst3 );
+ bOk = bOk && miOutOfBandRecord.Add( miValueResult3 );
+ bOk = bOk && MiOutOfBandRecordToStdout( miOutOfBandRecord );
+ bOk = bOk && TextToStdout( "(gdb)" );
+ }
+ }
+
+ // ToDo: Remove when finished coding application
+ m_pLog->WriteLog( CMIUtilString::Format( "##### An SB Process event stop state occurred: %s", pEventType ) );
+
+ return bOk;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Asynchronous event handler for LLDB Process stop signal.
+// Type: Method.
+// Args: vwrbShouldBrk - (W) True = Yes break, false = do not.
+// Return: MIstatus::success - Functionality succeeded.
+// MIstatus::failure - Functionality failed.
+// Throws: None.
+//--
+bool CMICmnLLDBDebuggerHandleEvents::HandleProcessEventStopSignal( bool & vwrbShouldBrk )
+{
+ bool bOk = MIstatus::success;
+
+ lldb::SBProcess & rProcess = CMICmnLLDBDebugSessionInfo::Instance().m_lldbProcess;
+ const MIuint64 nStopReason = rProcess.GetSelectedThread().GetStopReasonDataAtIndex( 0 );
+ switch( nStopReason )
+ {
+ case 2: // Terminal interrupt signal. SIGINT
+ {
+ // MI print "*stopped,reason=\"signal-received\",signal-name=\"SIGNINT\",signal-meaning=\"Interrupt\",frame={%s}"
+ const CMICmnMIValueConst miValueConst( "signal-received" );
+ const CMICmnMIValueResult miValueResult( "reason", miValueConst );
+ CMICmnMIOutOfBandRecord miOutOfBandRecord( CMICmnMIOutOfBandRecord::eOutOfBand_Stopped, miValueResult );
+ const CMICmnMIValueConst miValueConst2( "SIGINT" );
+ const CMICmnMIValueResult miValueResult2( "signal-name", miValueConst2 );
+ bOk = miOutOfBandRecord.Add( miValueResult2 );
+ const CMICmnMIValueConst miValueConst3( "Interrupt" );
+ const CMICmnMIValueResult miValueResult3( "signal-meaning", miValueConst3 );
+ bOk = bOk && miOutOfBandRecord.Add( miValueResult3 );
+ CMICmnMIValueTuple miValueTuple;
+ bOk = bOk && MiHelpGetCurrentThreadFrame( miValueTuple );
+ const CMICmnMIValueResult miValueResult5( "frame", miValueTuple );
+ bOk = bOk && miOutOfBandRecord.Add( miValueResult5 );
+ bOk = bOk && MiOutOfBandRecordToStdout( miOutOfBandRecord );
+ bOk = bOk && TextToStdout( "(gdb)" );
+ }
+ break;
+ case 11: // Invalid memory reference. SIGSEGV
+ {
+ // MI print "*stopped,reason=\"signal-received\",signal-name=\"SIGSEGV\",signal-meaning=\"Segmentation fault\",thread-id=\"%d\",frame={%s}"
+ const CMICmnMIValueConst miValueConst( "signal-received" );
+ const CMICmnMIValueResult miValueResult( "reason", miValueConst );
+ CMICmnMIOutOfBandRecord miOutOfBandRecord( CMICmnMIOutOfBandRecord::eOutOfBand_Stopped, miValueResult );
+ const CMICmnMIValueConst miValueConst2( "SIGSEGV" );
+ const CMICmnMIValueResult miValueResult2( "signal-name", miValueConst2 );
+ bOk = miOutOfBandRecord.Add( miValueResult2 );
+ const CMICmnMIValueConst miValueConst3( "Segmentation fault" );
+ const CMICmnMIValueResult miValueResult3( "signal-meaning", miValueConst3 );
+ bOk = bOk && miOutOfBandRecord.Add( miValueResult3 );
+ const CMIUtilString strThreadId( CMIUtilString::Format( "%d", rProcess.GetSelectedThread().GetIndexID() ) );
+ const CMICmnMIValueConst miValueConst4( strThreadId );
+ const CMICmnMIValueResult miValueResult4( "thread-id", miValueConst4 );
+ bOk = bOk && miOutOfBandRecord.Add( miValueResult4 );
+ CMICmnMIValueTuple miValueTuple;
+ bOk = bOk && MiHelpGetCurrentThreadFrame( miValueTuple );
+ const CMICmnMIValueResult miValueResult5( "frame", miValueTuple );
+ bOk = bOk && miOutOfBandRecord.Add( miValueResult5 );
+ bOk = bOk && MiOutOfBandRecordToStdout( miOutOfBandRecord );
+ // Note no "(gdb)" output here
+ }
+ break;
+ case 19:
+ if( rProcess.IsValid() )
+ rProcess.Continue();
+ break;
+ case 5: // Trace/breakpoint trap. SIGTRAP
+ {
+ lldb::SBThread thread = rProcess.GetSelectedThread();
+ const MIuint nFrames = thread.GetNumFrames();
+ if( nFrames > 0 )
+ {
+ lldb::SBFrame frame = thread.GetFrameAtIndex( 0 );
+ const char * pFnName = frame.GetFunctionName();
+ if( pFnName != nullptr )
+ {
+ const CMIUtilString fnName = CMIUtilString( pFnName );
+ static const CMIUtilString threadCloneFn = CMIUtilString( "__pthread_clone" );
+
+ if( CMIUtilString::Compare( threadCloneFn, fnName ) )
+ {
+ if( rProcess.IsValid() )
+ {
+ rProcess.Continue();
+ vwrbShouldBrk = true;
+ break;
+ }
+ }
+ }
+ }
+ }
+ default:
+ {
+ // MI print "*stopped,reason=\"signal-received\",signal=\"%lld\",stopped-threads=\"all\""
+ const CMICmnMIValueConst miValueConst( "signal-received" );
+ const CMICmnMIValueResult miValueResult( "reason", miValueConst );
+ CMICmnMIOutOfBandRecord miOutOfBandRecord( CMICmnMIOutOfBandRecord::eOutOfBand_Stopped, miValueResult );
+ const CMIUtilString strReason( CMIUtilString::Format( "%lld", nStopReason ) );
+ const CMICmnMIValueConst miValueConst2( strReason );
+ const CMICmnMIValueResult miValueResult2( "signal", miValueConst2 );
+ bOk = miOutOfBandRecord.Add( miValueResult2 );
+ const CMICmnMIValueConst miValueConst3( "all" );
+ const CMICmnMIValueResult miValueResult3( "stopped-threads", miValueConst3 );
+ bOk = bOk && miOutOfBandRecord.Add( miValueResult3 );
+ bOk = bOk && MiOutOfBandRecordToStdout( miOutOfBandRecord );
+ bOk = bOk && TextToStdout( "(gdb)" );
+ }
+ } // switch( nStopReason )
+
+ return bOk;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Form partial MI response in a MI value tuple object.
+// Type: Method.
+// Args: vwrMiValueTuple - (W) MI value tuple object.
+// Return: MIstatus::success - Functionality succeeded.
+// MIstatus::failure - Functionality failed.
+// Throws: None.
+//--
+bool CMICmnLLDBDebuggerHandleEvents::MiHelpGetCurrentThreadFrame( CMICmnMIValueTuple & vwrMiValueTuple )
+{
+ CMIUtilString strThreadFrame;
+ lldb::SBProcess & rProcess = CMICmnLLDBDebugSessionInfo::Instance().m_lldbProcess;
+ lldb::SBThread thread = rProcess.GetSelectedThread();
+ const MIuint nFrame = thread.GetNumFrames();
+ if( nFrame == 0 )
+ {
+ // MI print "addr=\"??\",func=\"??\",file=\"??\",fullname=\"??\",line=\"??\""
+ const CMICmnMIValueConst miValueConst( "??" );
+ const CMICmnMIValueResult miValueResult( "addr", miValueConst );
+ CMICmnMIValueTuple miValueTuple( miValueResult );
+ const CMICmnMIValueResult miValueResult2( "func", miValueConst );
+ miValueTuple.Add( miValueResult2 );
+ const CMICmnMIValueResult miValueResult4( "file", miValueConst );
+ miValueTuple.Add( miValueResult4 );
+ const CMICmnMIValueResult miValueResult5( "fullname", miValueConst );
+ miValueTuple.Add( miValueResult5 );
+ const CMICmnMIValueResult miValueResult6( "line", miValueConst );
+ miValueTuple.Add( miValueResult6 );
+
+ vwrMiValueTuple = miValueTuple;
+
+ return MIstatus::success;
+ }
+
+ CMICmnMIValueTuple miValueTuple;
+ if( !CMICmnLLDBDebugSessionInfo::Instance().MIResponseFormFrameInfo( thread, 0, miValueTuple ) )
+ {
+ SetErrorDescription( CMIUtilString::Format( MIRSRC( IDS_LLDBOUTOFBAND_ERR_FORM_MI_RESPONSE ), "MiHelpGetCurrentThreadFrame()" ) );
+ return MIstatus::failure;
+ }
+
+ vwrMiValueTuple = miValueTuple;
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Asynchronous event handler for LLDB Process stop reason breakpoint.
+// Type: Method.
+// Args: None.
+// Return: MIstatus::success - Functionality succeeded.
+// MIstatus::failure - Functionality failed.
+// Throws: None.
+//--
+bool CMICmnLLDBDebuggerHandleEvents::HandleProcessEventStopReasonBreakpoint( void )
+{
+ // CODETAG_DEBUG_SESSION_RUNNING_PROG_RECEIVED_SIGINT_PAUSE_PROGRAM
+ if( !CMIDriver::Instance().SetDriverStateRunningNotDebugging() )
+ {
+ const CMIUtilString & rErrMsg( CMIDriver::Instance().GetErrorDescription() );
+ SetErrorDescription( CMIUtilString::Format( MIRSRC( IDS_LLDBOUTOFBAND_ERR_SETNEWDRIVERSTATE ), "HandleProcessEventStopReasonBreakpoint()", rErrMsg.c_str() ) );
+ return MIstatus::failure;
+ }
+
+ lldb::SBProcess & rProcess = CMICmnLLDBDebugSessionInfo::Instance().m_lldbProcess;
+ const MIuint64 brkPtId = rProcess.GetSelectedThread().GetStopReasonDataAtIndex( 0 );
+ lldb::SBBreakpoint brkPt = CMICmnLLDBDebugSessionInfo::Instance().m_lldbTarget.GetBreakpointAtIndex( (MIuint) brkPtId );
+
+ return MiStoppedAtBreakPoint( brkPtId, brkPt );
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Form the MI Out-of-band response for stopped reason on hitting a break point.
+// Type: Method.
+// Args: vBrkPtId - (R) The LLDB break point's ID
+// vBrkPt - (R) THe LLDB break point object.
+// Return: MIstatus::success - Functionality succeeded.
+// MIstatus::failure - Functionality failed.
+// Throws: None.
+//--
+bool CMICmnLLDBDebuggerHandleEvents::MiStoppedAtBreakPoint( const MIuint64 vBrkPtId, const lldb::SBBreakpoint & vBrkPt )
+{
+ bool bOk = MIstatus::success;
+
+ lldb::SBProcess & rProcess = CMICmnLLDBDebugSessionInfo::Instance().m_lldbProcess;
+ lldb::SBThread thread = rProcess.GetSelectedThread();
+ const MIuint nFrame = thread.GetNumFrames();
+ if( nFrame == 0 )
+ {
+ // MI print "*stopped,reason=\"breakpoint-hit\",disp=\"del\",bkptno=\"%d\",frame={},thread-id=\"%d\",stopped-threads=\"all\""
+ const CMICmnMIValueConst miValueConst( "breakpoint-hit" );
+ const CMICmnMIValueResult miValueResult( "reason", miValueConst );
+ CMICmnMIOutOfBandRecord miOutOfBandRecord( CMICmnMIOutOfBandRecord::eOutOfBand_Stopped, miValueResult );
+ const CMICmnMIValueConst miValueConst2( "del" );
+ const CMICmnMIValueResult miValueResult2( "disp", miValueConst2 );
+ bOk = miOutOfBandRecord.Add( miValueResult2 );
+ const CMIUtilString strBkp( CMIUtilString::Format( "%d", vBrkPtId ) );
+ const CMICmnMIValueConst miValueConst3( strBkp );
+ CMICmnMIValueResult miValueResult3( "bkptno", miValueConst3 );
+ bOk = bOk && miOutOfBandRecord.Add( miValueResult3 );
+ const CMICmnMIValueConst miValueConst4( "{}" );
+ const CMICmnMIValueResult miValueResult4( "frame", miValueConst4 );
+ bOk = bOk && miOutOfBandRecord.Add( miValueResult4 );
+ const CMIUtilString strThreadId( CMIUtilString::Format( "%d", vBrkPt.GetThreadIndex() ) );
+ const CMICmnMIValueConst miValueConst5( strThreadId );
+ const CMICmnMIValueResult miValueResult5( "thread-id", miValueConst5 );
+ bOk = bOk && miOutOfBandRecord.Add( miValueResult5 );
+ const CMICmnMIValueConst miValueConst6( "all" );
+ const CMICmnMIValueResult miValueResult6( "stopped-threads", miValueConst6 );
+ bOk = bOk && miOutOfBandRecord.Add( miValueResult6 );
+ bOk = bOk && MiOutOfBandRecordToStdout( miOutOfBandRecord );
+ bOk = bOk && TextToStdout( "(gdb)" );
+ return bOk;
+ }
+
+ CMICmnLLDBDebugSessionInfo & rSession = CMICmnLLDBDebugSessionInfo::Instance();
+
+ lldb::SBFrame frame = thread.GetFrameAtIndex( 0 );
+ lldb::addr_t pc = 0;
+ CMIUtilString fnName;
+ CMIUtilString fileName;
+ CMIUtilString path;
+ MIuint nLine = 0;
+ if( !rSession.GetFrameInfo( frame, pc, fnName, fileName, path, nLine ) )
+ {
+ SetErrorDescription( CMIUtilString::Format( MIRSRC( IDS_LLDBOUTOFBAND_ERR_FRAME_INFO_GET ), "MiStoppedAtBreakPoint()" ) );
+ return MIstatus::failure;
+ }
+
+ // MI print "*stopped,reason=\"breakpoint-hit\",disp=\"del\",bkptno=\"%d\",frame={addr=\"0x%08x\",func=\"%s\",args=[],file=\"%s\",fullname=\"%s\",line=\"%d\"},thread-id=\"%d\",stopped-threads=\"all\""
+ const CMICmnMIValueConst miValueConst( "breakpoint-hit" );
+ const CMICmnMIValueResult miValueResult( "reason", miValueConst );
+ CMICmnMIOutOfBandRecord miOutOfBandRecord( CMICmnMIOutOfBandRecord::eOutOfBand_Stopped, miValueResult );
+ const CMICmnMIValueConst miValueConstA( "del" );
+ const CMICmnMIValueResult miValueResultA( "disp", miValueConstA );
+ bOk = miOutOfBandRecord.Add( miValueResultA );
+ const CMIUtilString strBkp( CMIUtilString::Format( "%d", vBrkPtId ) );
+ const CMICmnMIValueConst miValueConstB( strBkp );
+ CMICmnMIValueResult miValueResultB( "bkptno", miValueConstB );
+ bOk = bOk && miOutOfBandRecord.Add( miValueResultB );
+
+ // frame={addr=\"0x%08x\",func=\"%s\",args=[],file=\"%s\",fullname=\"%s\",line=\"%d\"}
+ if( bOk )
+ {
+ CMICmnMIValueList miValueList( true );
+ const MIuint maskVarTypes = 0x1000;
+ bOk = rSession.MIResponseFormVariableInfo2( frame, maskVarTypes, miValueList );
+
+ CMICmnMIValueTuple miValueTuple;
+ bOk = bOk && rSession.MIResponseFormFrameInfo2( pc, miValueList.GetString(), fnName, fileName, path, nLine, miValueTuple );
+ const CMICmnMIValueResult miValueResult8( "frame", miValueTuple );
+ bOk = bOk && miOutOfBandRecord.Add( miValueResult8 );
+ }
+
+ // Add to MI thread-id=\"%d\",stopped-threads=\"all\"
+ if( bOk )
+ {
+ const CMIUtilString strThreadId( CMIUtilString::Format( "%d", thread.GetIndexID() ) );
+ const CMICmnMIValueConst miValueConst8( strThreadId );
+ const CMICmnMIValueResult miValueResult8( "thread-id", miValueConst8 );
+ bOk = miOutOfBandRecord.Add( miValueResult8 );
+ }
+ if( bOk )
+ {
+ const CMICmnMIValueConst miValueConst9( "all" );
+ const CMICmnMIValueResult miValueResult9( "stopped-threads", miValueConst9 );
+ bOk = miOutOfBandRecord.Add( miValueResult9 );
+ bOk = MiOutOfBandRecordToStdout( miOutOfBandRecord );
+ bOk = bOk && TextToStdout( "(gdb)" );
+ }
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Asynchronous event handler for LLDB Process stop reason trace.
+// Type: Method.
+// Args: None.
+// Return: MIstatus::success - Functionality succeeded.
+// MIstatus::failure - Functionality failed.
+// Throws: None.
+//--
+bool CMICmnLLDBDebuggerHandleEvents::HandleProcessEventStopReasonTrace( void )
+{
+ bool bOk = true;
+ lldb::SBProcess & rProcess = CMICmnLLDBDebugSessionInfo::Instance().m_lldbProcess;
+ lldb::SBThread thread = rProcess.GetSelectedThread();
+ const MIuint nFrame = thread.GetNumFrames();
+ if( nFrame == 0 )
+ {
+ // MI print "*stopped,reason=\"trace\",stopped-threads=\"all\""
+ const CMICmnMIValueConst miValueConst( "trace" );
+ const CMICmnMIValueResult miValueResult( "reason", miValueConst );
+ CMICmnMIOutOfBandRecord miOutOfBandRecord( CMICmnMIOutOfBandRecord::eOutOfBand_Stopped, miValueResult );
+ const CMICmnMIValueConst miValueConst2( "all" );
+ const CMICmnMIValueResult miValueResult2( "stopped-threads", miValueConst2 );
+ bOk = miOutOfBandRecord.Add( miValueResult2 );
+ bOk = MiOutOfBandRecordToStdout( miOutOfBandRecord );
+ bOk = bOk && TextToStdout( "(gdb)" );
+ return bOk;
+ }
+
+ CMICmnLLDBDebugSessionInfo & rSession = CMICmnLLDBDebugSessionInfo::Instance();
+
+ // MI print "*stopped,reason=\"end-stepping-range\",frame={addr=\"0x%08x\",func=\"%s\",args=[\"%s\"],file=\"%s\",fullname=\"%s\",line=\"%d\"},thread-id=\"%d\",stopped-threads=\"all\""
+ lldb::SBFrame frame = thread.GetFrameAtIndex( 0 );
+ lldb::addr_t pc = 0;
+ CMIUtilString fnName;
+ CMIUtilString fileName;
+ CMIUtilString path;
+ MIuint nLine = 0;
+ if( !rSession.GetFrameInfo( frame, pc, fnName, fileName, path, nLine ) )
+ {
+ SetErrorDescription( CMIUtilString::Format( MIRSRC( IDS_LLDBOUTOFBAND_ERR_FRAME_INFO_GET ), "HandleProcessEventStopReasonTrace()" ) );
+ return MIstatus::failure;
+ }
+
+ // Function args
+ CMICmnMIValueList miValueList( true );
+ const MIuint maskVarTypes = 0x1000;
+ if( !rSession.MIResponseFormVariableInfo2( frame, maskVarTypes, miValueList ) )
+ return MIstatus::failure;
+ CMICmnMIValueTuple miValueTuple;
+ if( !rSession.MIResponseFormFrameInfo2( pc, miValueList.GetString(), fnName, fileName, path, nLine, miValueTuple ) )
+ return MIstatus::failure;
+
+ const CMICmnMIValueConst miValueConst( "end-stepping-range" );
+ const CMICmnMIValueResult miValueResult( "reason", miValueConst );
+ CMICmnMIOutOfBandRecord miOutOfBandRecord( CMICmnMIOutOfBandRecord::eOutOfBand_Stopped, miValueResult );
+ const CMICmnMIValueResult miValueResult2( "frame", miValueTuple );
+ bOk = miOutOfBandRecord.Add( miValueResult2 );
+
+ // Add to MI thread-id=\"%d\",stopped-threads=\"all\"
+ if( bOk )
+ {
+ const CMIUtilString strThreadId( CMIUtilString::Format( "%d", thread.GetIndexID() ) );
+ const CMICmnMIValueConst miValueConst8( strThreadId );
+ const CMICmnMIValueResult miValueResult8( "thread-id", miValueConst8 );
+ bOk = miOutOfBandRecord.Add( miValueResult8 );
+ }
+ if( bOk )
+ {
+ const CMICmnMIValueConst miValueConst9( "all" );
+ const CMICmnMIValueResult miValueResult9( "stopped-threads", miValueConst9 );
+ bOk = miOutOfBandRecord.Add( miValueResult9 );
+ bOk = MiOutOfBandRecordToStdout( miOutOfBandRecord );
+ bOk = bOk && TextToStdout( "(gdb)" );
+ }
+
+ return bOk;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Asynchronous function update selected thread.
+// Type: Method.
+// Args: None.
+// Return: MIstatus::success - Functionality succeeded.
+// MIstatus::failure - Functionality failed.
+// Throws: None.
+//--
+bool CMICmnLLDBDebuggerHandleEvents::UpdateSelectedThread( void )
+{
+ lldb::SBProcess process = CMICmnLLDBDebugSessionInfo::Instance().m_rLldbDebugger.GetSelectedTarget().GetProcess();
+ if( !process.IsValid() )
+ return MIstatus::success;
+
+ lldb::SBThread currentThread = process.GetSelectedThread();
+ lldb::SBThread thread;
+ const lldb::StopReason eCurrentThreadStoppedReason = currentThread.GetStopReason();
+ if( !currentThread.IsValid() || (eCurrentThreadStoppedReason == lldb::eStopReasonInvalid) || (eCurrentThreadStoppedReason == lldb::eStopReasonNone) )
+ {
+ // Prefer a thread that has just completed its plan over another thread as current thread
+ lldb::SBThread planThread;
+ lldb::SBThread otherThread;
+ const size_t nThread = process.GetNumThreads();
+ for( MIuint i = 0; i < nThread; i++ )
+ {
+ // GetThreadAtIndex() uses a base 0 index
+ // GetThreadByIndexID() uses a base 1 index
+ thread = process.GetThreadAtIndex( i );
+ const lldb::StopReason eThreadStopReason = thread.GetStopReason();
+ switch( eThreadStopReason )
+ {
+ case lldb::eStopReasonTrace:
+ case lldb::eStopReasonBreakpoint:
+ case lldb::eStopReasonWatchpoint:
+ case lldb::eStopReasonSignal:
+ case lldb::eStopReasonException:
+ if( !otherThread.IsValid() )
+ otherThread = thread;
+ break;
+ case lldb::eStopReasonPlanComplete:
+ if( !planThread.IsValid() )
+ planThread = thread;
+ break;
+ case lldb::eStopReasonInvalid:
+ case lldb::eStopReasonNone:
+ default:
+ break;
+ }
+ }
+ if( planThread.IsValid() )
+ process.SetSelectedThread( planThread );
+ else if( otherThread.IsValid() )
+ process.SetSelectedThread( otherThread );
+ else
+ {
+ if( currentThread.IsValid() )
+ thread = currentThread;
+ else
+ thread = process.GetThreadAtIndex( 0 );
+
+ if( thread.IsValid() )
+ process.SetSelectedThread( thread );
+ }
+ } // if( !currentThread.IsValid() || (eCurrentThreadStoppedReason == lldb::eStopReasonInvalid) || (eCurrentThreadStoppedReason == lldb::eStopReasonNone) )
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Print to stdout "*running,thread-id=\"all\"", "(gdb)".
+// Type: Method.
+// Args: None.
+// Return: MIstatus::success - Functionality succeeded.
+// MIstatus::failure - Functionality failed.
+// Throws: None.
+//--
+bool CMICmnLLDBDebuggerHandleEvents::HandleProcessEventStateRunning( void )
+{
+ CMICmnMIValueConst miValueConst( "all" );
+ CMICmnMIValueResult miValueResult( "thread-id", miValueConst );
+ CMICmnMIOutOfBandRecord miOutOfBandRecord( CMICmnMIOutOfBandRecord::eOutOfBand_Running, miValueResult );
+ bool bOk = MiOutOfBandRecordToStdout( miOutOfBandRecord );
+ bOk = bOk && TextToStdout( "(gdb)" );
+
+ return bOk;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Print to stdout "=thread-exited,id=\"%ld\",group-id=\"i1\"",
+// "=thread-group-exited,id=\"i1\",exit-code=\"0\""),
+// "*stopped,reason=\"exited-normally\"",
+// "(gdb)"
+// Type: Method.
+// Args: None.
+// Return: MIstatus::success - Functionality succeeded.
+// MIstatus::failure - Functionality failed.
+// Throws: None.
+//--
+bool CMICmnLLDBDebuggerHandleEvents::HandleProcessEventStateExited( void )
+{
+ const CMIUtilString strId( CMIUtilString::Format( "%ld", 1 ) );
+ CMICmnMIValueConst miValueConst( strId );
+ CMICmnMIValueResult miValueResult( "id", miValueConst );
+ CMICmnMIOutOfBandRecord miOutOfBandRecord( CMICmnMIOutOfBandRecord::eOutOfBand_ThreadExited, miValueResult );
+ CMICmnMIValueConst miValueConst2( "i1" );
+ CMICmnMIValueResult miValueResult2( "group-id", miValueConst2 );
+ bool bOk = miOutOfBandRecord.Add( miValueResult2 );
+ bOk = bOk && MiOutOfBandRecordToStdout( miOutOfBandRecord );
+ if( bOk )
+ {
+ CMICmnMIValueConst miValueConst3( "i1" );
+ CMICmnMIValueResult miValueResult3( "id", miValueConst3 );
+ CMICmnMIOutOfBandRecord miOutOfBandRecord2( CMICmnMIOutOfBandRecord::eOutOfBand_ThreadGroupExited, miValueResult3 );
+ CMICmnMIValueConst miValueConst2( "0" );
+ CMICmnMIValueResult miValueResult2( "exit-code", miValueConst2 );
+ bOk = miOutOfBandRecord2.Add( miValueResult2 );
+ bOk = bOk && MiOutOfBandRecordToStdout( miOutOfBandRecord2 );
+ }
+ if( bOk )
+ {
+ CMICmnMIValueConst miValueConst4( "exited-normally" );
+ CMICmnMIValueResult miValueResult4( "reason", miValueConst4 );
+ CMICmnMIOutOfBandRecord miOutOfBandRecord3( CMICmnMIOutOfBandRecord::eOutOfBand_Stopped, miValueResult4 );
+ bOk = MiOutOfBandRecordToStdout( miOutOfBandRecord3 );
+ }
+ bOk = bOk && TextToStdout( "(gdb)" );
+
+ return bOk;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Drain all stdout so we don't see any output come after we print our prompts.
+// The process has stuff waiting for stdout; get it and write it out to the
+// appropriate place.
+// Type: Method.
+// Args: None.
+// Return: MIstatus::success - Functionality succeeded.
+// MIstatus::failure - Functionality failed.
+// Throws: None.
+//--
+bool CMICmnLLDBDebuggerHandleEvents::GetProcessStdout( void )
+{
+ bool bOk = MIstatus::success;
+
+ char c;
+ size_t nBytes = 0;
+ CMIUtilString text;
+ lldb::SBProcess process = CMICmnLLDBDebugSessionInfo::Instance().m_rLldbDebugger.GetSelectedTarget().GetProcess();
+ while( process.GetSTDOUT( &c, 1 ) > 0 )
+ {
+ CMIUtilString str;
+ if( ConvertPrintfCtrlCodeToString( c, str ) )
+ text += str;
+ nBytes++;
+ }
+ if( nBytes > 0 )
+ {
+ const CMIUtilString t( CMIUtilString::Format( "~\"%s\"", text.c_str() ) );
+ bOk = TextToStdout( t );
+ }
+
+ return bOk;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Drain all stderr so we don't see any output come after we print our prompts.
+// The process has stuff waiting for stderr; get it and write it out to the
+// appropriate place.
+// Type: Method.
+// Args: None.
+// Return: MIstatus::success - Functionality succeeded.
+// MIstatus::failure - Functionality failed.
+// Throws: None.
+//--
+bool CMICmnLLDBDebuggerHandleEvents::GetProcessStderr( void )
+{
+ bool bOk = MIstatus::success;
+
+ char c;
+ size_t nBytes = 0;
+ CMIUtilString text;
+ lldb::SBProcess process = CMICmnLLDBDebugSessionInfo::Instance().m_rLldbDebugger.GetSelectedTarget().GetProcess();
+ while( process.GetSTDERR( &c, 1 ) > 0 )
+ {
+ CMIUtilString str;
+ if( ConvertPrintfCtrlCodeToString( c, str ) )
+ text += str;
+ nBytes++;
+ }
+ if( nBytes > 0 )
+ {
+ const CMIUtilString t( CMIUtilString::Format( "~\"%s\"", text.c_str() ) );
+ bOk = TextToStdout( t );
+ }
+
+ return bOk;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Convert text stream control codes to text equivalent.
+// Type: Method.
+// Args: vCtrl - (R) The control code.
+// vwrStrEquivalent - (W) The text equivalent.
+// Return: MIstatus::success - Functionality succeeded.
+// MIstatus::failure - Functionality failed.
+// Throws: None.
+//--
+bool CMICmnLLDBDebuggerHandleEvents::ConvertPrintfCtrlCodeToString( const MIchar vCtrl, CMIUtilString & vwrStrEquivalent )
+{
+ switch( vCtrl )
+ {
+ case '\033': vwrStrEquivalent = "\\e"; break;
+ case '\a': vwrStrEquivalent = "\\a"; break;
+ case '\b': vwrStrEquivalent = "\\b"; break;
+ case '\f': vwrStrEquivalent = "\\f"; break;
+ case '\n': vwrStrEquivalent = "\\n"; break;
+ case '\r': vwrStrEquivalent = "\\r"; break;
+ case '\t': vwrStrEquivalent = "\\t"; break;
+ case '\v': vwrStrEquivalent = "\\v"; break;
+ default:
+ vwrStrEquivalent = CMIUtilString::Format( "%c", vCtrl );
+ break;
+ }
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Asynchronous event function check for state changes.
+// Type: Method.
+// Args: None.
+// Return: MIstatus::success - Functionality succeeded.
+// MIstatus::failure - Functionality failed.
+// Throws: None.
+//--
+bool CMICmnLLDBDebuggerHandleEvents::ChkForStateChanges( void )
+{
+ lldb::SBProcess & rProcess = CMICmnLLDBDebugSessionInfo::Instance().m_lldbProcess;
+ if( !rProcess.IsValid() )
+ return MIstatus::success;
+ lldb::SBTarget & rTarget = CMICmnLLDBDebugSessionInfo::Instance().m_lldbTarget;
+ if( !rTarget.IsValid() )
+ return MIstatus::success;
+
+ bool bOk = MIstatus::success;
+
+ // Check for created threads
+ const MIuint nThread = rProcess.GetNumThreads();
+ for( MIuint i = 0; i < nThread; i++ )
+ {
+ // GetThreadAtIndex() uses a base 0 index
+ // GetThreadByIndexID() uses a base 1 index
+ lldb::SBThread thread = rProcess.GetThreadAtIndex( i );
+ if( !thread.IsValid() )
+ continue;
+
+ CMICmnLLDBDebugSessionInfo::VecActiveThreadId_t::const_iterator it = CMICmnLLDBDebugSessionInfo::Instance().m_vecActiveThreadId.begin();
+ bool bFound = false;
+ while( it != CMICmnLLDBDebugSessionInfo::Instance().m_vecActiveThreadId.end() )
+ {
+ const MIuint nThreadId = *it;
+ if( nThreadId == i )
+ {
+ bFound = true;
+ break;
+ }
+
+ // Next
+ ++it;
+ }
+ if( !bFound )
+ {
+ CMICmnLLDBDebugSessionInfo::Instance().m_vecActiveThreadId.push_back( i );
+
+ // Form MI "=thread-created,id=\"%d\",group-id=\"i1\""
+ const CMIUtilString strValue( CMIUtilString::Format( "%d", thread.GetIndexID() ) );
+ const CMICmnMIValueConst miValueConst( strValue );
+ const CMICmnMIValueResult miValueResult( "id", miValueConst );
+ CMICmnMIOutOfBandRecord miOutOfBand( CMICmnMIOutOfBandRecord::eOutOfBand_ThreadCreated, miValueResult );
+ const CMICmnMIValueConst miValueConst2( "i1" );
+ const CMICmnMIValueResult miValueResult2( "group-id", miValueConst2 );
+ bOk = miOutOfBand.Add( miValueResult2 );
+ bOk = bOk && MiOutOfBandRecordToStdout( miOutOfBand );
+ if( !bOk )
+ return MIstatus::failure;
+ }
+ }
+
+ lldb::SBThread currentThread = rProcess.GetSelectedThread();
+ if( currentThread.IsValid() )
+ {
+ const MIuint threadId = currentThread.GetIndexID();
+ if( CMICmnLLDBDebugSessionInfo::Instance().m_currentSelectedThread != threadId )
+ {
+ CMICmnLLDBDebugSessionInfo::Instance().m_currentSelectedThread = threadId;
+
+ // Form MI "=thread-selected,id=\"%d\""
+ const CMIUtilString strValue( CMIUtilString::Format( "%d", currentThread.GetIndexID() ) );
+ const CMICmnMIValueConst miValueConst( strValue );
+ const CMICmnMIValueResult miValueResult( "id", miValueConst );
+ CMICmnMIOutOfBandRecord miOutOfBand( CMICmnMIOutOfBandRecord::eOutOfBand_ThreadSelected, miValueResult );
+ if( !MiOutOfBandRecordToStdout( miOutOfBand ) )
+ return MIstatus::failure;
+ }
+ }
+
+ // Check for invalid (removed) threads
+ CMICmnLLDBDebugSessionInfo::VecActiveThreadId_t::const_iterator it = CMICmnLLDBDebugSessionInfo::Instance().m_vecActiveThreadId.begin();
+ while( it != CMICmnLLDBDebugSessionInfo::Instance().m_vecActiveThreadId.end() )
+ {
+ const MIuint nThreadId = *it;
+ lldb::SBThread thread = rProcess.GetThreadAtIndex( nThreadId );
+ if( !thread.IsValid() )
+ {
+ // Form MI "=thread-exited,id=\"%ld\",group-id=\"i1\""
+ const CMIUtilString strValue( CMIUtilString::Format( "%ld", thread.GetIndexID() ) );
+ const CMICmnMIValueConst miValueConst( strValue );
+ const CMICmnMIValueResult miValueResult( "id", miValueConst );
+ CMICmnMIOutOfBandRecord miOutOfBand( CMICmnMIOutOfBandRecord::eOutOfBand_ThreadExited, miValueResult );
+ const CMICmnMIValueConst miValueConst2( "i1" );
+ const CMICmnMIValueResult miValueResult2( "group-id", miValueConst2 );
+ bOk = miOutOfBand.Add( miValueResult2 );
+ bOk = bOk && MiOutOfBandRecordToStdout( miOutOfBand );
+ if( !bOk )
+ return MIstatus::failure;
+ }
+
+ // Next
+ ++it;
+ }
+
+ return TextToStdout( "(gdb)" );
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Take a fully formed MI result record and send to the stdout stream.
+// Also output to the MI Log file.
+// Type: Method.
+// Args: vrMiResultRecord - (R) MI result record object.
+// Return: MIstatus::success - Functionality succeeded.
+// MIstatus::failure - Functionality failed.
+// Throws: None.
+//--
+bool CMICmnLLDBDebuggerHandleEvents::MiResultRecordToStdout( const CMICmnMIResultRecord & vrMiResultRecord )
+{
+ return TextToStdout( vrMiResultRecord.GetString() );
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Take a fully formed MI Out-of-band record and send to the stdout stream.
+// Also output to the MI Log file.
+// Type: Method.
+// Args: vrMiOutOfBandRecord - (R) MI Out-of-band record object.
+// Return: MIstatus::success - Functionality succeeded.
+// MIstatus::failure - Functionality failed.
+// Throws: None.
+//--
+bool CMICmnLLDBDebuggerHandleEvents::MiOutOfBandRecordToStdout( const CMICmnMIOutOfBandRecord & vrMiOutOfBandRecord )
+{
+ return TextToStdout( vrMiOutOfBandRecord.GetString() );
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Take a text data and send to the stdout stream. Also output to the MI Log
+// file.
+// Type: Method.
+// Args: vrTxt - (R) Text.
+// Return: MIstatus::success - Functionality succeeded.
+// MIstatus::failure - Functionality failed.
+// Throws: None.
+//--
+bool CMICmnLLDBDebuggerHandleEvents::TextToStdout( const CMIUtilString & vrTxt )
+{
+ return CMICmnStreamStdout::TextToStdout( vrTxt );
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Take a text data and send to the stderr stream. Also output to the MI Log
+// file.
+// Type: Method.
+// Args: vrTxt - (R) Text.
+// Return: MIstatus::success - Functionality succeeded.
+// MIstatus::failure - Functionality failed.
+// Throws: None.
+//--
+bool CMICmnLLDBDebuggerHandleEvents::TextToStderr( const CMIUtilString & vrTxt )
+{
+ return CMICmnStreamStderr::TextToStderr( vrTxt );
+}