1 //===-- MICmnLLDBDebuggerHandleEvents.cpp --------------------------------------------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
11 // File: MICmnLLDBDebuggerHandleEvents.cpp
13 // Overview: CMICmnLLDBDebuggerHandleEvents implementation.
15 // Environment: Compilers: Visual C++ 12.
16 // gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1
17 // Libraries: See MIReadmetxt.
22 // Third party headers:
23 #include <lldb/API/SBEvent.h>
24 #include <lldb/API/SBProcess.h>
25 #include <lldb/API/SBBreakpoint.h>
26 #include <lldb/API/SBStream.h>
27 #include <lldb/API/SBThread.h>
28 #include <lldb/API/SBCommandInterpreter.h>
29 #include <lldb/API/SBCommandReturnObject.h>
31 #include <io.h> // For the ::_access()
33 #include <unistd.h> // For the ::access()
38 #include "MICmnLLDBDebuggerHandleEvents.h"
39 #include "MICmnResources.h"
41 #include "MICmnLLDBDebugSessionInfo.h"
42 #include "MICmnMIResultRecord.h"
43 #include "MICmnMIValueConst.h"
44 #include "MICmnMIValueList.h"
45 #include "MICmnMIOutOfBandRecord.h"
46 #include "MICmnStreamStdout.h"
47 #include "MICmnStreamStderr.h"
48 #include "MIUtilDebug.h"
51 //++ ------------------------------------------------------------------------------------
52 // Details: CMICmnLLDBDebuggerHandleEvents constructor.
58 CMICmnLLDBDebuggerHandleEvents::CMICmnLLDBDebuggerHandleEvents( void )
62 //++ ------------------------------------------------------------------------------------
63 // Details: CMICmnLLDBDebuggerHandleEvents destructor.
69 CMICmnLLDBDebuggerHandleEvents::~CMICmnLLDBDebuggerHandleEvents( void )
74 //++ ------------------------------------------------------------------------------------
75 // Details: Initialize resources for *this broardcaster object.
78 // Return: MIstatus::success - Functionality succeeded.
79 // MIstatus::failure - Functionality failed.
82 bool CMICmnLLDBDebuggerHandleEvents::Initialize( void )
84 m_clientUsageRefCnt++;
87 return MIstatus::success;
89 m_bInitialized = MIstatus::success;
91 return m_bInitialized;
94 //++ ------------------------------------------------------------------------------------
95 // Details: Release resources for *this broardcaster object.
98 // Return: MIstatus::success - Functionality succeeded.
99 // MIstatus::failure - Functionality failed.
102 bool CMICmnLLDBDebuggerHandleEvents::Shutdown( void )
104 if( --m_clientUsageRefCnt > 0 )
105 return MIstatus::success;
107 if( !m_bInitialized )
108 return MIstatus::success;
110 m_bInitialized = false;
112 return MIstatus::success;
115 //++ ------------------------------------------------------------------------------------
116 // Details: Interpret the event object to asscertain the action to take or information to
117 // to form and put in a MI Out-of-band record object which is given to stdout.
119 // Args: vEvent - (R) An LLDB broadcast event.
120 // vrbHandledEvent - (W) True - event handled, false = not handled.
121 // vrbExitAppEvent - (W) True - Received LLDB exit app event, false = did not.
122 // Return: MIstatus::success - Functionality succeeded.
123 // MIstatus::failure - Functionality failed.
126 bool CMICmnLLDBDebuggerHandleEvents::HandleEvent( const lldb::SBEvent & vEvent, bool & vrbHandledEvent, bool & vrbExitAppEvent )
128 bool bOk = MIstatus::success;
129 vrbHandledEvent = false;
130 vrbExitAppEvent = false;
132 if( lldb::SBProcess::EventIsProcessEvent( vEvent ) )
134 vrbHandledEvent = true;
135 bOk = HandleEventSBProcess( vEvent, vrbExitAppEvent );
137 else if( lldb::SBBreakpoint::EventIsBreakpointEvent( vEvent ) )
139 vrbHandledEvent = true;
140 bOk = HandleEventSBBreakPoint( vEvent );
142 else if( lldb::SBThread::EventIsThreadEvent( vEvent ) )
144 vrbHandledEvent = true;
145 bOk = HandleEventSBThread( vEvent );
151 //++ ------------------------------------------------------------------------------------
152 // Details: Handle a LLDB SBProcess event.
154 // Args: vEvent - (R) An LLDB broadcast event.
155 // vrbExitAppEvent - (W) True - Received LLDB exit app event, false = did not.
156 // Return: MIstatus::success - Functionality succeeded.
157 // MIstatus::failure - Functionality failed.
160 bool CMICmnLLDBDebuggerHandleEvents::HandleEventSBProcess( const lldb::SBEvent & vEvent, bool & vrbExitAppEvent )
162 bool bOk = MIstatus::success;
164 const MIchar * pEventType = "";
165 const MIuint nEventType = vEvent.GetType();
168 case lldb::SBProcess::eBroadcastBitInterrupt:
169 pEventType = "eBroadcastBitInterrupt";
171 case lldb::SBProcess::eBroadcastBitProfileData:
172 pEventType = "eBroadcastBitProfileData";
174 case lldb::SBProcess::eBroadcastBitStateChanged:
175 pEventType = "eBroadcastBitStateChanged";
176 bOk = HandleProcessEventBroadcastBitStateChanged( vEvent, vrbExitAppEvent );
178 case lldb::SBProcess::eBroadcastBitSTDERR:
179 pEventType = "eBroadcastBitSTDERR";
180 bOk = GetProcessStderr();
182 case lldb::SBProcess::eBroadcastBitSTDOUT:
183 pEventType = "eBroadcastBitSTDOUT";
184 bOk = GetProcessStdout();
188 const CMIUtilString msg( CMIUtilString::Format( MIRSRC( IDS_LLDBOUTOFBAND_ERR_UNKNOWN_EVENT ), "SBProcess", (MIuint) nEventType ) );
189 SetErrorDescription( msg );
190 return MIstatus::failure;
193 m_pLog->WriteLog( CMIUtilString::Format( "##### An SB Process event occurred: %s", pEventType ) );
198 //++ ------------------------------------------------------------------------------------
199 // Details: Handle a LLDB SBBreakpoint event.
201 // Args: vEvent - (R) An LLDB broadcast event.
202 // Return: MIstatus::success - Functionality succeeded.
203 // MIstatus::failure - Functionality failed.
206 bool CMICmnLLDBDebuggerHandleEvents::HandleEventSBBreakPoint( const lldb::SBEvent & vEvent )
208 bool bOk = MIstatus::success;
210 const MIchar * pEventType ="";
211 const lldb::BreakpointEventType eEvent = lldb::SBBreakpoint::GetBreakpointEventTypeFromEvent( vEvent );
214 case lldb::eBreakpointEventTypeThreadChanged:
215 pEventType = "eBreakpointEventTypeThreadChanged";
217 case lldb::eBreakpointEventTypeLocationsRemoved:
218 pEventType = "eBreakpointEventTypeLocationsRemoved";
220 case lldb::eBreakpointEventTypeInvalidType:
221 pEventType = "eBreakpointEventTypeInvalidType";
223 case lldb::eBreakpointEventTypeLocationsAdded:
224 pEventType = "eBreakpointEventTypeLocationsAdded";
225 bOk = HandleEventSBBreakpointLocationsAdded( vEvent );
227 case lldb::eBreakpointEventTypeAdded:
228 pEventType = "eBreakpointEventTypeAdded";
229 bOk = HandleEventSBBreakpointAdded( vEvent );
231 case lldb::eBreakpointEventTypeRemoved:
232 pEventType = "eBreakpointEventTypeRemoved";
233 bOk = HandleEventSBBreakpointCmn( vEvent );
235 case lldb::eBreakpointEventTypeLocationsResolved:
236 pEventType = "eBreakpointEventTypeLocationsResolved";
238 case lldb::eBreakpointEventTypeEnabled:
239 pEventType ="eBreakpointEventTypeEnabled";
240 bOk = HandleEventSBBreakpointCmn( vEvent );
242 case lldb::eBreakpointEventTypeDisabled:
243 pEventType = "eBreakpointEventTypeDisabled";
244 bOk = HandleEventSBBreakpointCmn( vEvent );
246 case lldb::eBreakpointEventTypeCommandChanged:
247 pEventType = "eBreakpointEventTypeCommandChanged";
248 bOk = HandleEventSBBreakpointCmn( vEvent );
250 case lldb::eBreakpointEventTypeConditionChanged:
251 pEventType ="eBreakpointEventTypeConditionChanged";
252 bOk = HandleEventSBBreakpointCmn( vEvent );
254 case lldb::eBreakpointEventTypeIgnoreChanged:
255 pEventType = "eBreakpointEventTypeIgnoreChanged";
256 bOk = HandleEventSBBreakpointCmn( vEvent );
260 const CMIUtilString msg( CMIUtilString::Format( MIRSRC( IDS_LLDBOUTOFBAND_ERR_UNKNOWN_EVENT ), "SBBreakPoint", (MIuint) eEvent ) );
261 SetErrorDescription( msg );
262 return MIstatus::failure;
265 m_pLog->WriteLog( CMIUtilString::Format( "##### An SB Breakpoint event occurred: %s", pEventType ) );
270 //++ ------------------------------------------------------------------------------------
271 // Details: Handle a LLDB SBBreakpoint event.
273 // Args: vEvent - (R) An LLDB broadcast event.
274 // Return: MIstatus::success - Functionality succeeded.
275 // MIstatus::failure - Functionality failed.
278 bool CMICmnLLDBDebuggerHandleEvents::HandleEventSBBreakpointLocationsAdded( const lldb::SBEvent & vEvent )
280 const MIuint nLoc = lldb::SBBreakpoint::GetNumBreakpointLocationsFromEvent( vEvent );
282 return MIstatus::success;
284 lldb::SBBreakpoint brkPt = lldb::SBBreakpoint::GetBreakpointFromEvent( vEvent );
285 const CMIUtilString plural( (nLoc == 1) ? "" : "s" );
286 const CMIUtilString msg( CMIUtilString::Format( "%d location%s added to breakpoint %d", nLoc, plural.c_str(), brkPt.GetID() ) );
288 return TextToStdout( msg );
291 //++ ------------------------------------------------------------------------------------
292 // Details: Handle a LLDB SBBreakpoint event.
294 // Args: vEvent - (R) An LLDB broadcast event.
295 // Return: MIstatus::success - Functionality succeeded.
296 // MIstatus::failure - Functionality failed.
299 bool CMICmnLLDBDebuggerHandleEvents::HandleEventSBBreakpointCmn( const lldb::SBEvent & vEvent )
301 lldb::SBBreakpoint brkPt = lldb::SBBreakpoint::GetBreakpointFromEvent( vEvent );
302 if( !brkPt.IsValid() )
303 return MIstatus::success;
305 CMICmnLLDBDebugSessionInfo & rSessionInfo( CMICmnLLDBDebugSessionInfo::Instance() );
306 CMICmnLLDBDebugSessionInfo::SBrkPtInfo sBrkPtInfo;
307 if( !rSessionInfo.GetBrkPtInfo( brkPt, sBrkPtInfo ) )
309 SetErrorDescription( CMIUtilString::Format( MIRSRC( IDS_LLDBOUTOFBAND_ERR_BRKPT_INFO_GET ), "HandleEventSBBreakpointCmn()", brkPt.GetID() ) );
310 return MIstatus::failure;
313 // CODETAG_LLDB_BREAKPOINT_CREATION
314 // This is in a worker thread
315 // Add more breakpoint information or overwrite existing information
316 CMICmnLLDBDebugSessionInfo::SBrkPtInfo sBrkPtInfoRec;
317 if( !rSessionInfo.RecordBrkPtInfoGet( brkPt.GetID(), sBrkPtInfoRec ) )
319 SetErrorDescription( CMIUtilString::Format( MIRSRC( IDS_LLDBOUTOFBAND_ERR_BRKPT_NOTFOUND ), "HandleEventSBBreakpointCmn()", brkPt.GetID() ) );
320 return MIstatus::failure;
322 sBrkPtInfo.m_bDisp = sBrkPtInfoRec.m_bDisp;
323 sBrkPtInfo.m_bEnabled = brkPt.IsEnabled();
324 sBrkPtInfo.m_bHaveArgOptionThreadGrp = false;
325 sBrkPtInfo.m_strOptThrdGrp = "";
326 sBrkPtInfo.m_nTimes = brkPt.GetHitCount();
327 sBrkPtInfo.m_strOrigLoc = sBrkPtInfoRec.m_strOrigLoc;
328 sBrkPtInfo.m_nIgnore = sBrkPtInfoRec.m_nIgnore;
329 sBrkPtInfo.m_bPending = sBrkPtInfoRec.m_bPending;
330 sBrkPtInfo.m_bCondition = sBrkPtInfoRec.m_bCondition;
331 sBrkPtInfo.m_strCondition = sBrkPtInfoRec.m_strCondition;
332 sBrkPtInfo.m_bBrkPtThreadId = sBrkPtInfoRec.m_bBrkPtThreadId;
333 sBrkPtInfo.m_nBrkPtThreadId = sBrkPtInfoRec.m_nBrkPtThreadId;
335 // 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\"}"
336 CMICmnMIValueTuple miValueTuple;
337 if( !rSessionInfo.MIResponseFormBrkPtInfo( sBrkPtInfo, miValueTuple ) )
339 SetErrorDescription( CMIUtilString::Format( MIRSRC( IDS_LLDBOUTOFBAND_ERR_FORM_MI_RESPONSE ), "HandleEventSBBreakpointCmn()" ) );
340 return MIstatus::failure;
343 const CMICmnMIValueResult miValueResultC( "bkpt", miValueTuple );
344 const CMICmnMIOutOfBandRecord miOutOfBandRecord( CMICmnMIOutOfBandRecord::eOutOfBand_BreakPointModified, miValueResultC );
345 const bool bOk = MiOutOfBandRecordToStdout( miOutOfBandRecord );
350 //++ ------------------------------------------------------------------------------------
351 // Details: Handle a LLDB SBBreakpoint added event.
352 // Add more breakpoint information or overwrite existing information.
353 // Normally a break point session info objects exists by now when an MI command
354 // was issued to insert a break so the retrieval would normally always succeed
355 // however should a user type "b main" into a console then LLDB will create a
356 // breakpoint directly, hence no MI command, hence no previous record of the
357 // breakpoint so RecordBrkPtInfoGet() will fail. We still get the event though
358 // so need to create a breakpoint info object here and send appropriate MI
361 // Args: vEvent - (R) An LLDB broadcast event.
362 // Return: MIstatus::success - Functionality succeeded.
363 // MIstatus::failure - Functionality failed.
366 bool CMICmnLLDBDebuggerHandleEvents::HandleEventSBBreakpointAdded( const lldb::SBEvent & vEvent )
368 lldb::SBBreakpoint brkPt = lldb::SBBreakpoint::GetBreakpointFromEvent( vEvent );
369 if( !brkPt.IsValid() )
370 return MIstatus::success;
372 CMICmnLLDBDebugSessionInfo & rSessionInfo( CMICmnLLDBDebugSessionInfo::Instance() );
373 CMICmnLLDBDebugSessionInfo::SBrkPtInfo sBrkPtInfo;
374 if( !rSessionInfo.GetBrkPtInfo( brkPt, sBrkPtInfo ) )
376 SetErrorDescription( CMIUtilString::Format( MIRSRC( IDS_LLDBOUTOFBAND_ERR_BRKPT_INFO_GET ), "HandleEventSBBreakpointAdded()", brkPt.GetID() ) );
377 return MIstatus::failure;
380 // CODETAG_LLDB_BREAKPOINT_CREATION
381 // This is in a worker thread
382 CMICmnLLDBDebugSessionInfo::SBrkPtInfo sBrkPtInfoRec;
383 const bool bBrkPtExistAlready = rSessionInfo.RecordBrkPtInfoGet( brkPt.GetID(), sBrkPtInfoRec );
384 if( bBrkPtExistAlready )
386 // Update breakpoint information object
387 sBrkPtInfo.m_bDisp = sBrkPtInfoRec.m_bDisp;
388 sBrkPtInfo.m_bEnabled = brkPt.IsEnabled();
389 sBrkPtInfo.m_bHaveArgOptionThreadGrp = false;
390 sBrkPtInfo.m_strOptThrdGrp.clear();
391 sBrkPtInfo.m_nTimes = brkPt.GetHitCount();
392 sBrkPtInfo.m_strOrigLoc = sBrkPtInfoRec.m_strOrigLoc;
393 sBrkPtInfo.m_nIgnore = sBrkPtInfoRec.m_nIgnore;
394 sBrkPtInfo.m_bPending = sBrkPtInfoRec.m_bPending;
395 sBrkPtInfo.m_bCondition = sBrkPtInfoRec.m_bCondition;
396 sBrkPtInfo.m_strCondition = sBrkPtInfoRec.m_strCondition;
397 sBrkPtInfo.m_bBrkPtThreadId = sBrkPtInfoRec.m_bBrkPtThreadId;
398 sBrkPtInfo.m_nBrkPtThreadId = sBrkPtInfoRec.m_nBrkPtThreadId;
402 // Create a breakpoint information object
403 sBrkPtInfo.m_bDisp = brkPt.IsOneShot();
404 sBrkPtInfo.m_bEnabled = brkPt.IsEnabled();
405 sBrkPtInfo.m_bHaveArgOptionThreadGrp = false;
406 sBrkPtInfo.m_strOptThrdGrp.clear();
407 sBrkPtInfo.m_strOrigLoc = CMIUtilString::Format( "%s:%d", sBrkPtInfo.m_fileName.c_str(), sBrkPtInfo.m_nLine );
408 sBrkPtInfo.m_nIgnore = brkPt.GetIgnoreCount();
409 sBrkPtInfo.m_bPending = false;
410 const MIchar * pStrCondition = brkPt.GetCondition();
411 sBrkPtInfo.m_bCondition = (pStrCondition != nullptr) ? true : false;
412 sBrkPtInfo.m_strCondition = (pStrCondition != nullptr) ? pStrCondition : "??";
413 sBrkPtInfo.m_bBrkPtThreadId = (brkPt.GetThreadID() != 0) ? true : false;
414 sBrkPtInfo.m_nBrkPtThreadId = brkPt.GetThreadID();
417 CMICmnMIValueTuple miValueTuple;
418 if( !rSessionInfo.MIResponseFormBrkPtInfo( sBrkPtInfo, miValueTuple ) )
420 SetErrorDescription( CMIUtilString::Format( MIRSRC( IDS_LLDBOUTOFBAND_ERR_FORM_MI_RESPONSE ), "HandleEventSBBreakpointAdded()" ) );
421 return MIstatus::failure;
424 bool bOk = MIstatus::success;
425 if( bBrkPtExistAlready )
427 // 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\"}"
428 const CMICmnMIValueResult miValueResult( "bkpt", miValueTuple );
429 const CMICmnMIOutOfBandRecord miOutOfBandRecord( CMICmnMIOutOfBandRecord::eOutOfBand_BreakPointModified, miValueResult );
430 bOk = MiOutOfBandRecordToStdout( miOutOfBandRecord );
434 // CODETAG_LLDB_BRKPT_ID_MAX
435 if( brkPt.GetID() > (lldb::break_id_t) rSessionInfo.m_nBrkPointCntMax )
437 SetErrorDescription( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_BRKPT_CNT_EXCEEDED ), "HandleEventSBBreakpointAdded()", rSessionInfo.m_nBrkPointCntMax, sBrkPtInfo.m_id ) );
438 return MIstatus::failure;
440 if( !rSessionInfo.RecordBrkPtInfo( brkPt.GetID(), sBrkPtInfo ) )
442 SetErrorDescription( CMIUtilString::Format( MIRSRC( IDS_LLDBOUTOFBAND_ERR_BRKPT_INFO_SET ), "HandleEventSBBreakpointAdded()", sBrkPtInfo.m_id ) );
443 return MIstatus::failure;
446 // MI print "=breakpoint-created,bkpt={number=\"%d\",type=\"breakpoint\",disp=\"%s\",enabled=\"%c\",addr=\"0x%08x\",func=\"%s\",file=\"%s\",fullname=\"%s/%s\",line=\"%d\",times=\"%d\",original-location=\"%s\"}"
447 const CMICmnMIValueResult miValueResult( "bkpt", miValueTuple );
448 const CMICmnMIOutOfBandRecord miOutOfBandRecord( CMICmnMIOutOfBandRecord::eOutOfBand_BreakPointCreated, miValueResult );
449 bOk = MiOutOfBandRecordToStdout( miOutOfBandRecord );
455 //++ ------------------------------------------------------------------------------------
456 // Details: Handle a LLDB SBThread event.
458 // Args: vEvent - (R) An LLDB broadcast event.
459 // Return: MIstatus::success - Functionality succeeded.
460 // MIstatus::failure - Functionality failed.
463 bool CMICmnLLDBDebuggerHandleEvents::HandleEventSBThread( const lldb::SBEvent & vEvent )
465 if( !ChkForStateChanges() )
466 return MIstatus::failure;
468 bool bOk = MIstatus::success;
469 const MIchar * pEventType = "";
470 const MIuint nEventType = vEvent.GetType();
473 case lldb::SBThread::eBroadcastBitStackChanged:
474 pEventType = "eBroadcastBitStackChanged";
475 bOk = HandleEventSBThreadBitStackChanged( vEvent );
477 case lldb::SBThread::eBroadcastBitThreadSuspended:
478 pEventType = "eBroadcastBitThreadSuspended";
479 bOk = HandleEventSBThreadSuspended( vEvent );
481 case lldb::SBThread::eBroadcastBitThreadResumed:
482 pEventType = "eBroadcastBitThreadResumed";
484 case lldb::SBThread::eBroadcastBitSelectedFrameChanged:
485 pEventType = "eBroadcastBitSelectedFrameChanged";
487 case lldb::SBThread::eBroadcastBitThreadSelected:
488 pEventType = "eBroadcastBitThreadSelected";
492 const CMIUtilString msg( CMIUtilString::Format( MIRSRC( IDS_LLDBOUTOFBAND_ERR_UNKNOWN_EVENT ), "SBThread", (MIuint) nEventType ) );
493 SetErrorDescription( msg );
494 return MIstatus::failure;
497 m_pLog->WriteLog( CMIUtilString::Format( "##### An SBThread event occurred: %s", pEventType ) );
502 //++ ------------------------------------------------------------------------------------
503 // Details: Handle a LLDB SBThread event.
505 // Args: vEvent - (R) An LLDB broadcast event.
506 // Return: MIstatus::success - Functionality succeeded.
507 // MIstatus::failure - Functionality failed.
510 bool CMICmnLLDBDebuggerHandleEvents::HandleEventSBThreadSuspended( const lldb::SBEvent & vEvent )
512 lldb::SBThread thread = lldb::SBThread::GetThreadFromEvent( vEvent );
513 if( !thread.IsValid() )
514 return MIstatus::success;
516 const lldb::StopReason eStopReason = thread.GetStopReason();
517 if( eStopReason != lldb::eStopReasonSignal )
518 return MIstatus::success;
520 // MI print "@thread=%d,signal=%lld"
521 const MIuint64 nId = thread.GetStopReasonDataAtIndex( 0 );
522 const CMIUtilString strThread( CMIUtilString::Format( "%d", thread.GetThreadID() ) );
523 const CMICmnMIValueConst miValueConst( strThread );
524 const CMICmnMIValueResult miValueResult( "thread", miValueConst );
525 CMICmnMIOutOfBandRecord miOutOfBandRecord( CMICmnMIOutOfBandRecord::eOutOfBand_Thread, miValueResult );
526 const CMIUtilString strSignal( CMIUtilString::Format( "%lld", nId ) );
527 const CMICmnMIValueConst miValueConst2( strSignal );
528 const CMICmnMIValueResult miValueResult2( "signal", miValueConst2 );
529 bool bOk = miOutOfBandRecord.Add( miValueResult2 );
530 bOk = bOk && MiOutOfBandRecordToStdout( miOutOfBandRecord );
535 //++ ------------------------------------------------------------------------------------
536 // Details: Handle a LLDB SBThread event.
538 // Args: vEvent - (R) An LLDB broadcast event.
539 // Return: MIstatus::success - Functionality succeeded.
540 // MIstatus::failure - Functionality failed.
543 bool CMICmnLLDBDebuggerHandleEvents::HandleEventSBThreadBitStackChanged( const lldb::SBEvent & vEvent )
545 lldb::SBThread thread = lldb::SBThread::GetThreadFromEvent( vEvent );
546 if( !thread.IsValid() )
547 return MIstatus::success;
549 lldb::SBStream streamOut;
550 const bool bOk = thread.GetStatus( streamOut );
551 return bOk && TextToStdout( streamOut.GetData() );
554 //++ ------------------------------------------------------------------------------------
555 // Details: Handle a LLDB SBCommandInterpreter event.
557 // Args: vEvent - (R) An LLDB command interpreter event.
558 // Return: MIstatus::success - Functionality succeeded.
559 // MIstatus::failure - Functionality failed.
562 bool CMICmnLLDBDebuggerHandleEvents::HandleEventSBCommandInterpreter( const lldb::SBEvent & vEvent )
564 // This function is not used
565 // *** This function is under development
567 const MIchar * pEventType = "";
568 const MIuint nEventType = vEvent.GetType();
571 case lldb::SBCommandInterpreter::eBroadcastBitThreadShouldExit:
572 pEventType ="eBroadcastBitThreadShouldExit";
573 // ToDo: IOR: Reminder to maybe handle this here
574 //const MIuint nEventType = event.GetType();
575 //if( nEventType & lldb::SBCommandInterpreter::eBroadcastBitThreadShouldExit )
577 // m_pClientDriver->SetExitApplicationFlag();
578 // vrbYesExit = true;
579 // return MIstatus::success;
581 case lldb::SBCommandInterpreter::eBroadcastBitResetPrompt:
582 pEventType = "eBroadcastBitResetPrompt";
584 case lldb::SBCommandInterpreter::eBroadcastBitQuitCommandReceived:
585 pEventType = "eBroadcastBitQuitCommandReceived";
587 case lldb::SBCommandInterpreter::eBroadcastBitAsynchronousOutputData:
588 pEventType = "eBroadcastBitAsynchronousOutputData";
590 case lldb::SBCommandInterpreter::eBroadcastBitAsynchronousErrorData:
591 pEventType = "eBroadcastBitAsynchronousErrorData";
595 const CMIUtilString msg( CMIUtilString::Format( MIRSRC( IDS_LLDBOUTOFBAND_ERR_UNKNOWN_EVENT ), "SBCommandInterpreter", (MIuint) nEventType ) );
596 SetErrorDescription( msg );
597 return MIstatus::failure;
600 m_pLog->WriteLog( CMIUtilString::Format( "##### An SBCommandInterpreter event occurred: %s", pEventType ) );
602 return MIstatus::success;
605 //++ ------------------------------------------------------------------------------------
606 // Details: Handle SBProcess event eBroadcastBitStateChanged.
608 // Args: vEvent - (R) An LLDB event object.
609 // vrbExitAppEvent - (W) True - Received LLDB exit app event, false = did not.
610 // Return: MIstatus::success - Functionality succeeded.
611 // MIstatus::failure - Functionality failed.
614 bool CMICmnLLDBDebuggerHandleEvents::HandleProcessEventBroadcastBitStateChanged( const lldb::SBEvent & vEvent, bool & vrbExitAppEvent )
616 bool bOk = ChkForStateChanges();
617 bOk = bOk && GetProcessStdout();
618 bOk = bOk && GetProcessStderr();
620 return MIstatus::failure;
622 // Something changed in the process; get the event and report the process's current
623 // status and location
624 const lldb::StateType eEventState = lldb::SBProcess::GetStateFromEvent( vEvent );
625 if( eEventState == lldb::eStateInvalid )
626 return MIstatus::success;
628 lldb::SBProcess process = lldb::SBProcess::GetProcessFromEvent( vEvent );
629 if( !process.IsValid() )
631 const CMIUtilString msg( CMIUtilString::Format( MIRSRC( IDS_LLDBOUTOFBAND_ERR_PROCESS_INVALID ), "SBProcess", "HandleProcessEventBroadcastBitStateChanged()" ) );
632 SetErrorDescription( msg );
633 return MIstatus::failure;
636 bool bShouldBrk = true;
637 const MIchar * pEventType = "";
638 switch( eEventState )
640 case lldb::eStateUnloaded:
641 pEventType = "eStateUnloaded";
643 case lldb::eStateConnected:
644 pEventType = "eStateConnected";
646 case lldb::eStateAttaching:
647 pEventType = "eStateAttaching";
649 case lldb::eStateLaunching:
650 pEventType ="eStateLaunching";
652 case lldb::eStateStopped:
653 pEventType = "eStateStopped";
654 bOk = HandleProcessEventStateStopped( bShouldBrk );
657 case lldb::eStateCrashed:
658 case lldb::eStateSuspended:
659 pEventType = "eStateSuspended";
660 bOk = HandleProcessEventStateSuspended( vEvent );
662 case lldb::eStateRunning:
663 pEventType = "eStateRunning";
664 bOk = HandleProcessEventStateRunning();
666 case lldb::eStateStepping:
667 pEventType = "eStateStepping";
669 case lldb::eStateDetached:
670 pEventType = "eStateDetached";
672 case lldb::eStateExited:
673 pEventType = "eStateExited";
674 vrbExitAppEvent = true;
675 bOk = HandleProcessEventStateExited();
679 const CMIUtilString msg( CMIUtilString::Format( MIRSRC( IDS_LLDBOUTOFBAND_ERR_UNKNOWN_EVENT ), "SBProcess BroadcastBitStateChanged", (MIuint) eEventState ) );
680 SetErrorDescription( msg );
681 return MIstatus::failure;
685 // ToDo: Remove when finished coding application
686 m_pLog->WriteLog( CMIUtilString::Format( "##### An SB Process event BroadcastBitStateChanged occurred: %s", pEventType ) );
691 //++ ------------------------------------------------------------------------------------
692 // Details: Asynchronous event handler for LLDB Process state suspended.
694 // Args: vEvent - (R) An LLDB event object.
695 // Return: MIstatus::success - Functionality succeeded.
696 // MIstatus::failure - Functionality failed.
699 bool CMICmnLLDBDebuggerHandleEvents::HandleProcessEventStateSuspended( const lldb::SBEvent & vEvent )
701 // Make sure the program hasn't been auto-restarted:
702 if( lldb::SBProcess::GetRestartedFromEvent( vEvent ) )
703 return MIstatus::success;
705 bool bOk = MIstatus::success;
706 lldb::SBDebugger & rDebugger = CMICmnLLDBDebugSessionInfo::Instance().m_rLldbDebugger;
707 lldb::SBProcess & rProcess = CMICmnLLDBDebugSessionInfo::Instance().m_lldbProcess;
708 lldb::SBTarget target = rProcess.GetTarget();
709 if( rDebugger.GetSelectedTarget() == target )
711 if( !UpdateSelectedThread() )
712 return MIstatus::failure;
714 lldb::SBCommandReturnObject result;
715 const lldb::ReturnStatus status = rDebugger.GetCommandInterpreter().HandleCommand( "process status", result, false ); MIunused( status );
716 bOk = TextToStderr( result.GetError() );
717 bOk = bOk && TextToStdout( result.GetOutput() );
721 lldb::SBStream streamOut;
722 const MIuint nTargetIndex = rDebugger.GetIndexOfTarget( target );
723 if( nTargetIndex != UINT_MAX )
724 streamOut.Printf( "Target %d: (", nTargetIndex );
726 streamOut.Printf( "Target <unknown index>: (" );
727 target.GetDescription( streamOut, lldb::eDescriptionLevelBrief );
728 streamOut.Printf( ") stopped.\n" );
729 bOk = TextToStdout( streamOut.GetData() );
735 //++ ------------------------------------------------------------------------------------
736 // Details: Print to stdout MI formatted text to indicate process stopped.
738 // Args: vwrbShouldBrk - (W) True = Yes break, false = do not.
739 // Return: MIstatus::success - Functionality succeeded.
740 // MIstatus::failure - Functionality failed.
743 bool CMICmnLLDBDebuggerHandleEvents::HandleProcessEventStateStopped( bool & vwrbShouldBrk )
745 if( !UpdateSelectedThread() )
746 return MIstatus::failure;
748 const MIchar * pEventType = "";
749 bool bOk = MIstatus::success;
750 lldb::SBProcess & rProcess = CMICmnLLDBDebugSessionInfo::Instance().m_lldbProcess;
751 const lldb::StopReason eStoppedReason = rProcess.GetSelectedThread().GetStopReason();
752 switch( eStoppedReason )
754 case lldb::eStopReasonInvalid:
755 pEventType = "eStopReasonInvalid";
756 vwrbShouldBrk = false;
758 case lldb::eStopReasonNone:
759 pEventType = "eStopReasonNone";
761 case lldb::eStopReasonTrace:
762 pEventType = "eStopReasonTrace";
763 bOk = HandleProcessEventStopReasonTrace();
765 case lldb::eStopReasonBreakpoint:
766 pEventType = "eStopReasonBreakpoint";
767 bOk = HandleProcessEventStopReasonBreakpoint();
769 case lldb::eStopReasonWatchpoint:
770 pEventType = "eStopReasonWatchpoint";
772 case lldb::eStopReasonSignal:
773 pEventType = "eStopReasonSignal";
774 bOk = HandleProcessEventStopSignal( vwrbShouldBrk );
776 case lldb::eStopReasonException:
777 pEventType ="eStopReasonException";
779 case lldb::eStopReasonExec:
780 pEventType = "eStopReasonExec";
782 case lldb::eStopReasonPlanComplete:
783 pEventType = "eStopReasonPlanComplete";
784 bOk = HandleProcessEventStopReasonTrace();
786 case lldb::eStopReasonThreadExiting:
787 pEventType = "eStopReasonThreadExiting";
791 vwrbShouldBrk = false;
793 // MI print "*stopped,reason=\"%d\",stopped-threads=\"all\",from-thread=\"%u\""
794 const CMIUtilString strReason( CMIUtilString::Format( "%d", eStoppedReason ) );
795 const CMICmnMIValueConst miValueConst( strReason );
796 const CMICmnMIValueResult miValueResult( "reason", miValueConst );
797 CMICmnMIOutOfBandRecord miOutOfBandRecord( CMICmnMIOutOfBandRecord::eOutOfBand_Stopped, miValueResult );
798 const CMICmnMIValueConst miValueConst2( "all" );
799 const CMICmnMIValueResult miValueResult2( "stopped-threads", miValueConst2 );
800 bOk = miOutOfBandRecord.Add( miValueResult2 );
801 const CMIUtilString strFromThread( CMIUtilString::Format( "%u", rProcess.GetSelectedThread().GetIndexID() ) );
802 const CMICmnMIValueConst miValueConst3( strFromThread );
803 const CMICmnMIValueResult miValueResult3( "from-thread", miValueConst3 );
804 bOk = bOk && miOutOfBandRecord.Add( miValueResult3 );
805 bOk = bOk && MiOutOfBandRecordToStdout( miOutOfBandRecord );
806 bOk = bOk && TextToStdout( "(gdb)" );
810 // ToDo: Remove when finished coding application
811 m_pLog->WriteLog( CMIUtilString::Format( "##### An SB Process event stop state occurred: %s", pEventType ) );
816 //++ ------------------------------------------------------------------------------------
817 // Details: Asynchronous event handler for LLDB Process stop signal.
819 // Args: vwrbShouldBrk - (W) True = Yes break, false = do not.
820 // Return: MIstatus::success - Functionality succeeded.
821 // MIstatus::failure - Functionality failed.
824 bool CMICmnLLDBDebuggerHandleEvents::HandleProcessEventStopSignal( bool & vwrbShouldBrk )
826 bool bOk = MIstatus::success;
828 lldb::SBProcess & rProcess = CMICmnLLDBDebugSessionInfo::Instance().m_lldbProcess;
829 const MIuint64 nStopReason = rProcess.GetSelectedThread().GetStopReasonDataAtIndex( 0 );
830 switch( nStopReason )
832 case 2: // Terminal interrupt signal. SIGINT
834 // MI print "*stopped,reason=\"signal-received\",signal-name=\"SIGNINT\",signal-meaning=\"Interrupt\",frame={%s}"
835 const CMICmnMIValueConst miValueConst( "signal-received" );
836 const CMICmnMIValueResult miValueResult( "reason", miValueConst );
837 CMICmnMIOutOfBandRecord miOutOfBandRecord( CMICmnMIOutOfBandRecord::eOutOfBand_Stopped, miValueResult );
838 const CMICmnMIValueConst miValueConst2( "SIGINT" );
839 const CMICmnMIValueResult miValueResult2( "signal-name", miValueConst2 );
840 bOk = miOutOfBandRecord.Add( miValueResult2 );
841 const CMICmnMIValueConst miValueConst3( "Interrupt" );
842 const CMICmnMIValueResult miValueResult3( "signal-meaning", miValueConst3 );
843 bOk = bOk && miOutOfBandRecord.Add( miValueResult3 );
844 CMICmnMIValueTuple miValueTuple;
845 bOk = bOk && MiHelpGetCurrentThreadFrame( miValueTuple );
846 const CMICmnMIValueResult miValueResult5( "frame", miValueTuple );
847 bOk = bOk && miOutOfBandRecord.Add( miValueResult5 );
848 bOk = bOk && MiOutOfBandRecordToStdout( miOutOfBandRecord );
849 bOk = bOk && TextToStdout( "(gdb)" );
852 case 11: // Invalid memory reference. SIGSEGV
854 // MI print "*stopped,reason=\"signal-received\",signal-name=\"SIGSEGV\",signal-meaning=\"Segmentation fault\",thread-id=\"%d\",frame={%s}"
855 const CMICmnMIValueConst miValueConst( "signal-received" );
856 const CMICmnMIValueResult miValueResult( "reason", miValueConst );
857 CMICmnMIOutOfBandRecord miOutOfBandRecord( CMICmnMIOutOfBandRecord::eOutOfBand_Stopped, miValueResult );
858 const CMICmnMIValueConst miValueConst2( "SIGSEGV" );
859 const CMICmnMIValueResult miValueResult2( "signal-name", miValueConst2 );
860 bOk = miOutOfBandRecord.Add( miValueResult2 );
861 const CMICmnMIValueConst miValueConst3( "Segmentation fault" );
862 const CMICmnMIValueResult miValueResult3( "signal-meaning", miValueConst3 );
863 bOk = bOk && miOutOfBandRecord.Add( miValueResult3 );
864 const CMIUtilString strThreadId( CMIUtilString::Format( "%d", rProcess.GetSelectedThread().GetIndexID() ) );
865 const CMICmnMIValueConst miValueConst4( strThreadId );
866 const CMICmnMIValueResult miValueResult4( "thread-id", miValueConst4 );
867 bOk = bOk && miOutOfBandRecord.Add( miValueResult4 );
868 CMICmnMIValueTuple miValueTuple;
869 bOk = bOk && MiHelpGetCurrentThreadFrame( miValueTuple );
870 const CMICmnMIValueResult miValueResult5( "frame", miValueTuple );
871 bOk = bOk && miOutOfBandRecord.Add( miValueResult5 );
872 bOk = bOk && MiOutOfBandRecordToStdout( miOutOfBandRecord );
873 // Note no "(gdb)" output here
877 if( rProcess.IsValid() )
880 case 5: // Trace/breakpoint trap. SIGTRAP
882 lldb::SBThread thread = rProcess.GetSelectedThread();
883 const MIuint nFrames = thread.GetNumFrames();
886 lldb::SBFrame frame = thread.GetFrameAtIndex( 0 );
887 const char * pFnName = frame.GetFunctionName();
888 if( pFnName != nullptr )
890 const CMIUtilString fnName = CMIUtilString( pFnName );
891 static const CMIUtilString threadCloneFn = CMIUtilString( "__pthread_clone" );
893 if( CMIUtilString::Compare( threadCloneFn, fnName ) )
895 if( rProcess.IsValid() )
898 vwrbShouldBrk = true;
907 // MI print "*stopped,reason=\"signal-received\",signal=\"%lld\",stopped-threads=\"all\""
908 const CMICmnMIValueConst miValueConst( "signal-received" );
909 const CMICmnMIValueResult miValueResult( "reason", miValueConst );
910 CMICmnMIOutOfBandRecord miOutOfBandRecord( CMICmnMIOutOfBandRecord::eOutOfBand_Stopped, miValueResult );
911 const CMIUtilString strReason( CMIUtilString::Format( "%lld", nStopReason ) );
912 const CMICmnMIValueConst miValueConst2( strReason );
913 const CMICmnMIValueResult miValueResult2( "signal", miValueConst2 );
914 bOk = miOutOfBandRecord.Add( miValueResult2 );
915 const CMICmnMIValueConst miValueConst3( "all" );
916 const CMICmnMIValueResult miValueResult3( "stopped-threads", miValueConst3 );
917 bOk = bOk && miOutOfBandRecord.Add( miValueResult3 );
918 bOk = bOk && MiOutOfBandRecordToStdout( miOutOfBandRecord );
919 bOk = bOk && TextToStdout( "(gdb)" );
921 } // switch( nStopReason )
926 //++ ------------------------------------------------------------------------------------
927 // Details: Form partial MI response in a MI value tuple object.
929 // Args: vwrMiValueTuple - (W) MI value tuple object.
930 // Return: MIstatus::success - Functionality succeeded.
931 // MIstatus::failure - Functionality failed.
934 bool CMICmnLLDBDebuggerHandleEvents::MiHelpGetCurrentThreadFrame( CMICmnMIValueTuple & vwrMiValueTuple )
936 CMIUtilString strThreadFrame;
937 lldb::SBProcess & rProcess = CMICmnLLDBDebugSessionInfo::Instance().m_lldbProcess;
938 lldb::SBThread thread = rProcess.GetSelectedThread();
939 const MIuint nFrame = thread.GetNumFrames();
942 // MI print "addr=\"??\",func=\"??\",file=\"??\",fullname=\"??\",line=\"??\""
943 const CMICmnMIValueConst miValueConst( "??" );
944 const CMICmnMIValueResult miValueResult( "addr", miValueConst );
945 CMICmnMIValueTuple miValueTuple( miValueResult );
946 const CMICmnMIValueResult miValueResult2( "func", miValueConst );
947 miValueTuple.Add( miValueResult2 );
948 const CMICmnMIValueResult miValueResult4( "file", miValueConst );
949 miValueTuple.Add( miValueResult4 );
950 const CMICmnMIValueResult miValueResult5( "fullname", miValueConst );
951 miValueTuple.Add( miValueResult5 );
952 const CMICmnMIValueResult miValueResult6( "line", miValueConst );
953 miValueTuple.Add( miValueResult6 );
955 vwrMiValueTuple = miValueTuple;
957 return MIstatus::success;
960 CMICmnMIValueTuple miValueTuple;
961 if( !CMICmnLLDBDebugSessionInfo::Instance().MIResponseFormFrameInfo( thread, 0, miValueTuple ) )
963 SetErrorDescription( CMIUtilString::Format( MIRSRC( IDS_LLDBOUTOFBAND_ERR_FORM_MI_RESPONSE ), "MiHelpGetCurrentThreadFrame()" ) );
964 return MIstatus::failure;
967 vwrMiValueTuple = miValueTuple;
969 return MIstatus::success;
972 //++ ------------------------------------------------------------------------------------
973 // Details: Asynchronous event handler for LLDB Process stop reason breakpoint.
976 // Return: MIstatus::success - Functionality succeeded.
977 // MIstatus::failure - Functionality failed.
980 bool CMICmnLLDBDebuggerHandleEvents::HandleProcessEventStopReasonBreakpoint( void )
982 // CODETAG_DEBUG_SESSION_RUNNING_PROG_RECEIVED_SIGINT_PAUSE_PROGRAM
983 if( !CMIDriver::Instance().SetDriverStateRunningNotDebugging() )
985 const CMIUtilString & rErrMsg( CMIDriver::Instance().GetErrorDescription() );
986 SetErrorDescription( CMIUtilString::Format( MIRSRC( IDS_LLDBOUTOFBAND_ERR_SETNEWDRIVERSTATE ), "HandleProcessEventStopReasonBreakpoint()", rErrMsg.c_str() ) );
987 return MIstatus::failure;
990 lldb::SBProcess & rProcess = CMICmnLLDBDebugSessionInfo::Instance().m_lldbProcess;
991 const MIuint64 brkPtId = rProcess.GetSelectedThread().GetStopReasonDataAtIndex( 0 );
992 lldb::SBBreakpoint brkPt = CMICmnLLDBDebugSessionInfo::Instance().m_lldbTarget.GetBreakpointAtIndex( (MIuint) brkPtId );
994 return MiStoppedAtBreakPoint( brkPtId, brkPt );
997 //++ ------------------------------------------------------------------------------------
998 // Details: Form the MI Out-of-band response for stopped reason on hitting a break point.
1000 // Args: vBrkPtId - (R) The LLDB break point's ID
1001 // vBrkPt - (R) THe LLDB break point object.
1002 // Return: MIstatus::success - Functionality succeeded.
1003 // MIstatus::failure - Functionality failed.
1006 bool CMICmnLLDBDebuggerHandleEvents::MiStoppedAtBreakPoint( const MIuint64 vBrkPtId, const lldb::SBBreakpoint & vBrkPt )
1008 bool bOk = MIstatus::success;
1010 lldb::SBProcess & rProcess = CMICmnLLDBDebugSessionInfo::Instance().m_lldbProcess;
1011 lldb::SBThread thread = rProcess.GetSelectedThread();
1012 const MIuint nFrame = thread.GetNumFrames();
1015 // MI print "*stopped,reason=\"breakpoint-hit\",disp=\"del\",bkptno=\"%d\",frame={},thread-id=\"%d\",stopped-threads=\"all\""
1016 const CMICmnMIValueConst miValueConst( "breakpoint-hit" );
1017 const CMICmnMIValueResult miValueResult( "reason", miValueConst );
1018 CMICmnMIOutOfBandRecord miOutOfBandRecord( CMICmnMIOutOfBandRecord::eOutOfBand_Stopped, miValueResult );
1019 const CMICmnMIValueConst miValueConst2( "del" );
1020 const CMICmnMIValueResult miValueResult2( "disp", miValueConst2 );
1021 bOk = miOutOfBandRecord.Add( miValueResult2 );
1022 const CMIUtilString strBkp( CMIUtilString::Format( "%d", vBrkPtId ) );
1023 const CMICmnMIValueConst miValueConst3( strBkp );
1024 CMICmnMIValueResult miValueResult3( "bkptno", miValueConst3 );
1025 bOk = bOk && miOutOfBandRecord.Add( miValueResult3 );
1026 const CMICmnMIValueConst miValueConst4( "{}" );
1027 const CMICmnMIValueResult miValueResult4( "frame", miValueConst4 );
1028 bOk = bOk && miOutOfBandRecord.Add( miValueResult4 );
1029 const CMIUtilString strThreadId( CMIUtilString::Format( "%d", vBrkPt.GetThreadIndex() ) );
1030 const CMICmnMIValueConst miValueConst5( strThreadId );
1031 const CMICmnMIValueResult miValueResult5( "thread-id", miValueConst5 );
1032 bOk = bOk && miOutOfBandRecord.Add( miValueResult5 );
1033 const CMICmnMIValueConst miValueConst6( "all" );
1034 const CMICmnMIValueResult miValueResult6( "stopped-threads", miValueConst6 );
1035 bOk = bOk && miOutOfBandRecord.Add( miValueResult6 );
1036 bOk = bOk && MiOutOfBandRecordToStdout( miOutOfBandRecord );
1037 bOk = bOk && TextToStdout( "(gdb)" );
1041 CMICmnLLDBDebugSessionInfo & rSession = CMICmnLLDBDebugSessionInfo::Instance();
1043 lldb::SBFrame frame = thread.GetFrameAtIndex( 0 );
1044 lldb::addr_t pc = 0;
1045 CMIUtilString fnName;
1046 CMIUtilString fileName;
1049 if( !rSession.GetFrameInfo( frame, pc, fnName, fileName, path, nLine ) )
1051 SetErrorDescription( CMIUtilString::Format( MIRSRC( IDS_LLDBOUTOFBAND_ERR_FRAME_INFO_GET ), "MiStoppedAtBreakPoint()" ) );
1052 return MIstatus::failure;
1055 // 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\""
1056 const CMICmnMIValueConst miValueConst( "breakpoint-hit" );
1057 const CMICmnMIValueResult miValueResult( "reason", miValueConst );
1058 CMICmnMIOutOfBandRecord miOutOfBandRecord( CMICmnMIOutOfBandRecord::eOutOfBand_Stopped, miValueResult );
1059 const CMICmnMIValueConst miValueConstA( "del" );
1060 const CMICmnMIValueResult miValueResultA( "disp", miValueConstA );
1061 bOk = miOutOfBandRecord.Add( miValueResultA );
1062 const CMIUtilString strBkp( CMIUtilString::Format( "%d", vBrkPtId ) );
1063 const CMICmnMIValueConst miValueConstB( strBkp );
1064 CMICmnMIValueResult miValueResultB( "bkptno", miValueConstB );
1065 bOk = bOk && miOutOfBandRecord.Add( miValueResultB );
1067 // frame={addr=\"0x%08x\",func=\"%s\",args=[],file=\"%s\",fullname=\"%s\",line=\"%d\"}
1070 CMICmnMIValueList miValueList( true );
1071 const MIuint maskVarTypes = 0x1000;
1072 bOk = rSession.MIResponseFormVariableInfo2( frame, maskVarTypes, miValueList );
1074 CMICmnMIValueTuple miValueTuple;
1075 bOk = bOk && rSession.MIResponseFormFrameInfo2( pc, miValueList.GetString(), fnName, fileName, path, nLine, miValueTuple );
1076 const CMICmnMIValueResult miValueResult8( "frame", miValueTuple );
1077 bOk = bOk && miOutOfBandRecord.Add( miValueResult8 );
1080 // Add to MI thread-id=\"%d\",stopped-threads=\"all\"
1083 const CMIUtilString strThreadId( CMIUtilString::Format( "%d", thread.GetIndexID() ) );
1084 const CMICmnMIValueConst miValueConst8( strThreadId );
1085 const CMICmnMIValueResult miValueResult8( "thread-id", miValueConst8 );
1086 bOk = miOutOfBandRecord.Add( miValueResult8 );
1090 const CMICmnMIValueConst miValueConst9( "all" );
1091 const CMICmnMIValueResult miValueResult9( "stopped-threads", miValueConst9 );
1092 bOk = miOutOfBandRecord.Add( miValueResult9 );
1093 bOk = MiOutOfBandRecordToStdout( miOutOfBandRecord );
1094 bOk = bOk && TextToStdout( "(gdb)" );
1097 return MIstatus::success;
1100 //++ ------------------------------------------------------------------------------------
1101 // Details: Asynchronous event handler for LLDB Process stop reason trace.
1104 // Return: MIstatus::success - Functionality succeeded.
1105 // MIstatus::failure - Functionality failed.
1108 bool CMICmnLLDBDebuggerHandleEvents::HandleProcessEventStopReasonTrace( void )
1111 lldb::SBProcess & rProcess = CMICmnLLDBDebugSessionInfo::Instance().m_lldbProcess;
1112 lldb::SBThread thread = rProcess.GetSelectedThread();
1113 const MIuint nFrame = thread.GetNumFrames();
1116 // MI print "*stopped,reason=\"trace\",stopped-threads=\"all\""
1117 const CMICmnMIValueConst miValueConst( "trace" );
1118 const CMICmnMIValueResult miValueResult( "reason", miValueConst );
1119 CMICmnMIOutOfBandRecord miOutOfBandRecord( CMICmnMIOutOfBandRecord::eOutOfBand_Stopped, miValueResult );
1120 const CMICmnMIValueConst miValueConst2( "all" );
1121 const CMICmnMIValueResult miValueResult2( "stopped-threads", miValueConst2 );
1122 bOk = miOutOfBandRecord.Add( miValueResult2 );
1123 bOk = MiOutOfBandRecordToStdout( miOutOfBandRecord );
1124 bOk = bOk && TextToStdout( "(gdb)" );
1128 CMICmnLLDBDebugSessionInfo & rSession = CMICmnLLDBDebugSessionInfo::Instance();
1130 // MI print "*stopped,reason=\"end-stepping-range\",frame={addr=\"0x%08x\",func=\"%s\",args=[\"%s\"],file=\"%s\",fullname=\"%s\",line=\"%d\"},thread-id=\"%d\",stopped-threads=\"all\""
1131 lldb::SBFrame frame = thread.GetFrameAtIndex( 0 );
1132 lldb::addr_t pc = 0;
1133 CMIUtilString fnName;
1134 CMIUtilString fileName;
1137 if( !rSession.GetFrameInfo( frame, pc, fnName, fileName, path, nLine ) )
1139 SetErrorDescription( CMIUtilString::Format( MIRSRC( IDS_LLDBOUTOFBAND_ERR_FRAME_INFO_GET ), "HandleProcessEventStopReasonTrace()" ) );
1140 return MIstatus::failure;
1144 CMICmnMIValueList miValueList( true );
1145 const MIuint maskVarTypes = 0x1000;
1146 if( !rSession.MIResponseFormVariableInfo2( frame, maskVarTypes, miValueList ) )
1147 return MIstatus::failure;
1148 CMICmnMIValueTuple miValueTuple;
1149 if( !rSession.MIResponseFormFrameInfo2( pc, miValueList.GetString(), fnName, fileName, path, nLine, miValueTuple ) )
1150 return MIstatus::failure;
1152 const CMICmnMIValueConst miValueConst( "end-stepping-range" );
1153 const CMICmnMIValueResult miValueResult( "reason", miValueConst );
1154 CMICmnMIOutOfBandRecord miOutOfBandRecord( CMICmnMIOutOfBandRecord::eOutOfBand_Stopped, miValueResult );
1155 const CMICmnMIValueResult miValueResult2( "frame", miValueTuple );
1156 bOk = miOutOfBandRecord.Add( miValueResult2 );
1158 // Add to MI thread-id=\"%d\",stopped-threads=\"all\"
1161 const CMIUtilString strThreadId( CMIUtilString::Format( "%d", thread.GetIndexID() ) );
1162 const CMICmnMIValueConst miValueConst8( strThreadId );
1163 const CMICmnMIValueResult miValueResult8( "thread-id", miValueConst8 );
1164 bOk = miOutOfBandRecord.Add( miValueResult8 );
1168 const CMICmnMIValueConst miValueConst9( "all" );
1169 const CMICmnMIValueResult miValueResult9( "stopped-threads", miValueConst9 );
1170 bOk = miOutOfBandRecord.Add( miValueResult9 );
1171 bOk = MiOutOfBandRecordToStdout( miOutOfBandRecord );
1172 bOk = bOk && TextToStdout( "(gdb)" );
1178 //++ ------------------------------------------------------------------------------------
1179 // Details: Asynchronous function update selected thread.
1182 // Return: MIstatus::success - Functionality succeeded.
1183 // MIstatus::failure - Functionality failed.
1186 bool CMICmnLLDBDebuggerHandleEvents::UpdateSelectedThread( void )
1188 lldb::SBProcess process = CMICmnLLDBDebugSessionInfo::Instance().m_rLldbDebugger.GetSelectedTarget().GetProcess();
1189 if( !process.IsValid() )
1190 return MIstatus::success;
1192 lldb::SBThread currentThread = process.GetSelectedThread();
1193 lldb::SBThread thread;
1194 const lldb::StopReason eCurrentThreadStoppedReason = currentThread.GetStopReason();
1195 if( !currentThread.IsValid() || (eCurrentThreadStoppedReason == lldb::eStopReasonInvalid) || (eCurrentThreadStoppedReason == lldb::eStopReasonNone) )
1197 // Prefer a thread that has just completed its plan over another thread as current thread
1198 lldb::SBThread planThread;
1199 lldb::SBThread otherThread;
1200 const size_t nThread = process.GetNumThreads();
1201 for( MIuint i = 0; i < nThread; i++ )
1203 // GetThreadAtIndex() uses a base 0 index
1204 // GetThreadByIndexID() uses a base 1 index
1205 thread = process.GetThreadAtIndex( i );
1206 const lldb::StopReason eThreadStopReason = thread.GetStopReason();
1207 switch( eThreadStopReason )
1209 case lldb::eStopReasonTrace:
1210 case lldb::eStopReasonBreakpoint:
1211 case lldb::eStopReasonWatchpoint:
1212 case lldb::eStopReasonSignal:
1213 case lldb::eStopReasonException:
1214 if( !otherThread.IsValid() )
1215 otherThread = thread;
1217 case lldb::eStopReasonPlanComplete:
1218 if( !planThread.IsValid() )
1219 planThread = thread;
1221 case lldb::eStopReasonInvalid:
1222 case lldb::eStopReasonNone:
1227 if( planThread.IsValid() )
1228 process.SetSelectedThread( planThread );
1229 else if( otherThread.IsValid() )
1230 process.SetSelectedThread( otherThread );
1233 if( currentThread.IsValid() )
1234 thread = currentThread;
1236 thread = process.GetThreadAtIndex( 0 );
1238 if( thread.IsValid() )
1239 process.SetSelectedThread( thread );
1241 } // if( !currentThread.IsValid() || (eCurrentThreadStoppedReason == lldb::eStopReasonInvalid) || (eCurrentThreadStoppedReason == lldb::eStopReasonNone) )
1243 return MIstatus::success;
1246 //++ ------------------------------------------------------------------------------------
1247 // Details: Print to stdout "*running,thread-id=\"all\"", "(gdb)".
1250 // Return: MIstatus::success - Functionality succeeded.
1251 // MIstatus::failure - Functionality failed.
1254 bool CMICmnLLDBDebuggerHandleEvents::HandleProcessEventStateRunning( void )
1256 CMICmnMIValueConst miValueConst( "all" );
1257 CMICmnMIValueResult miValueResult( "thread-id", miValueConst );
1258 CMICmnMIOutOfBandRecord miOutOfBandRecord( CMICmnMIOutOfBandRecord::eOutOfBand_Running, miValueResult );
1259 bool bOk = MiOutOfBandRecordToStdout( miOutOfBandRecord );
1260 bOk = bOk && TextToStdout( "(gdb)" );
1265 //++ ------------------------------------------------------------------------------------
1266 // Details: Print to stdout "=thread-exited,id=\"%ld\",group-id=\"i1\"",
1267 // "=thread-group-exited,id=\"i1\",exit-code=\"0\""),
1268 // "*stopped,reason=\"exited-normally\"",
1272 // Return: MIstatus::success - Functionality succeeded.
1273 // MIstatus::failure - Functionality failed.
1276 bool CMICmnLLDBDebuggerHandleEvents::HandleProcessEventStateExited( void )
1278 const CMIUtilString strId( CMIUtilString::Format( "%ld", 1 ) );
1279 CMICmnMIValueConst miValueConst( strId );
1280 CMICmnMIValueResult miValueResult( "id", miValueConst );
1281 CMICmnMIOutOfBandRecord miOutOfBandRecord( CMICmnMIOutOfBandRecord::eOutOfBand_ThreadExited, miValueResult );
1282 CMICmnMIValueConst miValueConst2( "i1" );
1283 CMICmnMIValueResult miValueResult2( "group-id", miValueConst2 );
1284 bool bOk = miOutOfBandRecord.Add( miValueResult2 );
1285 bOk = bOk && MiOutOfBandRecordToStdout( miOutOfBandRecord );
1288 CMICmnMIValueConst miValueConst3( "i1" );
1289 CMICmnMIValueResult miValueResult3( "id", miValueConst3 );
1290 CMICmnMIOutOfBandRecord miOutOfBandRecord2( CMICmnMIOutOfBandRecord::eOutOfBand_ThreadGroupExited, miValueResult3 );
1291 CMICmnMIValueConst miValueConst2( "0" );
1292 CMICmnMIValueResult miValueResult2( "exit-code", miValueConst2 );
1293 bOk = miOutOfBandRecord2.Add( miValueResult2 );
1294 bOk = bOk && MiOutOfBandRecordToStdout( miOutOfBandRecord2 );
1298 CMICmnMIValueConst miValueConst4( "exited-normally" );
1299 CMICmnMIValueResult miValueResult4( "reason", miValueConst4 );
1300 CMICmnMIOutOfBandRecord miOutOfBandRecord3( CMICmnMIOutOfBandRecord::eOutOfBand_Stopped, miValueResult4 );
1301 bOk = MiOutOfBandRecordToStdout( miOutOfBandRecord3 );
1303 bOk = bOk && TextToStdout( "(gdb)" );
1308 //++ ------------------------------------------------------------------------------------
1309 // Details: Drain all stdout so we don't see any output come after we print our prompts.
1310 // The process has stuff waiting for stdout; get it and write it out to the
1311 // appropriate place.
1314 // Return: MIstatus::success - Functionality succeeded.
1315 // MIstatus::failure - Functionality failed.
1318 bool CMICmnLLDBDebuggerHandleEvents::GetProcessStdout( void )
1320 bool bOk = MIstatus::success;
1325 lldb::SBProcess process = CMICmnLLDBDebugSessionInfo::Instance().m_rLldbDebugger.GetSelectedTarget().GetProcess();
1326 while( process.GetSTDOUT( &c, 1 ) > 0 )
1329 if( ConvertPrintfCtrlCodeToString( c, str ) )
1335 const CMIUtilString t( CMIUtilString::Format( "~\"%s\"", text.c_str() ) );
1336 bOk = TextToStdout( t );
1342 //++ ------------------------------------------------------------------------------------
1343 // Details: Drain all stderr so we don't see any output come after we print our prompts.
1344 // The process has stuff waiting for stderr; get it and write it out to the
1345 // appropriate place.
1348 // Return: MIstatus::success - Functionality succeeded.
1349 // MIstatus::failure - Functionality failed.
1352 bool CMICmnLLDBDebuggerHandleEvents::GetProcessStderr( void )
1354 bool bOk = MIstatus::success;
1359 lldb::SBProcess process = CMICmnLLDBDebugSessionInfo::Instance().m_rLldbDebugger.GetSelectedTarget().GetProcess();
1360 while( process.GetSTDERR( &c, 1 ) > 0 )
1363 if( ConvertPrintfCtrlCodeToString( c, str ) )
1369 const CMIUtilString t( CMIUtilString::Format( "~\"%s\"", text.c_str() ) );
1370 bOk = TextToStdout( t );
1376 //++ ------------------------------------------------------------------------------------
1377 // Details: Convert text stream control codes to text equivalent.
1379 // Args: vCtrl - (R) The control code.
1380 // vwrStrEquivalent - (W) The text equivalent.
1381 // Return: MIstatus::success - Functionality succeeded.
1382 // MIstatus::failure - Functionality failed.
1385 bool CMICmnLLDBDebuggerHandleEvents::ConvertPrintfCtrlCodeToString( const MIchar vCtrl, CMIUtilString & vwrStrEquivalent )
1389 case '\033': vwrStrEquivalent = "\\e"; break;
1390 case '\a': vwrStrEquivalent = "\\a"; break;
1391 case '\b': vwrStrEquivalent = "\\b"; break;
1392 case '\f': vwrStrEquivalent = "\\f"; break;
1393 case '\n': vwrStrEquivalent = "\\n"; break;
1394 case '\r': vwrStrEquivalent = "\\r"; break;
1395 case '\t': vwrStrEquivalent = "\\t"; break;
1396 case '\v': vwrStrEquivalent = "\\v"; break;
1398 vwrStrEquivalent = CMIUtilString::Format( "%c", vCtrl );
1402 return MIstatus::success;
1405 //++ ------------------------------------------------------------------------------------
1406 // Details: Asynchronous event function check for state changes.
1409 // Return: MIstatus::success - Functionality succeeded.
1410 // MIstatus::failure - Functionality failed.
1413 bool CMICmnLLDBDebuggerHandleEvents::ChkForStateChanges( void )
1415 lldb::SBProcess & rProcess = CMICmnLLDBDebugSessionInfo::Instance().m_lldbProcess;
1416 if( !rProcess.IsValid() )
1417 return MIstatus::success;
1418 lldb::SBTarget & rTarget = CMICmnLLDBDebugSessionInfo::Instance().m_lldbTarget;
1419 if( !rTarget.IsValid() )
1420 return MIstatus::success;
1422 bool bOk = MIstatus::success;
1424 // Check for created threads
1425 const MIuint nThread = rProcess.GetNumThreads();
1426 for( MIuint i = 0; i < nThread; i++ )
1428 // GetThreadAtIndex() uses a base 0 index
1429 // GetThreadByIndexID() uses a base 1 index
1430 lldb::SBThread thread = rProcess.GetThreadAtIndex( i );
1431 if( !thread.IsValid() )
1434 CMICmnLLDBDebugSessionInfo::VecActiveThreadId_t::const_iterator it = CMICmnLLDBDebugSessionInfo::Instance().m_vecActiveThreadId.begin();
1435 bool bFound = false;
1436 while( it != CMICmnLLDBDebugSessionInfo::Instance().m_vecActiveThreadId.end() )
1438 const MIuint nThreadId = *it;
1439 if( nThreadId == i )
1450 CMICmnLLDBDebugSessionInfo::Instance().m_vecActiveThreadId.push_back( i );
1452 // Form MI "=thread-created,id=\"%d\",group-id=\"i1\""
1453 const CMIUtilString strValue( CMIUtilString::Format( "%d", thread.GetIndexID() ) );
1454 const CMICmnMIValueConst miValueConst( strValue );
1455 const CMICmnMIValueResult miValueResult( "id", miValueConst );
1456 CMICmnMIOutOfBandRecord miOutOfBand( CMICmnMIOutOfBandRecord::eOutOfBand_ThreadCreated, miValueResult );
1457 const CMICmnMIValueConst miValueConst2( "i1" );
1458 const CMICmnMIValueResult miValueResult2( "group-id", miValueConst2 );
1459 bOk = miOutOfBand.Add( miValueResult2 );
1460 bOk = bOk && MiOutOfBandRecordToStdout( miOutOfBand );
1462 return MIstatus::failure;
1466 lldb::SBThread currentThread = rProcess.GetSelectedThread();
1467 if( currentThread.IsValid() )
1469 const MIuint threadId = currentThread.GetIndexID();
1470 if( CMICmnLLDBDebugSessionInfo::Instance().m_currentSelectedThread != threadId )
1472 CMICmnLLDBDebugSessionInfo::Instance().m_currentSelectedThread = threadId;
1474 // Form MI "=thread-selected,id=\"%d\""
1475 const CMIUtilString strValue( CMIUtilString::Format( "%d", currentThread.GetIndexID() ) );
1476 const CMICmnMIValueConst miValueConst( strValue );
1477 const CMICmnMIValueResult miValueResult( "id", miValueConst );
1478 CMICmnMIOutOfBandRecord miOutOfBand( CMICmnMIOutOfBandRecord::eOutOfBand_ThreadSelected, miValueResult );
1479 if( !MiOutOfBandRecordToStdout( miOutOfBand ) )
1480 return MIstatus::failure;
1484 // Check for invalid (removed) threads
1485 CMICmnLLDBDebugSessionInfo::VecActiveThreadId_t::const_iterator it = CMICmnLLDBDebugSessionInfo::Instance().m_vecActiveThreadId.begin();
1486 while( it != CMICmnLLDBDebugSessionInfo::Instance().m_vecActiveThreadId.end() )
1488 const MIuint nThreadId = *it;
1489 lldb::SBThread thread = rProcess.GetThreadAtIndex( nThreadId );
1490 if( !thread.IsValid() )
1492 // Form MI "=thread-exited,id=\"%ld\",group-id=\"i1\""
1493 const CMIUtilString strValue( CMIUtilString::Format( "%ld", thread.GetIndexID() ) );
1494 const CMICmnMIValueConst miValueConst( strValue );
1495 const CMICmnMIValueResult miValueResult( "id", miValueConst );
1496 CMICmnMIOutOfBandRecord miOutOfBand( CMICmnMIOutOfBandRecord::eOutOfBand_ThreadExited, miValueResult );
1497 const CMICmnMIValueConst miValueConst2( "i1" );
1498 const CMICmnMIValueResult miValueResult2( "group-id", miValueConst2 );
1499 bOk = miOutOfBand.Add( miValueResult2 );
1500 bOk = bOk && MiOutOfBandRecordToStdout( miOutOfBand );
1502 return MIstatus::failure;
1509 return TextToStdout( "(gdb)" );
1512 //++ ------------------------------------------------------------------------------------
1513 // Details: Take a fully formed MI result record and send to the stdout stream.
1514 // Also output to the MI Log file.
1516 // Args: vrMiResultRecord - (R) MI result record object.
1517 // Return: MIstatus::success - Functionality succeeded.
1518 // MIstatus::failure - Functionality failed.
1521 bool CMICmnLLDBDebuggerHandleEvents::MiResultRecordToStdout( const CMICmnMIResultRecord & vrMiResultRecord )
1523 return TextToStdout( vrMiResultRecord.GetString() );
1526 //++ ------------------------------------------------------------------------------------
1527 // Details: Take a fully formed MI Out-of-band record and send to the stdout stream.
1528 // Also output to the MI Log file.
1530 // Args: vrMiOutOfBandRecord - (R) MI Out-of-band record object.
1531 // Return: MIstatus::success - Functionality succeeded.
1532 // MIstatus::failure - Functionality failed.
1535 bool CMICmnLLDBDebuggerHandleEvents::MiOutOfBandRecordToStdout( const CMICmnMIOutOfBandRecord & vrMiOutOfBandRecord )
1537 return TextToStdout( vrMiOutOfBandRecord.GetString() );
1540 //++ ------------------------------------------------------------------------------------
1541 // Details: Take a text data and send to the stdout stream. Also output to the MI Log
1544 // Args: vrTxt - (R) Text.
1545 // Return: MIstatus::success - Functionality succeeded.
1546 // MIstatus::failure - Functionality failed.
1549 bool CMICmnLLDBDebuggerHandleEvents::TextToStdout( const CMIUtilString & vrTxt )
1551 return CMICmnStreamStdout::TextToStdout( vrTxt );
1554 //++ ------------------------------------------------------------------------------------
1555 // Details: Take a text data and send to the stderr stream. Also output to the MI Log
1558 // Args: vrTxt - (R) Text.
1559 // Return: MIstatus::success - Functionality succeeded.
1560 // MIstatus::failure - Functionality failed.
1563 bool CMICmnLLDBDebuggerHandleEvents::TextToStderr( const CMIUtilString & vrTxt )
1565 return CMICmnStreamStderr::TextToStderr( vrTxt );