2014-05-16 18:51:01 +08:00
//===-- 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"
2014-06-25 00:35:50 +08:00
# include "MIDriver.h"
2014-05-16 18:51:01 +08:00
//++ ------------------------------------------------------------------------------------
// 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 = HandleEventSBBreakpointCmn ( 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 ;
2014-06-25 00:35:50 +08:00
CMICmnLLDBDebugSessionInfo & rSessionInfo ( CMICmnLLDBDebugSessionInfo : : Instance ( ) ) ;
CMICmnLLDBDebugSessionInfo : : SBrkPtInfo sBrkPtInfo ;
if ( ! rSessionInfo . GetBrkPtInfo ( brkPt , sBrkPtInfo ) )
2014-05-16 18:51:01 +08:00
{
2014-06-25 00:35:50 +08:00
SetErrorDescription ( CMIUtilString : : Format ( MIRSRC ( IDS_LLDBOUTOFBAND_ERR_BRKPT_INFO_GET ) , " HandleEventSBBreakpointCmn() " , brkPt . GetID ( ) ) ) ;
return MIstatus : : failure ;
2014-05-16 18:51:01 +08:00
}
2014-06-25 00:35:50 +08:00
// 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 ;
2014-05-16 18:51:01 +08:00
// 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 ;
2014-06-25 00:35:50 +08:00
if ( ! rSessionInfo . MIResponseFormBrkPtInfo ( sBrkPtInfo , miValueTuple ) )
2014-05-16 18:51:01 +08:00
{
2014-06-25 00:35:50 +08:00
SetErrorDescription ( CMIUtilString : : Format ( MIRSRC ( IDS_LLDBOUTOFBAND_ERR_FORM_MI_RESPONSE ) , " HandleEventSBBreakpointCmn() " ) ) ;
2014-05-16 18:51:01 +08:00
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 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 ;
2014-06-25 00:35:50 +08:00
const lldb : : ReturnStatus status = rDebugger . GetCommandInterpreter ( ) . HandleCommand ( " process status " , result , false ) ; MIunused ( status ) ;
2014-05-16 18:51:01 +08:00
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 )
{
2014-06-25 00:35:50 +08:00
case 2 : // Terminal interrupt signal. SIGINT
2014-05-16 18:51:01 +08:00
{
2014-06-25 00:35:50 +08:00
// MI print "*stopped,reason=\"signal-received\",signal-name=\"SIGNINT\",signal-meaning=\"Interrupt\",frame={%s}"
2014-05-16 18:51:01 +08:00
const CMICmnMIValueConst miValueConst ( " signal-received " ) ;
const CMICmnMIValueResult miValueResult ( " reason " , miValueConst ) ;
CMICmnMIOutOfBandRecord miOutOfBandRecord ( CMICmnMIOutOfBandRecord : : eOutOfBand_Stopped , miValueResult ) ;
2014-06-25 00:35:50 +08:00
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 " ) ;
2014-05-16 18:51:01 +08:00
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 ;
2014-06-25 00:35:50 +08:00
case 5 : // Trace/breakpoint trap. SIGTRAP
2014-05-16 18:51:01 +08:00
{
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=\"??\",args=[],file=\"??\",fullname=\"??\",line=\"??\""
const CMICmnMIValueConst miValueConst ( " ?? " ) ;
const CMICmnMIValueResult miValueResult ( " addr " , miValueConst ) ;
CMICmnMIValueTuple miValueTuple ( miValueResult ) ;
const CMICmnMIValueResult miValueResult2 ( " func " , miValueConst ) ;
miValueTuple . Add ( miValueResult2 ) ;
const CMICmnMIValueConst miValueConst2 ( " [] " , true ) ;
const CMICmnMIValueResult miValueResult3 ( " args " , miValueConst2 ) ;
miValueTuple . Add ( miValueResult3 ) ;
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 ) )
2014-06-25 00:35:50 +08:00
{
SetErrorDescription ( CMIUtilString : : Format ( MIRSRC ( IDS_LLDBOUTOFBAND_ERR_FORM_MI_RESPONSE ) , " MiHelpGetCurrentThreadFrame() " ) ) ;
2014-05-16 18:51:01 +08:00
return MIstatus : : failure ;
2014-06-25 00:35:50 +08:00
}
2014-05-16 18:51:01 +08:00
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 )
{
2014-06-25 00:35:50 +08:00
// 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 ;
}
2014-05-16 18:51:01 +08:00
lldb : : SBProcess & rProcess = CMICmnLLDBDebugSessionInfo : : Instance ( ) . m_lldbProcess ;
const MIuint64 brkPtId = rProcess . GetSelectedThread ( ) . GetStopReasonDataAtIndex ( 0 ) ;
lldb : : SBBreakpoint brkPt = CMICmnLLDBDebugSessionInfo : : Instance ( ) . m_lldbTarget . GetBreakpointAtIndex ( ( MIuint ) brkPtId ) ;
2014-06-25 00:35:50 +08:00
return MiStoppedAtBreakPoint ( brkPtId , brkPt ) ;
2014-05-16 18:51:01 +08:00
}
//++ ------------------------------------------------------------------------------------
2014-06-25 00:35:50 +08:00
// Details: Form the MI Out-of-band response for stopped reason on hitting a break point.
2014-05-16 18:51:01 +08:00
// Type: Method.
2014-06-25 00:35:50 +08:00
// Args: vBrkPtId - (R) The LLDB break point's ID
// vBrkPt - (R) THe LLDB break point object.
2014-05-16 18:51:01 +08:00
// Return: MIstatus::success - Functionality succeeded.
// MIstatus::failure - Functionality failed.
// Throws: None.
//--
2014-06-25 00:35:50 +08:00
bool CMICmnLLDBDebuggerHandleEvents : : MiStoppedAtBreakPoint ( const MIuint64 vBrkPtId , const lldb : : SBBreakpoint & vBrkPt )
2014-05-16 18:51:01 +08:00
{
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 ) ;
2014-06-25 00:35:50 +08:00
const CMIUtilString strBkp ( CMIUtilString : : Format ( " %d " , vBrkPtId ) ) ;
2014-05-16 18:51:01 +08:00
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 ) )
2014-06-25 00:35:50 +08:00
{
SetErrorDescription ( CMIUtilString : : Format ( MIRSRC ( IDS_LLDBOUTOFBAND_ERR_FRAME_INFO_GET ) , " MiStoppedAtBreakPoint() " ) ) ;
2014-05-16 18:51:01 +08:00
return MIstatus : : failure ;
2014-06-25 00:35:50 +08:00
}
2014-05-16 18:51:01 +08:00
// 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 ) ;
2014-06-25 00:35:50 +08:00
const CMIUtilString strBkp ( CMIUtilString : : Format ( " %d " , vBrkPtId ) ) ;
2014-05-16 18:51:01 +08:00
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 vMaskVarTypes = 0x1000 ;
bOk = rSession . MIResponseFormVariableInfo ( frame , vMaskVarTypes , miValueList ) ;
CMICmnMIValueTuple miValueTuple ;
bOk = bOk & & rSession . MIResponseFormFrameInfo ( pc , fnName , miValueList . GetString ( ) , 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=[],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 ) )
2014-06-25 00:35:50 +08:00
{
SetErrorDescription ( CMIUtilString : : Format ( MIRSRC ( IDS_LLDBOUTOFBAND_ERR_FRAME_INFO_GET ) , " HandleProcessEventStopReasonTrace() " ) ) ;
2014-05-16 18:51:01 +08:00
return MIstatus : : failure ;
2014-06-25 00:35:50 +08:00
}
2014-05-16 18:51:01 +08:00
// frame={addr=\"0x%08x\",func=\"%s\",args=[],file=\"%s\",fullname=\"%s\",line=\"%d\"}
CMICmnMIValueTuple miValueTuple ;
if ( ! rSession . MIResponseFormFrameInfo ( pc , 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 ) ;
bOk = miOutOfBandRecord . Add ( miValueTuple ) ;
// 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 )
{
2014-06-25 00:35:50 +08:00
return CMICmnStreamStdout : : TextToStdout ( vrTxt ) ;
2014-05-16 18:51:01 +08:00
}
//++ ------------------------------------------------------------------------------------
// 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 )
{
2014-06-25 00:35:50 +08:00
return CMICmnStreamStderr : : TextToStderr ( vrTxt ) ;
2014-05-16 18:51:01 +08:00
}