]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/lldb/tools/lldb-mi/MICmnLLDBDebuggerHandleEvents.cpp
Merge ^/head r274961 through r276472.
[FreeBSD/FreeBSD.git] / contrib / llvm / tools / lldb / tools / lldb-mi / MICmnLLDBDebuggerHandleEvents.cpp
1 //===-- MICmnLLDBDebuggerHandleEvents.cpp --------------------------------------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9
10 //++
11 // File:                MICmnLLDBDebuggerHandleEvents.cpp
12 //
13 // Overview:    CMICmnLLDBDebuggerHandleEvents implementation.
14 //
15 // Environment: Compilers:      Visual C++ 12.
16 //                                                      gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1
17 //                              Libraries:      See MIReadmetxt. 
18 //
19 // Copyright:   None.
20 //--
21
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>
30 #ifdef _WIN32
31         #include <io.h>                 // For the ::_access()
32 #else
33         #include <unistd.h>             // For the ::access()
34 #endif // _WIN32
35 #include <limits.h>
36
37 // In-house headers:
38 #include "MICmnLLDBDebuggerHandleEvents.h"
39 #include "MICmnResources.h"
40 #include "MICmnLog.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"
49 #include "MIDriver.h"
50
51 //++ ------------------------------------------------------------------------------------
52 // Details:     CMICmnLLDBDebuggerHandleEvents constructor.
53 // Type:        Method.
54 // Args:        None.
55 // Return:      None.
56 // Throws:      None.
57 //--
58 CMICmnLLDBDebuggerHandleEvents::CMICmnLLDBDebuggerHandleEvents( void )
59 {
60 }
61
62 //++ ------------------------------------------------------------------------------------
63 // Details:     CMICmnLLDBDebuggerHandleEvents destructor.
64 // Type:        Overridable.
65 // Args:        None.
66 // Return:      None.
67 // Throws:      None.
68 //--
69 CMICmnLLDBDebuggerHandleEvents::~CMICmnLLDBDebuggerHandleEvents( void )
70 {
71         Shutdown();
72 }
73
74 //++ ------------------------------------------------------------------------------------
75 // Details:     Initialize resources for *this broardcaster object.
76 // Type:        Method.
77 // Args:        None.
78 // Return:      MIstatus::success - Functionality succeeded.
79 //                      MIstatus::failure - Functionality failed.
80 // Throws:      None.
81 //--
82 bool CMICmnLLDBDebuggerHandleEvents::Initialize( void )
83 {
84         m_clientUsageRefCnt++;
85
86         if( m_bInitialized )
87                 return MIstatus::success;
88
89         m_bInitialized = MIstatus::success;
90         
91         return m_bInitialized;
92 }
93
94 //++ ------------------------------------------------------------------------------------
95 // Details:     Release resources for *this broardcaster object.
96 // Type:        Method.
97 // Args:        None.
98 // Return:      MIstatus::success - Functionality succeeded.
99 //                      MIstatus::failure - Functionality failed.
100 // Throws:      None.
101 //--
102 bool CMICmnLLDBDebuggerHandleEvents::Shutdown( void )
103 {
104         if( --m_clientUsageRefCnt > 0 )
105                 return MIstatus::success;
106         
107         if( !m_bInitialized )
108                 return MIstatus::success;
109
110         m_bInitialized = false;
111
112         return MIstatus::success;
113 }       
114
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.
118 // Type:        Method.
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.
124 // Throws:      None.
125 //--
126 bool CMICmnLLDBDebuggerHandleEvents::HandleEvent( const lldb::SBEvent & vEvent, bool & vrbHandledEvent, bool & vrbExitAppEvent )
127 {
128         bool bOk = MIstatus::success;
129         vrbHandledEvent = false;
130         vrbExitAppEvent = false;
131         
132         if( lldb::SBProcess::EventIsProcessEvent( vEvent ) )
133         {
134                 vrbHandledEvent = true;
135                 bOk = HandleEventSBProcess( vEvent, vrbExitAppEvent );
136         }
137         else if( lldb::SBBreakpoint::EventIsBreakpointEvent( vEvent ) )
138         {
139                 vrbHandledEvent = true;
140                 bOk = HandleEventSBBreakPoint( vEvent );
141         }
142         else if( lldb::SBThread::EventIsThreadEvent( vEvent ) )
143         {
144                 vrbHandledEvent = true;
145                 bOk = HandleEventSBThread( vEvent );
146         }
147         
148         return bOk;
149 }
150
151 //++ ------------------------------------------------------------------------------------
152 // Details:     Handle a LLDB SBProcess event.
153 // Type:        Method.
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.
158 // Throws:      None.
159 //--
160 bool CMICmnLLDBDebuggerHandleEvents::HandleEventSBProcess( const lldb::SBEvent & vEvent, bool & vrbExitAppEvent )
161 {
162         bool bOk = MIstatus::success;
163
164         const MIchar * pEventType = "";
165         const MIuint nEventType = vEvent.GetType();
166         switch( nEventType )
167         {
168         case lldb::SBProcess::eBroadcastBitInterrupt:
169                 pEventType = "eBroadcastBitInterrupt";
170                 break;
171         case lldb::SBProcess::eBroadcastBitProfileData:
172                 pEventType = "eBroadcastBitProfileData";
173                 break;
174         case lldb::SBProcess::eBroadcastBitStateChanged:
175                 pEventType = "eBroadcastBitStateChanged";
176                 bOk = HandleProcessEventBroadcastBitStateChanged( vEvent, vrbExitAppEvent );
177                 break;
178         case lldb::SBProcess::eBroadcastBitSTDERR:
179                 pEventType = "eBroadcastBitSTDERR";
180                 bOk = GetProcessStderr();
181                 break;
182         case lldb::SBProcess::eBroadcastBitSTDOUT:
183                 pEventType = "eBroadcastBitSTDOUT";
184                 bOk = GetProcessStdout();
185                 break;
186         default:
187         {
188                 const CMIUtilString msg( CMIUtilString::Format( MIRSRC( IDS_LLDBOUTOFBAND_ERR_UNKNOWN_EVENT ), "SBProcess", (MIuint) nEventType ) );
189                 SetErrorDescription( msg );
190                 return MIstatus::failure;
191         }
192         }
193         m_pLog->WriteLog( CMIUtilString::Format( "##### An SB Process event occurred: %s", pEventType ) );
194
195         return bOk;
196 }
197   
198 //++ ------------------------------------------------------------------------------------
199 // Details:     Handle a LLDB SBBreakpoint event.
200 // Type:        Method.
201 // Args:        vEvent  - (R) An LLDB broadcast event.
202 // Return:      MIstatus::success - Functionality succeeded.
203 //                      MIstatus::failure - Functionality failed.
204 // Throws:      None.
205 //--
206 bool CMICmnLLDBDebuggerHandleEvents::HandleEventSBBreakPoint( const lldb::SBEvent & vEvent )
207 {
208         bool bOk = MIstatus::success;
209
210         const MIchar * pEventType ="";
211     const lldb::BreakpointEventType eEvent = lldb::SBBreakpoint::GetBreakpointEventTypeFromEvent( vEvent );
212         switch( eEvent )
213         {
214         case lldb::eBreakpointEventTypeThreadChanged:
215                 pEventType = "eBreakpointEventTypeThreadChanged";
216                 break;
217         case lldb::eBreakpointEventTypeLocationsRemoved:
218                 pEventType = "eBreakpointEventTypeLocationsRemoved";
219                 break;
220     case lldb::eBreakpointEventTypeInvalidType:
221                 pEventType = "eBreakpointEventTypeInvalidType";
222                 break;
223     case lldb::eBreakpointEventTypeLocationsAdded:
224                 pEventType = "eBreakpointEventTypeLocationsAdded";
225                 bOk = HandleEventSBBreakpointLocationsAdded( vEvent );
226                 break;
227     case lldb::eBreakpointEventTypeAdded:
228                 pEventType = "eBreakpointEventTypeAdded";
229                 bOk = HandleEventSBBreakpointAdded( vEvent );
230                 break;
231     case lldb::eBreakpointEventTypeRemoved:
232                 pEventType = "eBreakpointEventTypeRemoved";
233                 bOk = HandleEventSBBreakpointCmn( vEvent );
234                 break;
235     case lldb::eBreakpointEventTypeLocationsResolved:
236                 pEventType = "eBreakpointEventTypeLocationsResolved";
237                 break;
238     case lldb::eBreakpointEventTypeEnabled:
239                 pEventType ="eBreakpointEventTypeEnabled";
240                 bOk = HandleEventSBBreakpointCmn( vEvent );
241                 break;
242     case lldb::eBreakpointEventTypeDisabled:
243                 pEventType = "eBreakpointEventTypeDisabled";
244                 bOk = HandleEventSBBreakpointCmn( vEvent );
245                 break;
246     case lldb::eBreakpointEventTypeCommandChanged:
247                 pEventType = "eBreakpointEventTypeCommandChanged";
248                 bOk = HandleEventSBBreakpointCmn( vEvent );
249                 break;
250     case lldb::eBreakpointEventTypeConditionChanged:
251                 pEventType ="eBreakpointEventTypeConditionChanged";
252                 bOk = HandleEventSBBreakpointCmn( vEvent );
253                 break;
254     case lldb::eBreakpointEventTypeIgnoreChanged:
255                 pEventType = "eBreakpointEventTypeIgnoreChanged";
256                 bOk = HandleEventSBBreakpointCmn( vEvent );
257                 break;
258     default:
259         {
260                 const CMIUtilString msg( CMIUtilString::Format( MIRSRC( IDS_LLDBOUTOFBAND_ERR_UNKNOWN_EVENT ), "SBBreakPoint", (MIuint) eEvent ) );
261                 SetErrorDescription( msg );
262                 return MIstatus::failure;
263         }
264         }
265         m_pLog->WriteLog( CMIUtilString::Format( "##### An SB Breakpoint event occurred: %s", pEventType ) );
266
267         return bOk;
268 }
269
270 //++ ------------------------------------------------------------------------------------
271 // Details:     Handle a LLDB SBBreakpoint event.
272 // Type:        Method.
273 // Args:        vEvent  - (R) An LLDB broadcast event.
274 // Return:      MIstatus::success - Functionality succeeded.
275 //                      MIstatus::failure - Functionality failed.
276 // Throws:      None.
277 //--
278 bool CMICmnLLDBDebuggerHandleEvents::HandleEventSBBreakpointLocationsAdded( const lldb::SBEvent & vEvent )
279 {
280         const MIuint nLoc = lldb::SBBreakpoint::GetNumBreakpointLocationsFromEvent( vEvent );
281         if( nLoc == 0 )
282                 return MIstatus::success;
283
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() ) );
287         
288         return TextToStdout( msg );
289 }
290         
291 //++ ------------------------------------------------------------------------------------
292 // Details:     Handle a LLDB SBBreakpoint event.
293 // Type:        Method.
294 // Args:        vEvent  - (R) An LLDB broadcast event.
295 // Return:      MIstatus::success - Functionality succeeded.
296 //                      MIstatus::failure - Functionality failed.
297 // Throws:      None.
298 //--
299 bool CMICmnLLDBDebuggerHandleEvents::HandleEventSBBreakpointCmn( const lldb::SBEvent & vEvent )
300 {
301         lldb::SBBreakpoint brkPt = lldb::SBBreakpoint::GetBreakpointFromEvent( vEvent );
302         if( !brkPt.IsValid() )
303                 return MIstatus::success;
304
305         CMICmnLLDBDebugSessionInfo & rSessionInfo( CMICmnLLDBDebugSessionInfo::Instance() );
306         CMICmnLLDBDebugSessionInfo::SBrkPtInfo sBrkPtInfo;
307         if( !rSessionInfo.GetBrkPtInfo( brkPt, sBrkPtInfo ) )
308         {
309                 SetErrorDescription( CMIUtilString::Format( MIRSRC( IDS_LLDBOUTOFBAND_ERR_BRKPT_INFO_GET ), "HandleEventSBBreakpointCmn()", brkPt.GetID() ) );
310                 return MIstatus::failure;
311         }
312         
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 ) )
318         {
319                 SetErrorDescription( CMIUtilString::Format( MIRSRC( IDS_LLDBOUTOFBAND_ERR_BRKPT_NOTFOUND ), "HandleEventSBBreakpointCmn()", brkPt.GetID() ) );
320                 return MIstatus::failure;
321         }
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;
334                                                                                                                                                                                 
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 ) )
338         {
339                 SetErrorDescription( CMIUtilString::Format( MIRSRC( IDS_LLDBOUTOFBAND_ERR_FORM_MI_RESPONSE ), "HandleEventSBBreakpointCmn()" ) );
340                 return MIstatus::failure;
341         }
342         
343         const CMICmnMIValueResult miValueResultC( "bkpt", miValueTuple );
344         const CMICmnMIOutOfBandRecord miOutOfBandRecord( CMICmnMIOutOfBandRecord::eOutOfBand_BreakPointModified, miValueResultC );
345         const bool bOk = MiOutOfBandRecordToStdout( miOutOfBandRecord );
346                 
347         return bOk;
348 }
349
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 
359 //                      response.
360 // Type:        Method.
361 // Args:        vEvent  - (R) An LLDB broadcast event.
362 // Return:      MIstatus::success - Functionality succeeded.
363 //                      MIstatus::failure - Functionality failed.
364 // Throws:      None.
365 //--
366 bool CMICmnLLDBDebuggerHandleEvents::HandleEventSBBreakpointAdded( const lldb::SBEvent & vEvent )
367 {
368         lldb::SBBreakpoint brkPt = lldb::SBBreakpoint::GetBreakpointFromEvent( vEvent );
369         if( !brkPt.IsValid() )
370                 return MIstatus::success;
371
372         CMICmnLLDBDebugSessionInfo & rSessionInfo( CMICmnLLDBDebugSessionInfo::Instance() );
373         CMICmnLLDBDebugSessionInfo::SBrkPtInfo sBrkPtInfo;
374         if( !rSessionInfo.GetBrkPtInfo( brkPt, sBrkPtInfo ) )
375         {
376                 SetErrorDescription( CMIUtilString::Format( MIRSRC( IDS_LLDBOUTOFBAND_ERR_BRKPT_INFO_GET ), "HandleEventSBBreakpointAdded()", brkPt.GetID() ) );
377                 return MIstatus::failure;
378         }
379         
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 )
385         {
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;
399         }
400         else
401         {
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();
415         }
416
417         CMICmnMIValueTuple miValueTuple;
418         if( !rSessionInfo.MIResponseFormBrkPtInfo( sBrkPtInfo, miValueTuple ) )
419         {
420                 SetErrorDescription( CMIUtilString::Format( MIRSRC( IDS_LLDBOUTOFBAND_ERR_FORM_MI_RESPONSE ), "HandleEventSBBreakpointAdded()" ) );
421                 return MIstatus::failure;
422         }
423
424         bool bOk = MIstatus::success;
425         if( bBrkPtExistAlready )
426         {
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 );
431         }
432         else
433         {
434                 // CODETAG_LLDB_BRKPT_ID_MAX
435                 if( brkPt.GetID() > (lldb::break_id_t) rSessionInfo.m_nBrkPointCntMax )
436                 {
437                         SetErrorDescription( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_BRKPT_CNT_EXCEEDED ), "HandleEventSBBreakpointAdded()", rSessionInfo.m_nBrkPointCntMax, sBrkPtInfo.m_id ) );
438                         return MIstatus::failure;
439                 }
440                 if( !rSessionInfo.RecordBrkPtInfo( brkPt.GetID(), sBrkPtInfo ) )
441                 {
442                         SetErrorDescription( CMIUtilString::Format( MIRSRC( IDS_LLDBOUTOFBAND_ERR_BRKPT_INFO_SET ), "HandleEventSBBreakpointAdded()", sBrkPtInfo.m_id ) );
443                         return MIstatus::failure;
444                 }
445
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 );
450         }
451                                                                                                                                                                                 
452         return bOk;
453 }
454
455 //++ ------------------------------------------------------------------------------------
456 // Details:     Handle a LLDB SBThread event.
457 // Type:        Method.
458 // Args:        vEvent  - (R) An LLDB broadcast event.
459 // Return:      MIstatus::success - Functionality succeeded.
460 //                      MIstatus::failure - Functionality failed.
461 // Throws:      None.
462 //--
463 bool CMICmnLLDBDebuggerHandleEvents::HandleEventSBThread( const lldb::SBEvent & vEvent )
464 {
465         if( !ChkForStateChanges() )
466                 return MIstatus::failure;
467
468         bool bOk = MIstatus::success;
469         const MIchar * pEventType = "";
470     const MIuint nEventType = vEvent.GetType();
471         switch( nEventType )
472         {
473         case lldb::SBThread::eBroadcastBitStackChanged:
474                 pEventType = "eBroadcastBitStackChanged";
475                 bOk = HandleEventSBThreadBitStackChanged( vEvent );
476                 break;
477         case lldb::SBThread::eBroadcastBitThreadSuspended:
478                 pEventType = "eBroadcastBitThreadSuspended";
479                 bOk = HandleEventSBThreadSuspended( vEvent );
480                 break;
481         case lldb::SBThread::eBroadcastBitThreadResumed:
482                 pEventType = "eBroadcastBitThreadResumed";
483                 break;
484         case lldb::SBThread::eBroadcastBitSelectedFrameChanged:
485                 pEventType = "eBroadcastBitSelectedFrameChanged";
486                 break;
487         case lldb::SBThread::eBroadcastBitThreadSelected:
488                 pEventType = "eBroadcastBitThreadSelected";
489                 break;
490         default:
491         {
492                 const CMIUtilString msg( CMIUtilString::Format( MIRSRC( IDS_LLDBOUTOFBAND_ERR_UNKNOWN_EVENT ), "SBThread", (MIuint) nEventType ) );
493                 SetErrorDescription( msg );
494                 return MIstatus::failure;
495         }
496         }
497         m_pLog->WriteLog( CMIUtilString::Format( "##### An SBThread event occurred: %s", pEventType ) );
498
499         return bOk;
500 }
501
502 //++ ------------------------------------------------------------------------------------
503 // Details:     Handle a LLDB SBThread event.
504 // Type:        Method.
505 // Args:        vEvent  - (R) An LLDB broadcast event.
506 // Return:      MIstatus::success - Functionality succeeded.
507 //                      MIstatus::failure - Functionality failed.
508 // Throws:      None.
509 //--
510 bool CMICmnLLDBDebuggerHandleEvents::HandleEventSBThreadSuspended( const lldb::SBEvent & vEvent )
511 {
512         lldb::SBThread thread = lldb::SBThread::GetThreadFromEvent( vEvent );
513         if( !thread.IsValid() )
514                 return MIstatus::success;
515
516         const lldb::StopReason eStopReason = thread.GetStopReason();
517         if( eStopReason != lldb::eStopReasonSignal )
518                 return MIstatus::success;
519
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 );    
531
532         return bOk;
533 }
534
535 //++ ------------------------------------------------------------------------------------
536 // Details:     Handle a LLDB SBThread event.
537 // Type:        Method.
538 // Args:        vEvent  - (R) An LLDB broadcast event.
539 // Return:      MIstatus::success - Functionality succeeded.
540 //                      MIstatus::failure - Functionality failed.
541 // Throws:      None.
542 //--
543 bool CMICmnLLDBDebuggerHandleEvents::HandleEventSBThreadBitStackChanged( const lldb::SBEvent & vEvent )
544 {
545         lldb::SBThread thread = lldb::SBThread::GetThreadFromEvent( vEvent );
546         if( !thread.IsValid() )
547                 return MIstatus::success;
548
549         lldb::SBStream streamOut;
550         const bool bOk = thread.GetStatus( streamOut );
551         return bOk && TextToStdout( streamOut.GetData() );
552 }
553         
554 //++ ------------------------------------------------------------------------------------
555 // Details:     Handle a LLDB SBCommandInterpreter event.
556 // Type:        Method.
557 // Args:        vEvent  - (R) An LLDB command interpreter event.
558 // Return:      MIstatus::success - Functionality succeeded.
559 //                      MIstatus::failure - Functionality failed.
560 // Throws:      None.
561 //--
562 bool CMICmnLLDBDebuggerHandleEvents::HandleEventSBCommandInterpreter( const lldb::SBEvent & vEvent )
563 {
564         // This function is not used
565         // *** This function is under development
566
567     const MIchar * pEventType = "";
568     const MIuint nEventType = vEvent.GetType();
569         switch( nEventType )
570         {
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 )
576         //{
577         //      m_pClientDriver->SetExitApplicationFlag();    
578         //      vrbYesExit = true;
579         //      return MIstatus::success;
580         //}             break;
581         case lldb::SBCommandInterpreter::eBroadcastBitResetPrompt:
582                 pEventType = "eBroadcastBitResetPrompt";
583                 break;
584         case lldb::SBCommandInterpreter::eBroadcastBitQuitCommandReceived:
585                 pEventType = "eBroadcastBitQuitCommandReceived";
586                 break;
587         case lldb::SBCommandInterpreter::eBroadcastBitAsynchronousOutputData:
588                 pEventType = "eBroadcastBitAsynchronousOutputData";
589                 break;
590         case lldb::SBCommandInterpreter::eBroadcastBitAsynchronousErrorData:
591                 pEventType = "eBroadcastBitAsynchronousErrorData";
592                 break;
593         default:
594         {
595                 const CMIUtilString msg( CMIUtilString::Format( MIRSRC( IDS_LLDBOUTOFBAND_ERR_UNKNOWN_EVENT ), "SBCommandInterpreter", (MIuint) nEventType ) );
596                 SetErrorDescription( msg );
597                 return MIstatus::failure;
598         }
599         }
600         m_pLog->WriteLog( CMIUtilString::Format( "##### An SBCommandInterpreter event occurred: %s", pEventType ) );
601
602         return MIstatus::success;
603 }
604  
605 //++ ------------------------------------------------------------------------------------
606 // Details:     Handle SBProcess event eBroadcastBitStateChanged.
607 // Type:        Method.
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.
612 // Throws:      None.
613 //--
614 bool CMICmnLLDBDebuggerHandleEvents::HandleProcessEventBroadcastBitStateChanged( const lldb::SBEvent & vEvent, bool & vrbExitAppEvent )
615 {
616         bool bOk = ChkForStateChanges();
617         bOk = bOk && GetProcessStdout();
618         bOk = bOk && GetProcessStderr();
619         if( !bOk )
620                 return MIstatus::failure;
621
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;
627
628         lldb::SBProcess process = lldb::SBProcess::GetProcessFromEvent( vEvent );
629         if( !process.IsValid() )
630         {
631                 const CMIUtilString msg( CMIUtilString::Format( MIRSRC( IDS_LLDBOUTOFBAND_ERR_PROCESS_INVALID ), "SBProcess", "HandleProcessEventBroadcastBitStateChanged()" ) );
632                 SetErrorDescription( msg );
633                 return MIstatus::failure;
634         }
635
636         bool bShouldBrk = true;
637         const MIchar * pEventType = "";
638     switch( eEventState )
639         {
640         case lldb::eStateUnloaded:
641                 pEventType = "eStateUnloaded";
642                 break;
643     case lldb::eStateConnected:
644                 pEventType = "eStateConnected";
645                 break;
646     case lldb::eStateAttaching:
647                 pEventType = "eStateAttaching";
648                 break;
649     case lldb::eStateLaunching:
650                 pEventType ="eStateLaunching";
651                 break;
652     case lldb::eStateStopped:
653                 pEventType = "eStateStopped";
654                 bOk = HandleProcessEventStateStopped( bShouldBrk );
655                 if( bShouldBrk )
656                         break;
657     case lldb::eStateCrashed:
658         case lldb::eStateSuspended:
659                 pEventType = "eStateSuspended";
660                 bOk = HandleProcessEventStateSuspended( vEvent );
661                 break;
662         case lldb::eStateRunning:
663                 pEventType = "eStateRunning";
664                 bOk = HandleProcessEventStateRunning();
665                 break;
666     case lldb::eStateStepping:
667                 pEventType = "eStateStepping";
668                 break;
669    case lldb::eStateDetached:
670                 pEventType = "eStateDetached";
671                 break;
672     case lldb::eStateExited:
673                 pEventType = "eStateExited";
674                 vrbExitAppEvent = true;
675                 bOk = HandleProcessEventStateExited();
676                 break;
677     default:
678         {
679                 const CMIUtilString msg( CMIUtilString::Format( MIRSRC( IDS_LLDBOUTOFBAND_ERR_UNKNOWN_EVENT ), "SBProcess BroadcastBitStateChanged", (MIuint) eEventState ) );
680                 SetErrorDescription( msg );
681                 return MIstatus::failure;
682         }
683         }
684
685         // ToDo: Remove when finished coding application
686         m_pLog->WriteLog( CMIUtilString::Format( "##### An SB Process event BroadcastBitStateChanged occurred: %s", pEventType ) );
687
688         return bOk;
689 }
690
691 //++ ------------------------------------------------------------------------------------
692 // Details:     Asynchronous event handler for LLDB Process state suspended.
693 // Type:        Method.
694 // Args:        vEvent  - (R) An LLDB event object.
695 // Return:      MIstatus::success - Functionality succeeded.
696 //                      MIstatus::failure - Functionality failed.
697 // Throws:      None.
698 //--
699 bool CMICmnLLDBDebuggerHandleEvents::HandleProcessEventStateSuspended( const lldb::SBEvent & vEvent )
700 {
701         // Make sure the program hasn't been auto-restarted:
702     if( lldb::SBProcess::GetRestartedFromEvent( vEvent ) )
703                 return MIstatus::success;
704
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 )
710         {
711                 if( !UpdateSelectedThread() )
712                         return MIstatus::failure;
713
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() );
718         }
719         else
720         {
721                 lldb::SBStream streamOut;
722                 const MIuint nTargetIndex = rDebugger.GetIndexOfTarget( target );
723                 if( nTargetIndex != UINT_MAX )
724                         streamOut.Printf( "Target %d: (", nTargetIndex );
725                 else
726                         streamOut.Printf( "Target <unknown index>: (" );
727                 target.GetDescription( streamOut, lldb::eDescriptionLevelBrief );
728                 streamOut.Printf( ") stopped.\n" );
729                 bOk = TextToStdout( streamOut.GetData() );
730         }
731         
732         return bOk;
733 }
734                 
735 //++ ------------------------------------------------------------------------------------
736 // Details:     Print to stdout MI formatted text to indicate process stopped.
737 // Type:        Method.
738 // Args:        vwrbShouldBrk   - (W) True = Yes break, false = do not.
739 // Return:      MIstatus::success - Functionality succeeded.
740 //                      MIstatus::failure - Functionality failed.
741 // Throws:      None.
742 //--
743 bool CMICmnLLDBDebuggerHandleEvents::HandleProcessEventStateStopped( bool & vwrbShouldBrk )
744 {
745         if( !UpdateSelectedThread() )
746                 return MIstatus::failure;
747
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 )
753         {
754         case lldb::eStopReasonInvalid:
755                 pEventType = "eStopReasonInvalid";
756                 vwrbShouldBrk = false;
757                 break;
758     case lldb::eStopReasonNone:
759                 pEventType = "eStopReasonNone";
760                 break;
761     case lldb::eStopReasonTrace:
762                 pEventType = "eStopReasonTrace";
763                 bOk = HandleProcessEventStopReasonTrace();
764                 break;
765     case lldb::eStopReasonBreakpoint:
766                 pEventType = "eStopReasonBreakpoint";
767                 bOk = HandleProcessEventStopReasonBreakpoint();
768                 break;
769     case lldb::eStopReasonWatchpoint:
770                 pEventType = "eStopReasonWatchpoint";
771                 break;
772     case lldb::eStopReasonSignal:
773                 pEventType = "eStopReasonSignal";
774                 bOk = HandleProcessEventStopSignal( vwrbShouldBrk );
775                 break;
776     case lldb::eStopReasonException:
777                 pEventType ="eStopReasonException";
778                 break;
779     case lldb::eStopReasonExec:
780                 pEventType = "eStopReasonExec";
781                 break;
782     case lldb::eStopReasonPlanComplete:
783                 pEventType = "eStopReasonPlanComplete";
784                 bOk = HandleProcessEventStopReasonTrace();
785                 break;
786     case lldb::eStopReasonThreadExiting:
787                 pEventType = "eStopReasonThreadExiting";
788                 break;
789         default:
790         {
791                 vwrbShouldBrk = false;
792                 
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)" );
807         }
808         }
809         
810         // ToDo: Remove when finished coding application
811         m_pLog->WriteLog( CMIUtilString::Format( "##### An SB Process event stop state occurred: %s", pEventType ) );
812
813         return bOk;
814 }
815
816 //++ ------------------------------------------------------------------------------------
817 // Details:     Asynchronous event handler for LLDB Process stop signal.
818 // Type:        Method.
819 // Args:        vwrbShouldBrk   - (W) True = Yes break, false = do not.
820 // Return:      MIstatus::success - Functionality succeeded.
821 //                      MIstatus::failure - Functionality failed.
822 // Throws:      None.
823 //--
824 bool CMICmnLLDBDebuggerHandleEvents::HandleProcessEventStopSignal( bool & vwrbShouldBrk )
825 {
826         bool bOk = MIstatus::success;
827
828         lldb::SBProcess & rProcess = CMICmnLLDBDebugSessionInfo::Instance().m_lldbProcess;
829         const MIuint64 nStopReason = rProcess.GetSelectedThread().GetStopReasonDataAtIndex( 0 );
830         switch( nStopReason )
831         {
832         case 2: // Terminal interrupt signal. SIGINT
833                 {
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)" );
850                 }
851                 break;
852         case 11: // Invalid memory reference. SIGSEGV
853                 {
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
874                 }
875                 break;
876         case 19:
877                 if( rProcess.IsValid() )
878                         rProcess.Continue();
879                 break;
880         case 5: //  Trace/breakpoint trap. SIGTRAP
881         {
882                 lldb::SBThread thread = rProcess.GetSelectedThread();
883                 const MIuint nFrames = thread.GetNumFrames();
884                 if( nFrames > 0 )
885                 {
886                         lldb::SBFrame frame = thread.GetFrameAtIndex( 0 );
887                         const char * pFnName = frame.GetFunctionName();
888                         if( pFnName != nullptr )
889                         {
890                                 const CMIUtilString fnName = CMIUtilString( pFnName );
891                                 static const CMIUtilString threadCloneFn = CMIUtilString( "__pthread_clone" );
892
893                                 if( CMIUtilString::Compare( threadCloneFn, fnName ) )
894                                 {
895                                         if( rProcess.IsValid() )
896                                         {
897                                                 rProcess.Continue();
898                                                 vwrbShouldBrk = true;
899                                                 break;
900                                         }
901                                 }
902                         }
903                 }
904         }
905         default:
906         {
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)" );
920         }
921         } // switch( nStopReason )
922          
923         return bOk;
924 }
925         
926 //++ ------------------------------------------------------------------------------------
927 // Details:     Form partial MI response in a MI value tuple object.
928 // Type:        Method.
929 // Args:        vwrMiValueTuple - (W) MI value tuple object.
930 // Return:      MIstatus::success - Functionality succeeded.
931 //                      MIstatus::failure - Functionality failed.
932 // Throws:      None.
933 //--
934 bool CMICmnLLDBDebuggerHandleEvents::MiHelpGetCurrentThreadFrame( CMICmnMIValueTuple & vwrMiValueTuple )
935 {
936         CMIUtilString strThreadFrame;
937         lldb::SBProcess & rProcess = CMICmnLLDBDebugSessionInfo::Instance().m_lldbProcess;
938         lldb::SBThread thread = rProcess.GetSelectedThread();
939         const MIuint nFrame = thread.GetNumFrames();
940         if( nFrame == 0 )
941         {
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 );
954
955                 vwrMiValueTuple = miValueTuple;
956
957                 return MIstatus::success;
958         }
959
960         CMICmnMIValueTuple miValueTuple;
961         if( !CMICmnLLDBDebugSessionInfo::Instance().MIResponseFormFrameInfo( thread, 0, miValueTuple ) )
962         {
963                 SetErrorDescription( CMIUtilString::Format( MIRSRC( IDS_LLDBOUTOFBAND_ERR_FORM_MI_RESPONSE ), "MiHelpGetCurrentThreadFrame()" ) );
964                 return MIstatus::failure;
965         }
966                 
967         vwrMiValueTuple = miValueTuple;
968
969         return MIstatus::success;
970 }
971         
972 //++ ------------------------------------------------------------------------------------
973 // Details:     Asynchronous event handler for LLDB Process stop reason breakpoint.
974 // Type:        Method.
975 // Args:        None.
976 // Return:      MIstatus::success - Functionality succeeded.
977 //                      MIstatus::failure - Functionality failed.
978 // Throws:      None.
979 //--
980 bool CMICmnLLDBDebuggerHandleEvents::HandleProcessEventStopReasonBreakpoint( void )
981 {
982         // CODETAG_DEBUG_SESSION_RUNNING_PROG_RECEIVED_SIGINT_PAUSE_PROGRAM
983         if( !CMIDriver::Instance().SetDriverStateRunningNotDebugging() )
984         {
985                 const CMIUtilString & rErrMsg( CMIDriver::Instance().GetErrorDescription() );
986                 SetErrorDescription( CMIUtilString::Format( MIRSRC( IDS_LLDBOUTOFBAND_ERR_SETNEWDRIVERSTATE ), "HandleProcessEventStopReasonBreakpoint()", rErrMsg.c_str() ) );
987                 return MIstatus::failure;
988         }
989
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 );
993         
994         return MiStoppedAtBreakPoint( brkPtId, brkPt );
995 }
996
997 //++ ------------------------------------------------------------------------------------
998 // Details:     Form the MI Out-of-band response for stopped reason on hitting a break point.
999 // Type:        Method.
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.
1004 // Throws:      None.
1005 //--
1006 bool CMICmnLLDBDebuggerHandleEvents::MiStoppedAtBreakPoint( const MIuint64 vBrkPtId, const lldb::SBBreakpoint & vBrkPt )
1007 {
1008         bool bOk = MIstatus::success;
1009
1010         lldb::SBProcess & rProcess = CMICmnLLDBDebugSessionInfo::Instance().m_lldbProcess;
1011         lldb::SBThread thread = rProcess.GetSelectedThread();
1012         const MIuint nFrame = thread.GetNumFrames();
1013         if( nFrame == 0 )
1014         {
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)" );
1038                 return bOk;
1039         }
1040
1041         CMICmnLLDBDebugSessionInfo & rSession =  CMICmnLLDBDebugSessionInfo::Instance();
1042
1043         lldb::SBFrame frame = thread.GetFrameAtIndex( 0 );
1044         lldb::addr_t pc = 0;
1045         CMIUtilString fnName;
1046         CMIUtilString fileName;
1047         CMIUtilString path; 
1048         MIuint nLine = 0;
1049         if( !rSession.GetFrameInfo( frame, pc, fnName, fileName, path, nLine ) )
1050         {
1051                 SetErrorDescription( CMIUtilString::Format( MIRSRC( IDS_LLDBOUTOFBAND_ERR_FRAME_INFO_GET ), "MiStoppedAtBreakPoint()" ) );
1052                 return MIstatus::failure;
1053         }
1054         
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 );
1066
1067         // frame={addr=\"0x%08x\",func=\"%s\",args=[],file=\"%s\",fullname=\"%s\",line=\"%d\"}
1068         if( bOk )
1069         {
1070                 CMICmnMIValueList miValueList( true );
1071                 const MIuint maskVarTypes = 0x1000;
1072                 bOk = rSession.MIResponseFormVariableInfo2( frame, maskVarTypes, miValueList );
1073                 
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 );
1078         }
1079
1080         // Add to MI thread-id=\"%d\",stopped-threads=\"all\"
1081         if( bOk )
1082         {
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 );
1087         }       
1088         if( bOk )
1089         {
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)" );
1095         }       
1096
1097         return MIstatus::success;
1098 }
1099         
1100 //++ ------------------------------------------------------------------------------------
1101 // Details:     Asynchronous event handler for LLDB Process stop reason trace.
1102 // Type:        Method.
1103 // Args:        None.
1104 // Return:      MIstatus::success - Functionality succeeded.
1105 //                      MIstatus::failure - Functionality failed.
1106 // Throws:      None.
1107 //--
1108 bool CMICmnLLDBDebuggerHandleEvents::HandleProcessEventStopReasonTrace( void )
1109 {
1110         bool bOk = true;
1111         lldb::SBProcess & rProcess = CMICmnLLDBDebugSessionInfo::Instance().m_lldbProcess;
1112         lldb::SBThread thread = rProcess.GetSelectedThread();
1113         const MIuint nFrame = thread.GetNumFrames();
1114         if( nFrame == 0 )
1115         {
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)" );
1125                 return bOk;
1126         }
1127
1128         CMICmnLLDBDebugSessionInfo & rSession = CMICmnLLDBDebugSessionInfo::Instance();
1129
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;
1135         CMIUtilString path; 
1136         MIuint nLine = 0;
1137         if( !rSession.GetFrameInfo( frame, pc, fnName, fileName, path, nLine ) )
1138         {
1139                 SetErrorDescription( CMIUtilString::Format( MIRSRC( IDS_LLDBOUTOFBAND_ERR_FRAME_INFO_GET ), "HandleProcessEventStopReasonTrace()" ) );
1140                 return MIstatus::failure;
1141         }
1142
1143         // Function args
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;
1151
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 );
1157
1158         // Add to MI thread-id=\"%d\",stopped-threads=\"all\"
1159         if( bOk )
1160         {
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 );
1165         }       
1166         if( bOk )
1167         {
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)" );
1173         }       
1174
1175         return bOk;
1176 }
1177
1178 //++ ------------------------------------------------------------------------------------
1179 // Details:     Asynchronous function update selected thread.
1180 // Type:        Method.
1181 // Args:        None.
1182 // Return:      MIstatus::success - Functionality succeeded.
1183 //                      MIstatus::failure - Functionality failed.
1184 // Throws:      None.
1185 //--
1186 bool CMICmnLLDBDebuggerHandleEvents::UpdateSelectedThread( void )
1187 {
1188         lldb::SBProcess process = CMICmnLLDBDebugSessionInfo::Instance().m_rLldbDebugger.GetSelectedTarget().GetProcess();
1189         if( !process.IsValid() )
1190                 return MIstatus::success;
1191
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) )
1196         {
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++ )
1202                 {
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 )
1208                         {
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;
1216                     break;
1217                 case lldb::eStopReasonPlanComplete:
1218                     if( !planThread.IsValid() )
1219                         planThread = thread;
1220                     break;
1221                                 case lldb::eStopReasonInvalid:
1222                 case lldb::eStopReasonNone:
1223                 default:
1224                     break;
1225                         }
1226                 }
1227                 if( planThread.IsValid() )
1228                         process.SetSelectedThread( planThread );
1229                 else if( otherThread.IsValid() )
1230                         process.SetSelectedThread( otherThread );
1231                 else
1232                 {
1233                         if( currentThread.IsValid() )
1234                                 thread = currentThread;
1235                         else
1236                                 thread = process.GetThreadAtIndex( 0 );
1237
1238                         if( thread.IsValid() )
1239                                 process.SetSelectedThread( thread );
1240                 }
1241         } // if( !currentThread.IsValid() || (eCurrentThreadStoppedReason == lldb::eStopReasonInvalid) || (eCurrentThreadStoppedReason == lldb::eStopReasonNone) )
1242         
1243         return MIstatus::success;
1244 }
1245
1246 //++ ------------------------------------------------------------------------------------
1247 // Details:     Print to stdout "*running,thread-id=\"all\"", "(gdb)".
1248 // Type:        Method.
1249 // Args:        None.
1250 // Return:      MIstatus::success - Functionality succeeded.
1251 //                      MIstatus::failure - Functionality failed.
1252 // Throws:      None.
1253 //--
1254 bool CMICmnLLDBDebuggerHandleEvents::HandleProcessEventStateRunning( void )
1255 {
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)" );
1261
1262         return bOk;
1263 }
1264
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\"",
1269 //                                                      "(gdb)"
1270 // Type:        Method.
1271 // Args:        None.
1272 // Return:      MIstatus::success - Functionality succeeded.
1273 //                      MIstatus::failure - Functionality failed.
1274 // Throws:      None.
1275 //--
1276 bool CMICmnLLDBDebuggerHandleEvents::HandleProcessEventStateExited( void )
1277 {
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 );
1286         if( bOk )
1287         {
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 );
1295         }       
1296         if( bOk )
1297         {
1298                 CMICmnMIValueConst miValueConst4( "exited-normally" );
1299                 CMICmnMIValueResult miValueResult4( "reason", miValueConst4 );
1300                 CMICmnMIOutOfBandRecord miOutOfBandRecord3( CMICmnMIOutOfBandRecord::eOutOfBand_Stopped, miValueResult4 );
1301                 bOk = MiOutOfBandRecordToStdout( miOutOfBandRecord3 );
1302         }       
1303         bOk = bOk && TextToStdout( "(gdb)" );
1304
1305         return bOk;
1306 }
1307
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.
1312 // Type:        Method.
1313 // Args:        None.
1314 // Return:      MIstatus::success - Functionality succeeded.
1315 //                      MIstatus::failure - Functionality failed.
1316 // Throws:      None.
1317 //--
1318 bool CMICmnLLDBDebuggerHandleEvents::GetProcessStdout( void )
1319 {
1320         bool bOk = MIstatus::success;
1321
1322         char c;
1323         size_t nBytes = 0;
1324         CMIUtilString text;
1325         lldb::SBProcess process = CMICmnLLDBDebugSessionInfo::Instance().m_rLldbDebugger.GetSelectedTarget().GetProcess();
1326         while( process.GetSTDOUT( &c, 1 ) > 0 )
1327         {
1328                 CMIUtilString str;
1329                 if( ConvertPrintfCtrlCodeToString( c, str ) )
1330                         text += str;
1331                 nBytes++;
1332         }
1333         if( nBytes > 0 )
1334         {
1335                 const CMIUtilString t( CMIUtilString::Format( "~\"%s\"", text.c_str() ) );
1336                 bOk = TextToStdout( t );
1337         }
1338         
1339         return bOk;
1340 }
1341
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.
1346 // Type:        Method.
1347 // Args:        None.
1348 // Return:      MIstatus::success - Functionality succeeded.
1349 //                      MIstatus::failure - Functionality failed.
1350 // Throws:      None.
1351 //--
1352 bool CMICmnLLDBDebuggerHandleEvents::GetProcessStderr( void )
1353 {
1354         bool bOk = MIstatus::success;
1355
1356         char c;
1357         size_t nBytes = 0;
1358         CMIUtilString text;
1359         lldb::SBProcess process = CMICmnLLDBDebugSessionInfo::Instance().m_rLldbDebugger.GetSelectedTarget().GetProcess();
1360         while( process.GetSTDERR( &c, 1 ) > 0 )
1361         {
1362                 CMIUtilString str;
1363                 if( ConvertPrintfCtrlCodeToString( c, str ) )
1364                         text += str;
1365                 nBytes++;
1366         }
1367         if( nBytes > 0 )
1368         {
1369                 const CMIUtilString t( CMIUtilString::Format( "~\"%s\"", text.c_str() ) );
1370                 bOk = TextToStdout( t );
1371         }
1372         
1373         return bOk;
1374 }
1375         
1376 //++ ------------------------------------------------------------------------------------
1377 // Details:     Convert text stream control codes to text equivalent.
1378 // Type:        Method.
1379 // Args:        vCtrl                           - (R) The control code.
1380 //                      vwrStrEquivalent        - (W) The text equivalent.
1381 // Return:      MIstatus::success - Functionality succeeded.
1382 //                      MIstatus::failure - Functionality failed.
1383 // Throws:      None.
1384 //--
1385 bool CMICmnLLDBDebuggerHandleEvents::ConvertPrintfCtrlCodeToString( const MIchar vCtrl, CMIUtilString & vwrStrEquivalent )
1386 {
1387         switch( vCtrl )
1388         {
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;
1397                 default: 
1398                         vwrStrEquivalent = CMIUtilString::Format( "%c", vCtrl ); 
1399                         break;
1400         }
1401
1402         return MIstatus::success;
1403 }
1404
1405 //++ ------------------------------------------------------------------------------------
1406 // Details:     Asynchronous event function check for state changes.
1407 // Type:        Method.
1408 // Args:        None.
1409 // Return:      MIstatus::success - Functionality succeeded.
1410 //                      MIstatus::failure - Functionality failed.
1411 // Throws:      None.
1412 //--
1413 bool CMICmnLLDBDebuggerHandleEvents::ChkForStateChanges( void )
1414 {
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;
1421
1422         bool bOk = MIstatus::success;
1423
1424         // Check for created threads
1425     const MIuint nThread = rProcess.GetNumThreads();
1426         for( MIuint i = 0; i < nThread; i++ )
1427         {
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() )
1432                         continue;
1433
1434                 CMICmnLLDBDebugSessionInfo::VecActiveThreadId_t::const_iterator it = CMICmnLLDBDebugSessionInfo::Instance().m_vecActiveThreadId.begin();
1435                 bool bFound = false;
1436                 while( it != CMICmnLLDBDebugSessionInfo::Instance().m_vecActiveThreadId.end() )
1437                 {
1438                         const MIuint nThreadId = *it;
1439                         if( nThreadId == i )
1440                         {
1441                                 bFound = true;
1442                                 break;
1443                         }
1444
1445                         // Next
1446                         ++it;
1447                 }
1448                 if( !bFound )
1449                 {
1450                         CMICmnLLDBDebugSessionInfo::Instance().m_vecActiveThreadId.push_back( i );
1451
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 );
1461                         if( !bOk )
1462                                 return MIstatus::failure;
1463                 }
1464         }
1465
1466         lldb::SBThread currentThread = rProcess.GetSelectedThread();
1467         if( currentThread.IsValid() )
1468         {
1469                 const MIuint threadId = currentThread.GetIndexID();
1470                 if( CMICmnLLDBDebugSessionInfo::Instance().m_currentSelectedThread != threadId )
1471                 {
1472                         CMICmnLLDBDebugSessionInfo::Instance().m_currentSelectedThread = threadId;
1473
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;
1481                 }
1482         }
1483
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() )
1487         {
1488                 const MIuint nThreadId = *it;
1489                 lldb::SBThread thread = rProcess.GetThreadAtIndex( nThreadId );
1490                 if( !thread.IsValid() )
1491                 {
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 );
1501                         if( !bOk )
1502                                 return MIstatus::failure;
1503                 }
1504
1505                 // Next
1506                 ++it;
1507         }
1508                         
1509         return TextToStdout( "(gdb)" ); 
1510 }
1511
1512 //++ ------------------------------------------------------------------------------------
1513 // Details:     Take a fully formed MI result record and send to the stdout stream.
1514 //                      Also output to the MI Log file.
1515 // Type:        Method.
1516 // Args:        vrMiResultRecord        - (R) MI result record object.
1517 // Return:      MIstatus::success - Functionality succeeded.
1518 //                      MIstatus::failure - Functionality failed.
1519 // Throws:      None.
1520 //--
1521 bool CMICmnLLDBDebuggerHandleEvents::MiResultRecordToStdout( const CMICmnMIResultRecord & vrMiResultRecord )
1522 {
1523         return TextToStdout( vrMiResultRecord.GetString() );
1524 }
1525
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.
1529 // Type:        Method.
1530 // Args:        vrMiOutOfBandRecord     - (R) MI Out-of-band record object.
1531 // Return:      MIstatus::success - Functionality succeeded.
1532 //                      MIstatus::failure - Functionality failed.
1533 // Throws:      None.
1534 //--
1535 bool CMICmnLLDBDebuggerHandleEvents::MiOutOfBandRecordToStdout( const CMICmnMIOutOfBandRecord & vrMiOutOfBandRecord )
1536 {
1537         return TextToStdout( vrMiOutOfBandRecord.GetString() );
1538 }
1539
1540 //++ ------------------------------------------------------------------------------------
1541 // Details:     Take a text data and send to the stdout stream. Also output to the MI Log
1542 //                      file.
1543 // Type:        Method.
1544 // Args:        vrTxt   - (R) Text.
1545 // Return:      MIstatus::success - Functionality succeeded.
1546 //                      MIstatus::failure - Functionality failed.
1547 // Throws:      None.
1548 //--
1549 bool CMICmnLLDBDebuggerHandleEvents::TextToStdout( const CMIUtilString & vrTxt )
1550 {
1551         return CMICmnStreamStdout::TextToStdout( vrTxt );
1552 }
1553
1554 //++ ------------------------------------------------------------------------------------
1555 // Details:     Take a text data and send to the stderr stream. Also output to the MI Log
1556 //                      file.
1557 // Type:        Method.
1558 // Args:        vrTxt   - (R) Text.
1559 // Return:      MIstatus::success - Functionality succeeded.
1560 //                      MIstatus::failure - Functionality failed.
1561 // Throws:      None.
1562 //--
1563 bool CMICmnLLDBDebuggerHandleEvents::TextToStderr( const CMIUtilString & vrTxt )
1564 {
1565         return CMICmnStreamStderr::TextToStderr( vrTxt );
1566 }