forked from OSchip/llvm-project
1436 lines
52 KiB
C++
1436 lines
52 KiB
C++
|
//===-- 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/SBBreakpointLocation.h>
|
||
|
#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"
|
||
|
|
||
|
//++ ------------------------------------------------------------------------------------
|
||
|
// 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;
|
||
|
|
||
|
lldb::SBBreakpointLocation loc = brkPt.GetLocationAtIndex( 0 );
|
||
|
lldb::SBAddress addr = loc.GetAddress();
|
||
|
lldb::SBSymbolContext symbolContext = addr.GetSymbolContext( lldb::eSymbolContextEverything );
|
||
|
const char * pUnkwn = "??";
|
||
|
const char * pModule = pUnkwn;
|
||
|
const char * pFile = pUnkwn;
|
||
|
const char * pFunction = pUnkwn;
|
||
|
const char * pFilePath = pUnkwn;
|
||
|
//const char * pBrkName = brkPt.pUnkwn;
|
||
|
size_t nLine = 0;
|
||
|
lldb::SBTarget & rTarget = CMICmnLLDBDebugSessionInfo::Instance().m_lldbTarget;
|
||
|
size_t nAddr = addr.GetLoadAddress( rTarget );
|
||
|
lldb::SBModule module = symbolContext.GetModule();
|
||
|
if( module.IsValid() )
|
||
|
pModule = module.GetFileSpec().GetFilename();
|
||
|
lldb::SBCompileUnit compileUnit = symbolContext.GetCompileUnit();
|
||
|
if( compileUnit.IsValid() )
|
||
|
{
|
||
|
lldb::SBFileSpec fileSpec = compileUnit.GetFileSpec();
|
||
|
pFile = fileSpec.GetFilename();
|
||
|
pFilePath = fileSpec.GetDirectory();
|
||
|
lldb::SBFunction fn = symbolContext.GetFunction();
|
||
|
if( fn.IsValid() )
|
||
|
pFunction = fn.GetName();
|
||
|
const MIuint nLn = symbolContext.GetLineEntry().GetLine();
|
||
|
if( nLn > 0 )
|
||
|
nLine = nLn;
|
||
|
}
|
||
|
|
||
|
// 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( !CMICmnLLDBDebugSessionInfo::Instance().MIResponseFormBrkPtInfo( brkPt.GetID(), // "number="
|
||
|
"breakpoint", // "type="
|
||
|
false, // "disp="
|
||
|
brkPt.IsEnabled(), // "enabled="
|
||
|
nAddr, // "addr="
|
||
|
pFunction, // "func="
|
||
|
pFile, // "file="
|
||
|
pFilePath, // "fullname="
|
||
|
nLine, // "line="
|
||
|
false, //
|
||
|
"", // "thread-groups="
|
||
|
brkPt.GetHitCount(), // "times="
|
||
|
"unknown", // "original-location="
|
||
|
miValueTuple ))
|
||
|
{
|
||
|
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;
|
||
|
const lldb::ReturnStatus status = rDebugger.GetCommandInterpreter().HandleCommand( "process status", result, false );
|
||
|
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 11:
|
||
|
{
|
||
|
// 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:
|
||
|
{
|
||
|
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 ) )
|
||
|
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 )
|
||
|
{
|
||
|
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( brkPt );
|
||
|
}
|
||
|
|
||
|
//++ ------------------------------------------------------------------------------------
|
||
|
// Details: .
|
||
|
// Type: Method.
|
||
|
// Args: None.
|
||
|
// Return: MIstatus::success - Functionality succeeded.
|
||
|
// MIstatus::failure - Functionality failed.
|
||
|
// Throws: None.
|
||
|
//--
|
||
|
bool CMICmnLLDBDebuggerHandleEvents::MiStoppedAtBreakPoint( 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", vBrkPt.GetID() ) );
|
||
|
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 ) )
|
||
|
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", vBrkPt.GetID() + 1 ) );
|
||
|
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 ) )
|
||
|
return MIstatus::failure;
|
||
|
|
||
|
// 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 )
|
||
|
{
|
||
|
const bool bLock = CMICmnStreamStdout::Instance().Lock();
|
||
|
const bool bOk = bLock && CMICmnStreamStdout::Instance().WriteMIResponse( vrTxt );
|
||
|
bLock && CMICmnStreamStdout::Instance().Unlock();
|
||
|
|
||
|
return bOk;
|
||
|
}
|
||
|
|
||
|
//++ ------------------------------------------------------------------------------------
|
||
|
// 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::Instance().Write( vrTxt );
|
||
|
}
|