]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/lldb/tools/lldb-mi/MICmnLLDBDebuggerHandleEvents.cpp
Update LLDB snapshot to upstream r225923 (git 2b588ecd)
[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
83 CMICmnLLDBDebuggerHandleEvents::Initialize(void)
84 {
85     m_clientUsageRefCnt++;
86
87     if (m_bInitialized)
88         return MIstatus::success;
89
90     m_bInitialized = MIstatus::success;
91
92     return m_bInitialized;
93 }
94
95 //++ ------------------------------------------------------------------------------------
96 // Details: Release resources for *this broardcaster object.
97 // Type:    Method.
98 // Args:    None.
99 // Return:  MIstatus::success - Functionality succeeded.
100 //          MIstatus::failure - Functionality failed.
101 // Throws:  None.
102 //--
103 bool
104 CMICmnLLDBDebuggerHandleEvents::Shutdown(void)
105 {
106     if (--m_clientUsageRefCnt > 0)
107         return MIstatus::success;
108
109     if (!m_bInitialized)
110         return MIstatus::success;
111
112     m_bInitialized = false;
113
114     return MIstatus::success;
115 }
116
117 //++ ------------------------------------------------------------------------------------
118 // Details: Interpret the event object to asscertain the action to take or information to
119 //          to form and put in a MI Out-of-band record object which is given to stdout.
120 // Type:    Method.
121 // Args:    vEvent          - (R) An LLDB broadcast event.
122 //          vrbHandledEvent - (W) True - event handled, false = not handled.
123 //          vrbExitAppEvent - (W) True - Received LLDB exit app event, false = did not.
124 // Return:  MIstatus::success - Functionality succeeded.
125 //          MIstatus::failure - Functionality failed.
126 // Throws:  None.
127 //--
128 bool
129 CMICmnLLDBDebuggerHandleEvents::HandleEvent(const lldb::SBEvent &vEvent, bool &vrbHandledEvent, bool &vrbExitAppEvent)
130 {
131     bool bOk = MIstatus::success;
132     vrbHandledEvent = false;
133     vrbExitAppEvent = false;
134
135     if (lldb::SBProcess::EventIsProcessEvent(vEvent))
136     {
137         vrbHandledEvent = true;
138         bOk = HandleEventSBProcess(vEvent, vrbExitAppEvent);
139     }
140     else if (lldb::SBBreakpoint::EventIsBreakpointEvent(vEvent))
141     {
142         vrbHandledEvent = true;
143         bOk = HandleEventSBBreakPoint(vEvent);
144     }
145     else if (lldb::SBThread::EventIsThreadEvent(vEvent))
146     {
147         vrbHandledEvent = true;
148         bOk = HandleEventSBThread(vEvent);
149     }
150
151     return bOk;
152 }
153
154 //++ ------------------------------------------------------------------------------------
155 // Details: Handle a LLDB SBProcess event.
156 // Type:    Method.
157 // Args:    vEvent          - (R) An LLDB broadcast event.
158 //          vrbExitAppEvent - (W) True - Received LLDB exit app event, false = did not.
159 // Return:  MIstatus::success - Functionality succeeded.
160 //          MIstatus::failure - Functionality failed.
161 // Throws:  None.
162 //--
163 bool
164 CMICmnLLDBDebuggerHandleEvents::HandleEventSBProcess(const lldb::SBEvent &vEvent, bool &vrbExitAppEvent)
165 {
166     bool bOk = MIstatus::success;
167
168     const MIchar *pEventType = "";
169     const MIuint nEventType = vEvent.GetType();
170     switch (nEventType)
171     {
172         case lldb::SBProcess::eBroadcastBitInterrupt:
173             pEventType = "eBroadcastBitInterrupt";
174             break;
175         case lldb::SBProcess::eBroadcastBitProfileData:
176             pEventType = "eBroadcastBitProfileData";
177             break;
178         case lldb::SBProcess::eBroadcastBitStateChanged:
179             pEventType = "eBroadcastBitStateChanged";
180             bOk = HandleProcessEventBroadcastBitStateChanged(vEvent, vrbExitAppEvent);
181             break;
182         case lldb::SBProcess::eBroadcastBitSTDERR:
183             pEventType = "eBroadcastBitSTDERR";
184             bOk = GetProcessStderr();
185             break;
186         case lldb::SBProcess::eBroadcastBitSTDOUT:
187             pEventType = "eBroadcastBitSTDOUT";
188             bOk = GetProcessStdout();
189             break;
190         default:
191         {
192             const CMIUtilString msg(CMIUtilString::Format(MIRSRC(IDS_LLDBOUTOFBAND_ERR_UNKNOWN_EVENT), "SBProcess", (MIuint)nEventType));
193             SetErrorDescription(msg);
194             return MIstatus::failure;
195         }
196     }
197     m_pLog->WriteLog(CMIUtilString::Format("##### An SB Process event occurred: %s", pEventType));
198
199     return bOk;
200 }
201
202 //++ ------------------------------------------------------------------------------------
203 // Details: Handle a LLDB SBBreakpoint event.
204 // Type:    Method.
205 // Args:    vEvent  - (R) An LLDB broadcast event.
206 // Return:  MIstatus::success - Functionality succeeded.
207 //          MIstatus::failure - Functionality failed.
208 // Throws:  None.
209 //--
210 bool
211 CMICmnLLDBDebuggerHandleEvents::HandleEventSBBreakPoint(const lldb::SBEvent &vEvent)
212 {
213     bool bOk = MIstatus::success;
214
215     const MIchar *pEventType = "";
216     const lldb::BreakpointEventType eEvent = lldb::SBBreakpoint::GetBreakpointEventTypeFromEvent(vEvent);
217     switch (eEvent)
218     {
219         case lldb::eBreakpointEventTypeThreadChanged:
220             pEventType = "eBreakpointEventTypeThreadChanged";
221             break;
222         case lldb::eBreakpointEventTypeLocationsRemoved:
223             pEventType = "eBreakpointEventTypeLocationsRemoved";
224             break;
225         case lldb::eBreakpointEventTypeInvalidType:
226             pEventType = "eBreakpointEventTypeInvalidType";
227             break;
228         case lldb::eBreakpointEventTypeLocationsAdded:
229             pEventType = "eBreakpointEventTypeLocationsAdded";
230             bOk = HandleEventSBBreakpointLocationsAdded(vEvent);
231             break;
232         case lldb::eBreakpointEventTypeAdded:
233             pEventType = "eBreakpointEventTypeAdded";
234             bOk = HandleEventSBBreakpointAdded(vEvent);
235             break;
236         case lldb::eBreakpointEventTypeRemoved:
237             pEventType = "eBreakpointEventTypeRemoved";
238             bOk = HandleEventSBBreakpointCmn(vEvent);
239             break;
240         case lldb::eBreakpointEventTypeLocationsResolved:
241             pEventType = "eBreakpointEventTypeLocationsResolved";
242             break;
243         case lldb::eBreakpointEventTypeEnabled:
244             pEventType = "eBreakpointEventTypeEnabled";
245             bOk = HandleEventSBBreakpointCmn(vEvent);
246             break;
247         case lldb::eBreakpointEventTypeDisabled:
248             pEventType = "eBreakpointEventTypeDisabled";
249             bOk = HandleEventSBBreakpointCmn(vEvent);
250             break;
251         case lldb::eBreakpointEventTypeCommandChanged:
252             pEventType = "eBreakpointEventTypeCommandChanged";
253             bOk = HandleEventSBBreakpointCmn(vEvent);
254             break;
255         case lldb::eBreakpointEventTypeConditionChanged:
256             pEventType = "eBreakpointEventTypeConditionChanged";
257             bOk = HandleEventSBBreakpointCmn(vEvent);
258             break;
259         case lldb::eBreakpointEventTypeIgnoreChanged:
260             pEventType = "eBreakpointEventTypeIgnoreChanged";
261             bOk = HandleEventSBBreakpointCmn(vEvent);
262             break;
263     }
264     m_pLog->WriteLog(CMIUtilString::Format("##### An SB Breakpoint event occurred: %s", pEventType));
265
266     return bOk;
267 }
268
269 //++ ------------------------------------------------------------------------------------
270 // Details: Handle a LLDB SBBreakpoint event.
271 // Type:    Method.
272 // Args:    vEvent  - (R) An LLDB broadcast event.
273 // Return:  MIstatus::success - Functionality succeeded.
274 //          MIstatus::failure - Functionality failed.
275 // Throws:  None.
276 //--
277 bool
278 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
300 CMICmnLLDBDebuggerHandleEvents::HandleEventSBBreakpointCmn(const lldb::SBEvent &vEvent)
301 {
302     lldb::SBBreakpoint brkPt = lldb::SBBreakpoint::GetBreakpointFromEvent(vEvent);
303     if (!brkPt.IsValid())
304         return MIstatus::success;
305
306     CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance());
307     CMICmnLLDBDebugSessionInfo::SBrkPtInfo sBrkPtInfo;
308     if (!rSessionInfo.GetBrkPtInfo(brkPt, sBrkPtInfo))
309     {
310         SetErrorDescription(
311             CMIUtilString::Format(MIRSRC(IDS_LLDBOUTOFBAND_ERR_BRKPT_INFO_GET), "HandleEventSBBreakpointCmn()", brkPt.GetID()));
312         return MIstatus::failure;
313     }
314
315     // CODETAG_LLDB_BREAKPOINT_CREATION
316     // This is in a worker thread
317     // Add more breakpoint information or overwrite existing information
318     CMICmnLLDBDebugSessionInfo::SBrkPtInfo sBrkPtInfoRec;
319     if (!rSessionInfo.RecordBrkPtInfoGet(brkPt.GetID(), sBrkPtInfoRec))
320     {
321         SetErrorDescription(
322             CMIUtilString::Format(MIRSRC(IDS_LLDBOUTOFBAND_ERR_BRKPT_NOTFOUND), "HandleEventSBBreakpointCmn()", brkPt.GetID()));
323         return MIstatus::failure;
324     }
325     sBrkPtInfo.m_bDisp = sBrkPtInfoRec.m_bDisp;
326     sBrkPtInfo.m_bEnabled = brkPt.IsEnabled();
327     sBrkPtInfo.m_bHaveArgOptionThreadGrp = false;
328     sBrkPtInfo.m_strOptThrdGrp = "";
329     sBrkPtInfo.m_nTimes = brkPt.GetHitCount();
330     sBrkPtInfo.m_strOrigLoc = sBrkPtInfoRec.m_strOrigLoc;
331     sBrkPtInfo.m_nIgnore = sBrkPtInfoRec.m_nIgnore;
332     sBrkPtInfo.m_bPending = sBrkPtInfoRec.m_bPending;
333     sBrkPtInfo.m_bCondition = sBrkPtInfoRec.m_bCondition;
334     sBrkPtInfo.m_strCondition = sBrkPtInfoRec.m_strCondition;
335     sBrkPtInfo.m_bBrkPtThreadId = sBrkPtInfoRec.m_bBrkPtThreadId;
336     sBrkPtInfo.m_nBrkPtThreadId = sBrkPtInfoRec.m_nBrkPtThreadId;
337
338     // MI print "=breakpoint-modified,bkpt={number=\"%d\",type=\"breakpoint\",disp=\"%s\",enabled=\"%c\",addr=\"0x%08x\",
339     // func=\"%s\",file=\"%s\",fullname=\"%s/%s\",line=\"%d\",times=\"%d\",original-location=\"%s\"}"
340     CMICmnMIValueTuple miValueTuple;
341     if (!rSessionInfo.MIResponseFormBrkPtInfo(sBrkPtInfo, miValueTuple))
342     {
343         SetErrorDescription(CMIUtilString::Format(MIRSRC(IDS_LLDBOUTOFBAND_ERR_FORM_MI_RESPONSE), "HandleEventSBBreakpointCmn()"));
344         return MIstatus::failure;
345     }
346
347     const CMICmnMIValueResult miValueResultC("bkpt", miValueTuple);
348     const CMICmnMIOutOfBandRecord miOutOfBandRecord(CMICmnMIOutOfBandRecord::eOutOfBand_BreakPointModified, miValueResultC);
349     const bool bOk = MiOutOfBandRecordToStdout(miOutOfBandRecord);
350
351     return bOk;
352 }
353
354 //++ ------------------------------------------------------------------------------------
355 // Details: Handle a LLDB SBBreakpoint added event.
356 //          Add more breakpoint information or overwrite existing information.
357 //          Normally a break point session info objects exists by now when an MI command
358 //          was issued to insert a break so the retrieval would normally always succeed
359 //          however should a user type "b main" into a console then LLDB will create a
360 //          breakpoint directly, hence no MI command, hence no previous record of the
361 //          breakpoint so RecordBrkPtInfoGet() will fail. We still get the event though
362 //          so need to create a breakpoint info object here and send appropriate MI
363 //          response.
364 // Type:    Method.
365 // Args:    vEvent  - (R) An LLDB broadcast event.
366 // Return:  MIstatus::success - Functionality succeeded.
367 //          MIstatus::failure - Functionality failed.
368 // Throws:  None.
369 //--
370 bool
371 CMICmnLLDBDebuggerHandleEvents::HandleEventSBBreakpointAdded(const lldb::SBEvent &vEvent)
372 {
373     lldb::SBBreakpoint brkPt = lldb::SBBreakpoint::GetBreakpointFromEvent(vEvent);
374     if (!brkPt.IsValid())
375         return MIstatus::success;
376
377     CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance());
378     CMICmnLLDBDebugSessionInfo::SBrkPtInfo sBrkPtInfo;
379     if (!rSessionInfo.GetBrkPtInfo(brkPt, sBrkPtInfo))
380     {
381         SetErrorDescription(
382             CMIUtilString::Format(MIRSRC(IDS_LLDBOUTOFBAND_ERR_BRKPT_INFO_GET), "HandleEventSBBreakpointAdded()", brkPt.GetID()));
383         return MIstatus::failure;
384     }
385
386     // CODETAG_LLDB_BREAKPOINT_CREATION
387     // This is in a worker thread
388     CMICmnLLDBDebugSessionInfo::SBrkPtInfo sBrkPtInfoRec;
389     const bool bBrkPtExistAlready = rSessionInfo.RecordBrkPtInfoGet(brkPt.GetID(), sBrkPtInfoRec);
390     if (bBrkPtExistAlready)
391     {
392         // Update breakpoint information object
393         sBrkPtInfo.m_bDisp = sBrkPtInfoRec.m_bDisp;
394         sBrkPtInfo.m_bEnabled = brkPt.IsEnabled();
395         sBrkPtInfo.m_bHaveArgOptionThreadGrp = false;
396         sBrkPtInfo.m_strOptThrdGrp.clear();
397         sBrkPtInfo.m_nTimes = brkPt.GetHitCount();
398         sBrkPtInfo.m_strOrigLoc = sBrkPtInfoRec.m_strOrigLoc;
399         sBrkPtInfo.m_nIgnore = sBrkPtInfoRec.m_nIgnore;
400         sBrkPtInfo.m_bPending = sBrkPtInfoRec.m_bPending;
401         sBrkPtInfo.m_bCondition = sBrkPtInfoRec.m_bCondition;
402         sBrkPtInfo.m_strCondition = sBrkPtInfoRec.m_strCondition;
403         sBrkPtInfo.m_bBrkPtThreadId = sBrkPtInfoRec.m_bBrkPtThreadId;
404         sBrkPtInfo.m_nBrkPtThreadId = sBrkPtInfoRec.m_nBrkPtThreadId;
405     }
406     else
407     {
408         // Create a breakpoint information object
409         sBrkPtInfo.m_bDisp = brkPt.IsOneShot();
410         sBrkPtInfo.m_bEnabled = brkPt.IsEnabled();
411         sBrkPtInfo.m_bHaveArgOptionThreadGrp = false;
412         sBrkPtInfo.m_strOptThrdGrp.clear();
413         sBrkPtInfo.m_strOrigLoc = CMIUtilString::Format("%s:%d", sBrkPtInfo.m_fileName.c_str(), sBrkPtInfo.m_nLine);
414         sBrkPtInfo.m_nIgnore = brkPt.GetIgnoreCount();
415         sBrkPtInfo.m_bPending = false;
416         const MIchar *pStrCondition = brkPt.GetCondition();
417         sBrkPtInfo.m_bCondition = (pStrCondition != nullptr) ? true : false;
418         sBrkPtInfo.m_strCondition = (pStrCondition != nullptr) ? pStrCondition : "??";
419         sBrkPtInfo.m_bBrkPtThreadId = (brkPt.GetThreadID() != 0) ? true : false;
420         sBrkPtInfo.m_nBrkPtThreadId = brkPt.GetThreadID();
421     }
422
423     CMICmnMIValueTuple miValueTuple;
424     if (!rSessionInfo.MIResponseFormBrkPtInfo(sBrkPtInfo, miValueTuple))
425     {
426         SetErrorDescription(CMIUtilString::Format(MIRSRC(IDS_LLDBOUTOFBAND_ERR_FORM_MI_RESPONSE), "HandleEventSBBreakpointAdded()"));
427         return MIstatus::failure;
428     }
429
430     bool bOk = MIstatus::success;
431     if (bBrkPtExistAlready)
432     {
433         // MI print
434         // "=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\"}"
435         const CMICmnMIValueResult miValueResult("bkpt", miValueTuple);
436         const CMICmnMIOutOfBandRecord miOutOfBandRecord(CMICmnMIOutOfBandRecord::eOutOfBand_BreakPointModified, miValueResult);
437         bOk = MiOutOfBandRecordToStdout(miOutOfBandRecord);
438     }
439     else
440     {
441         // CODETAG_LLDB_BRKPT_ID_MAX
442         if (brkPt.GetID() > (lldb::break_id_t)rSessionInfo.m_nBrkPointCntMax)
443         {
444             SetErrorDescription(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_BRKPT_CNT_EXCEEDED), "HandleEventSBBreakpointAdded()",
445                                                       rSessionInfo.m_nBrkPointCntMax, sBrkPtInfo.m_id));
446             return MIstatus::failure;
447         }
448         if (!rSessionInfo.RecordBrkPtInfo(brkPt.GetID(), sBrkPtInfo))
449         {
450             SetErrorDescription(
451                 CMIUtilString::Format(MIRSRC(IDS_LLDBOUTOFBAND_ERR_BRKPT_INFO_SET), "HandleEventSBBreakpointAdded()", sBrkPtInfo.m_id));
452             return MIstatus::failure;
453         }
454
455         // MI print
456         // "=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\"}"
457         const CMICmnMIValueResult miValueResult("bkpt", miValueTuple);
458         const CMICmnMIOutOfBandRecord miOutOfBandRecord(CMICmnMIOutOfBandRecord::eOutOfBand_BreakPointCreated, miValueResult);
459         bOk = MiOutOfBandRecordToStdout(miOutOfBandRecord);
460     }
461
462     return bOk;
463 }
464
465 //++ ------------------------------------------------------------------------------------
466 // Details: Handle a LLDB SBThread event.
467 // Type:    Method.
468 // Args:    vEvent  - (R) An LLDB broadcast event.
469 // Return:  MIstatus::success - Functionality succeeded.
470 //          MIstatus::failure - Functionality failed.
471 // Throws:  None.
472 //--
473 bool
474 CMICmnLLDBDebuggerHandleEvents::HandleEventSBThread(const lldb::SBEvent &vEvent)
475 {
476     if (!ChkForStateChanges())
477         return MIstatus::failure;
478
479     bool bOk = MIstatus::success;
480     const MIchar *pEventType = "";
481     const MIuint nEventType = vEvent.GetType();
482     switch (nEventType)
483     {
484         case lldb::SBThread::eBroadcastBitStackChanged:
485             pEventType = "eBroadcastBitStackChanged";
486             bOk = HandleEventSBThreadBitStackChanged(vEvent);
487             break;
488         case lldb::SBThread::eBroadcastBitThreadSuspended:
489             pEventType = "eBroadcastBitThreadSuspended";
490             bOk = HandleEventSBThreadSuspended(vEvent);
491             break;
492         case lldb::SBThread::eBroadcastBitThreadResumed:
493             pEventType = "eBroadcastBitThreadResumed";
494             break;
495         case lldb::SBThread::eBroadcastBitSelectedFrameChanged:
496             pEventType = "eBroadcastBitSelectedFrameChanged";
497             break;
498         case lldb::SBThread::eBroadcastBitThreadSelected:
499             pEventType = "eBroadcastBitThreadSelected";
500             break;
501         default:
502         {
503             const CMIUtilString msg(CMIUtilString::Format(MIRSRC(IDS_LLDBOUTOFBAND_ERR_UNKNOWN_EVENT), "SBThread", (MIuint)nEventType));
504             SetErrorDescription(msg);
505             return MIstatus::failure;
506         }
507     }
508     m_pLog->WriteLog(CMIUtilString::Format("##### An SBThread event occurred: %s", pEventType));
509
510     return bOk;
511 }
512
513 //++ ------------------------------------------------------------------------------------
514 // Details: Handle a LLDB SBThread event.
515 // Type:    Method.
516 // Args:    vEvent  - (R) An LLDB broadcast event.
517 // Return:  MIstatus::success - Functionality succeeded.
518 //          MIstatus::failure - Functionality failed.
519 // Throws:  None.
520 //--
521 bool
522 CMICmnLLDBDebuggerHandleEvents::HandleEventSBThreadSuspended(const lldb::SBEvent &vEvent)
523 {
524     lldb::SBThread thread = lldb::SBThread::GetThreadFromEvent(vEvent);
525     if (!thread.IsValid())
526         return MIstatus::success;
527
528     const lldb::StopReason eStopReason = thread.GetStopReason();
529     if (eStopReason != lldb::eStopReasonSignal)
530         return MIstatus::success;
531
532     // MI print "@thread=%d,signal=%lld"
533     const MIuint64 nId = thread.GetStopReasonDataAtIndex(0);
534     const CMIUtilString strThread(CMIUtilString::Format("%d", thread.GetThreadID()));
535     const CMICmnMIValueConst miValueConst(strThread);
536     const CMICmnMIValueResult miValueResult("thread", miValueConst);
537     CMICmnMIOutOfBandRecord miOutOfBandRecord(CMICmnMIOutOfBandRecord::eOutOfBand_Thread, miValueResult);
538     const CMIUtilString strSignal(CMIUtilString::Format("%lld", nId));
539     const CMICmnMIValueConst miValueConst2(strSignal);
540     const CMICmnMIValueResult miValueResult2("signal", miValueConst2);
541     bool bOk = miOutOfBandRecord.Add(miValueResult2);
542     bOk = bOk && MiOutOfBandRecordToStdout(miOutOfBandRecord);
543
544     return bOk;
545 }
546
547 //++ ------------------------------------------------------------------------------------
548 // Details: Handle a LLDB SBThread event.
549 // Type:    Method.
550 // Args:    vEvent  - (R) An LLDB broadcast event.
551 // Return:  MIstatus::success - Functionality succeeded.
552 //          MIstatus::failure - Functionality failed.
553 // Throws:  None.
554 //--
555 bool
556 CMICmnLLDBDebuggerHandleEvents::HandleEventSBThreadBitStackChanged(const lldb::SBEvent &vEvent)
557 {
558     lldb::SBThread thread = lldb::SBThread::GetThreadFromEvent(vEvent);
559     if (!thread.IsValid())
560         return MIstatus::success;
561
562     lldb::SBStream streamOut;
563     const bool bOk = thread.GetStatus(streamOut);
564     return bOk && TextToStdout(streamOut.GetData());
565 }
566
567 //++ ------------------------------------------------------------------------------------
568 // Details: Handle a LLDB SBCommandInterpreter event.
569 // Type:    Method.
570 // Args:    vEvent  - (R) An LLDB command interpreter event.
571 // Return:  MIstatus::success - Functionality succeeded.
572 //          MIstatus::failure - Functionality failed.
573 // Throws:  None.
574 //--
575 bool
576 CMICmnLLDBDebuggerHandleEvents::HandleEventSBCommandInterpreter(const lldb::SBEvent &vEvent)
577 {
578     // This function is not used
579     // *** This function is under development
580
581     const MIchar *pEventType = "";
582     const MIuint nEventType = vEvent.GetType();
583     switch (nEventType)
584     {
585         case lldb::SBCommandInterpreter::eBroadcastBitThreadShouldExit:
586             pEventType = "eBroadcastBitThreadShouldExit";
587         // ToDo: IOR: Reminder to maybe handle this here
588         // const MIuint nEventType = event.GetType();
589         // if (nEventType & lldb::SBCommandInterpreter::eBroadcastBitThreadShouldExit)
590         //{
591         //  m_pClientDriver->SetExitApplicationFlag();
592         //  vrbYesExit = true;
593         //  return MIstatus::success;
594         //}     break;
595         case lldb::SBCommandInterpreter::eBroadcastBitResetPrompt:
596             pEventType = "eBroadcastBitResetPrompt";
597             break;
598         case lldb::SBCommandInterpreter::eBroadcastBitQuitCommandReceived:
599             pEventType = "eBroadcastBitQuitCommandReceived";
600             break;
601         case lldb::SBCommandInterpreter::eBroadcastBitAsynchronousOutputData:
602             pEventType = "eBroadcastBitAsynchronousOutputData";
603             break;
604         case lldb::SBCommandInterpreter::eBroadcastBitAsynchronousErrorData:
605             pEventType = "eBroadcastBitAsynchronousErrorData";
606             break;
607         default:
608         {
609             const CMIUtilString msg(
610                 CMIUtilString::Format(MIRSRC(IDS_LLDBOUTOFBAND_ERR_UNKNOWN_EVENT), "SBCommandInterpreter", (MIuint)nEventType));
611             SetErrorDescription(msg);
612             return MIstatus::failure;
613         }
614     }
615     m_pLog->WriteLog(CMIUtilString::Format("##### An SBCommandInterpreter event occurred: %s", pEventType));
616
617     return MIstatus::success;
618 }
619
620 //++ ------------------------------------------------------------------------------------
621 // Details: Handle SBProcess event eBroadcastBitStateChanged.
622 // Type:    Method.
623 // Args:    vEvent          - (R) An LLDB event object.
624 //          vrbExitAppEvent - (W) True - Received LLDB exit app event, false = did not.
625 // Return:  MIstatus::success - Functionality succeeded.
626 //          MIstatus::failure - Functionality failed.
627 // Throws:  None.
628 //--
629 bool
630 CMICmnLLDBDebuggerHandleEvents::HandleProcessEventBroadcastBitStateChanged(const lldb::SBEvent &vEvent, bool &vrbExitAppEvent)
631 {
632     bool bOk = ChkForStateChanges();
633     bOk = bOk && GetProcessStdout();
634     bOk = bOk && GetProcessStderr();
635     if (!bOk)
636         return MIstatus::failure;
637
638     // Something changed in the process; get the event and report the process's current
639     // status and location
640     const lldb::StateType eEventState = lldb::SBProcess::GetStateFromEvent(vEvent);
641     if (eEventState == lldb::eStateInvalid)
642         return MIstatus::success;
643
644     lldb::SBProcess process = lldb::SBProcess::GetProcessFromEvent(vEvent);
645     if (!process.IsValid())
646     {
647         const CMIUtilString msg(CMIUtilString::Format(MIRSRC(IDS_LLDBOUTOFBAND_ERR_PROCESS_INVALID), "SBProcess",
648                                                       "HandleProcessEventBroadcastBitStateChanged()"));
649         SetErrorDescription(msg);
650         return MIstatus::failure;
651     }
652
653     bool bShouldBrk = true;
654     const MIchar *pEventType = "";
655     switch (eEventState)
656     {
657         case lldb::eStateUnloaded:
658             pEventType = "eStateUnloaded";
659             break;
660         case lldb::eStateConnected:
661             pEventType = "eStateConnected";
662             break;
663         case lldb::eStateAttaching:
664             pEventType = "eStateAttaching";
665             break;
666         case lldb::eStateLaunching:
667             pEventType = "eStateLaunching";
668             break;
669         case lldb::eStateStopped:
670             pEventType = "eStateStopped";
671             bOk = HandleProcessEventStateStopped(bShouldBrk);
672             if (bShouldBrk)
673                 break;
674         case lldb::eStateCrashed:
675         case lldb::eStateSuspended:
676             pEventType = "eStateSuspended";
677             bOk = HandleProcessEventStateSuspended(vEvent);
678             break;
679         case lldb::eStateRunning:
680             pEventType = "eStateRunning";
681             bOk = HandleProcessEventStateRunning();
682             break;
683         case lldb::eStateStepping:
684             pEventType = "eStateStepping";
685             break;
686         case lldb::eStateDetached:
687             pEventType = "eStateDetached";
688             break;
689         case lldb::eStateExited:
690             pEventType = "eStateExited";
691             vrbExitAppEvent = true;
692             bOk = HandleProcessEventStateExited();
693             break;
694         default:
695         {
696             const CMIUtilString msg(CMIUtilString::Format(MIRSRC(IDS_LLDBOUTOFBAND_ERR_UNKNOWN_EVENT), "SBProcess BroadcastBitStateChanged",
697                                                           (MIuint)eEventState));
698             SetErrorDescription(msg);
699             return MIstatus::failure;
700         }
701     }
702
703     // ToDo: Remove when finished coding application
704     m_pLog->WriteLog(CMIUtilString::Format("##### An SB Process event BroadcastBitStateChanged occurred: %s", pEventType));
705
706     return bOk;
707 }
708
709 //++ ------------------------------------------------------------------------------------
710 // Details: Asynchronous event handler for LLDB Process state suspended.
711 // Type:    Method.
712 // Args:    vEvent  - (R) An LLDB event object.
713 // Return:  MIstatus::success - Functionality succeeded.
714 //          MIstatus::failure - Functionality failed.
715 // Throws:  None.
716 //--
717 bool
718 CMICmnLLDBDebuggerHandleEvents::HandleProcessEventStateSuspended(const lldb::SBEvent &vEvent)
719 {
720     // Make sure the program hasn't been auto-restarted:
721     if (lldb::SBProcess::GetRestartedFromEvent(vEvent))
722         return MIstatus::success;
723
724     bool bOk = MIstatus::success;
725     lldb::SBDebugger &rDebugger = CMICmnLLDBDebugSessionInfo::Instance().m_rLldbDebugger;
726     lldb::SBProcess &rProcess = CMICmnLLDBDebugSessionInfo::Instance().m_lldbProcess;
727     lldb::SBTarget target = rProcess.GetTarget();
728     if (rDebugger.GetSelectedTarget() == target)
729     {
730         if (!UpdateSelectedThread())
731             return MIstatus::failure;
732
733         lldb::SBCommandReturnObject result;
734         const lldb::ReturnStatus status = rDebugger.GetCommandInterpreter().HandleCommand("process status", result, false);
735         MIunused(status);
736         bOk = TextToStderr(result.GetError());
737         bOk = bOk && TextToStdout(result.GetOutput());
738     }
739     else
740     {
741         lldb::SBStream streamOut;
742         const MIuint nTargetIndex = rDebugger.GetIndexOfTarget(target);
743         if (nTargetIndex != UINT_MAX)
744             streamOut.Printf("Target %d: (", nTargetIndex);
745         else
746             streamOut.Printf("Target <unknown index>: (");
747         target.GetDescription(streamOut, lldb::eDescriptionLevelBrief);
748         streamOut.Printf(") stopped.\n");
749         bOk = TextToStdout(streamOut.GetData());
750     }
751
752     return bOk;
753 }
754
755 //++ ------------------------------------------------------------------------------------
756 // Details: Print to stdout MI formatted text to indicate process stopped.
757 // Type:    Method.
758 // Args:    vwrbShouldBrk   - (W) True = Yes break, false = do not.
759 // Return:  MIstatus::success - Functionality succeeded.
760 //          MIstatus::failure - Functionality failed.
761 // Throws:  None.
762 //--
763 bool
764 CMICmnLLDBDebuggerHandleEvents::HandleProcessEventStateStopped(bool &vwrbShouldBrk)
765 {
766     if (!UpdateSelectedThread())
767         return MIstatus::failure;
768
769     const MIchar *pEventType = "";
770     bool bOk = MIstatus::success;
771     lldb::SBProcess &rProcess = CMICmnLLDBDebugSessionInfo::Instance().m_lldbProcess;
772     const lldb::StopReason eStoppedReason = rProcess.GetSelectedThread().GetStopReason();
773     switch (eStoppedReason)
774     {
775         case lldb::eStopReasonInvalid:
776             pEventType = "eStopReasonInvalid";
777             vwrbShouldBrk = false;
778             break;
779         case lldb::eStopReasonNone:
780             pEventType = "eStopReasonNone";
781             break;
782         case lldb::eStopReasonTrace:
783             pEventType = "eStopReasonTrace";
784             bOk = HandleProcessEventStopReasonTrace();
785             break;
786         case lldb::eStopReasonBreakpoint:
787             pEventType = "eStopReasonBreakpoint";
788             bOk = HandleProcessEventStopReasonBreakpoint();
789             break;
790         case lldb::eStopReasonWatchpoint:
791             pEventType = "eStopReasonWatchpoint";
792             break;
793         case lldb::eStopReasonSignal:
794             pEventType = "eStopReasonSignal";
795             bOk = HandleProcessEventStopSignal(vwrbShouldBrk);
796             break;
797         case lldb::eStopReasonException:
798             pEventType = "eStopReasonException";
799             break;
800         case lldb::eStopReasonExec:
801             pEventType = "eStopReasonExec";
802             break;
803         case lldb::eStopReasonPlanComplete:
804             pEventType = "eStopReasonPlanComplete";
805             bOk = HandleProcessEventStopReasonTrace();
806             break;
807         case lldb::eStopReasonThreadExiting:
808             pEventType = "eStopReasonThreadExiting";
809             break;
810     }
811
812     // ToDo: Remove when finished coding application
813     m_pLog->WriteLog(CMIUtilString::Format("##### An SB Process event stop state occurred: %s", pEventType));
814
815     return bOk;
816 }
817
818 //++ ------------------------------------------------------------------------------------
819 // Details: Asynchronous event handler for LLDB Process stop signal.
820 // Type:    Method.
821 // Args:    vwrbShouldBrk   - (W) True = Yes break, false = do not.
822 // Return:  MIstatus::success - Functionality succeeded.
823 //          MIstatus::failure - Functionality failed.
824 // Throws:  None.
825 //--
826 bool
827 CMICmnLLDBDebuggerHandleEvents::HandleProcessEventStopSignal(bool &vwrbShouldBrk)
828 {
829     bool bOk = MIstatus::success;
830
831     lldb::SBProcess &rProcess = CMICmnLLDBDebugSessionInfo::Instance().m_lldbProcess;
832     const MIuint64 nStopReason = rProcess.GetSelectedThread().GetStopReasonDataAtIndex(0);
833     switch (nStopReason)
834     {
835         case 2: // Terminal interrupt signal. SIGINT
836         {
837             // MI print "*stopped,reason=\"signal-received\",signal-name=\"SIGNINT\",signal-meaning=\"Interrupt\",frame={%s}"
838             const CMICmnMIValueConst miValueConst("signal-received");
839             const CMICmnMIValueResult miValueResult("reason", miValueConst);
840             CMICmnMIOutOfBandRecord miOutOfBandRecord(CMICmnMIOutOfBandRecord::eOutOfBand_Stopped, miValueResult);
841             const CMICmnMIValueConst miValueConst2("SIGINT");
842             const CMICmnMIValueResult miValueResult2("signal-name", miValueConst2);
843             bOk = miOutOfBandRecord.Add(miValueResult2);
844             const CMICmnMIValueConst miValueConst3("Interrupt");
845             const CMICmnMIValueResult miValueResult3("signal-meaning", miValueConst3);
846             bOk = bOk && miOutOfBandRecord.Add(miValueResult3);
847             CMICmnMIValueTuple miValueTuple;
848             bOk = bOk && MiHelpGetCurrentThreadFrame(miValueTuple);
849             const CMICmnMIValueResult miValueResult5("frame", miValueTuple);
850             bOk = bOk && miOutOfBandRecord.Add(miValueResult5);
851             bOk = bOk && MiOutOfBandRecordToStdout(miOutOfBandRecord);
852             bOk = bOk && TextToStdout("(gdb)");
853         }
854         break;
855         case 11: // Invalid memory reference. SIGSEGV
856         {
857             // MI print "*stopped,reason=\"signal-received\",signal-name=\"SIGSEGV\",signal-meaning=\"Segmentation
858             // fault\",thread-id=\"%d\",frame={%s}"
859             const CMICmnMIValueConst miValueConst("signal-received");
860             const CMICmnMIValueResult miValueResult("reason", miValueConst);
861             CMICmnMIOutOfBandRecord miOutOfBandRecord(CMICmnMIOutOfBandRecord::eOutOfBand_Stopped, miValueResult);
862             const CMICmnMIValueConst miValueConst2("SIGSEGV");
863             const CMICmnMIValueResult miValueResult2("signal-name", miValueConst2);
864             bOk = miOutOfBandRecord.Add(miValueResult2);
865             const CMICmnMIValueConst miValueConst3("Segmentation fault");
866             const CMICmnMIValueResult miValueResult3("signal-meaning", miValueConst3);
867             bOk = bOk && miOutOfBandRecord.Add(miValueResult3);
868             const CMIUtilString strThreadId(CMIUtilString::Format("%d", rProcess.GetSelectedThread().GetIndexID()));
869             const CMICmnMIValueConst miValueConst4(strThreadId);
870             const CMICmnMIValueResult miValueResult4("thread-id", miValueConst4);
871             bOk = bOk && miOutOfBandRecord.Add(miValueResult4);
872             CMICmnMIValueTuple miValueTuple;
873             bOk = bOk && MiHelpGetCurrentThreadFrame(miValueTuple);
874             const CMICmnMIValueResult miValueResult5("frame", miValueTuple);
875             bOk = bOk && miOutOfBandRecord.Add(miValueResult5);
876             bOk = bOk && MiOutOfBandRecordToStdout(miOutOfBandRecord);
877             // Note no "(gdb)" output here
878         }
879         break;
880         case 19:
881             if (rProcess.IsValid())
882                 rProcess.Continue();
883             break;
884         case 5: //  Trace/breakpoint trap. SIGTRAP
885         {
886             lldb::SBThread thread = rProcess.GetSelectedThread();
887             const MIuint nFrames = thread.GetNumFrames();
888             if (nFrames > 0)
889             {
890                 lldb::SBFrame frame = thread.GetFrameAtIndex(0);
891                 const char *pFnName = frame.GetFunctionName();
892                 if (pFnName != nullptr)
893                 {
894                     const CMIUtilString fnName = CMIUtilString(pFnName);
895                     static const CMIUtilString threadCloneFn = CMIUtilString("__pthread_clone");
896
897                     if (CMIUtilString::Compare(threadCloneFn, fnName))
898                     {
899                         if (rProcess.IsValid())
900                         {
901                             rProcess.Continue();
902                             vwrbShouldBrk = true;
903                             break;
904                         }
905                     }
906                 }
907             }
908         }
909         default:
910         {
911             // MI print "*stopped,reason=\"signal-received\",signal=\"%lld\",stopped-threads=\"all\""
912             const CMICmnMIValueConst miValueConst("signal-received");
913             const CMICmnMIValueResult miValueResult("reason", miValueConst);
914             CMICmnMIOutOfBandRecord miOutOfBandRecord(CMICmnMIOutOfBandRecord::eOutOfBand_Stopped, miValueResult);
915             const CMIUtilString strReason(CMIUtilString::Format("%lld", nStopReason));
916             const CMICmnMIValueConst miValueConst2(strReason);
917             const CMICmnMIValueResult miValueResult2("signal", miValueConst2);
918             bOk = miOutOfBandRecord.Add(miValueResult2);
919             const CMICmnMIValueConst miValueConst3("all");
920             const CMICmnMIValueResult miValueResult3("stopped-threads", miValueConst3);
921             bOk = bOk && miOutOfBandRecord.Add(miValueResult3);
922             bOk = bOk && MiOutOfBandRecordToStdout(miOutOfBandRecord);
923             bOk = bOk && TextToStdout("(gdb)");
924         }
925     } // switch( nStopReason )
926
927     return bOk;
928 }
929
930 //++ ------------------------------------------------------------------------------------
931 // Details: Form partial MI response in a MI value tuple object.
932 // Type:    Method.
933 // Args:    vwrMiValueTuple   - (W) MI value tuple object.
934 // Return:  MIstatus::success - Functionality succeeded.
935 //          MIstatus::failure - Functionality failed.
936 // Throws:  None.
937 //--
938 bool
939 CMICmnLLDBDebuggerHandleEvents::MiHelpGetCurrentThreadFrame(CMICmnMIValueTuple &vwrMiValueTuple)
940 {
941     CMIUtilString strThreadFrame;
942     lldb::SBProcess &rProcess = CMICmnLLDBDebugSessionInfo::Instance().m_lldbProcess;
943     lldb::SBThread thread = rProcess.GetSelectedThread();
944     const MIuint nFrame = thread.GetNumFrames();
945     if (nFrame == 0)
946     {
947         // MI print "addr=\"??\",func=\"??\",file=\"??\",fullname=\"??\",line=\"??\""
948         const CMICmnMIValueConst miValueConst("??");
949         const CMICmnMIValueResult miValueResult("addr", miValueConst);
950         CMICmnMIValueTuple miValueTuple(miValueResult);
951         const CMICmnMIValueResult miValueResult2("func", miValueConst);
952         miValueTuple.Add(miValueResult2);
953         const CMICmnMIValueResult miValueResult4("file", miValueConst);
954         miValueTuple.Add(miValueResult4);
955         const CMICmnMIValueResult miValueResult5("fullname", miValueConst);
956         miValueTuple.Add(miValueResult5);
957         const CMICmnMIValueResult miValueResult6("line", miValueConst);
958         miValueTuple.Add(miValueResult6);
959
960         vwrMiValueTuple = miValueTuple;
961
962         return MIstatus::success;
963     }
964
965     CMICmnMIValueTuple miValueTuple;
966     if (!CMICmnLLDBDebugSessionInfo::Instance().MIResponseFormFrameInfo(thread, 0, miValueTuple))
967     {
968         SetErrorDescription(CMIUtilString::Format(MIRSRC(IDS_LLDBOUTOFBAND_ERR_FORM_MI_RESPONSE), "MiHelpGetCurrentThreadFrame()"));
969         return MIstatus::failure;
970     }
971
972     vwrMiValueTuple = miValueTuple;
973
974     return MIstatus::success;
975 }
976
977 //++ ------------------------------------------------------------------------------------
978 // Details: Asynchronous event handler for LLDB Process stop reason breakpoint.
979 // Type:    Method.
980 // Args:    None.
981 // Return:  MIstatus::success - Functionality succeeded.
982 //          MIstatus::failure - Functionality failed.
983 // Throws:  None.
984 //--
985 bool
986 CMICmnLLDBDebuggerHandleEvents::HandleProcessEventStopReasonBreakpoint(void)
987 {
988     // CODETAG_DEBUG_SESSION_RUNNING_PROG_RECEIVED_SIGINT_PAUSE_PROGRAM
989     if (!CMIDriver::Instance().SetDriverStateRunningNotDebugging())
990     {
991         const CMIUtilString &rErrMsg(CMIDriver::Instance().GetErrorDescription());
992         SetErrorDescription(CMIUtilString::Format(MIRSRC(IDS_LLDBOUTOFBAND_ERR_SETNEWDRIVERSTATE),
993                                                   "HandleProcessEventStopReasonBreakpoint()", rErrMsg.c_str()));
994         return MIstatus::failure;
995     }
996
997     lldb::SBProcess &rProcess = CMICmnLLDBDebugSessionInfo::Instance().m_lldbProcess;
998     const MIuint64 brkPtId = rProcess.GetSelectedThread().GetStopReasonDataAtIndex(0);
999     lldb::SBBreakpoint brkPt = CMICmnLLDBDebugSessionInfo::Instance().m_lldbTarget.GetBreakpointAtIndex((MIuint)brkPtId);
1000
1001     return MiStoppedAtBreakPoint(brkPtId, brkPt);
1002 }
1003
1004 //++ ------------------------------------------------------------------------------------
1005 // Details: Form the MI Out-of-band response for stopped reason on hitting a break point.
1006 // Type:    Method.
1007 // Args:    vBrkPtId    - (R) The LLDB break point's ID
1008 //          vBrkPt      - (R) THe LLDB break point object.
1009 // Return:  MIstatus::success - Functionality succeeded.
1010 //          MIstatus::failure - Functionality failed.
1011 // Throws:  None.
1012 //--
1013 bool
1014 CMICmnLLDBDebuggerHandleEvents::MiStoppedAtBreakPoint(const MIuint64 vBrkPtId, const lldb::SBBreakpoint &vBrkPt)
1015 {
1016     bool bOk = MIstatus::success;
1017
1018     lldb::SBProcess &rProcess = CMICmnLLDBDebugSessionInfo::Instance().m_lldbProcess;
1019     lldb::SBThread thread = rProcess.GetSelectedThread();
1020     const MIuint nFrame = thread.GetNumFrames();
1021     if (nFrame == 0)
1022     {
1023         // MI print "*stopped,reason=\"breakpoint-hit\",disp=\"del\",bkptno=\"%d\",frame={},thread-id=\"%d\",stopped-threads=\"all\""
1024         const CMICmnMIValueConst miValueConst("breakpoint-hit");
1025         const CMICmnMIValueResult miValueResult("reason", miValueConst);
1026         CMICmnMIOutOfBandRecord miOutOfBandRecord(CMICmnMIOutOfBandRecord::eOutOfBand_Stopped, miValueResult);
1027         const CMICmnMIValueConst miValueConst2("del");
1028         const CMICmnMIValueResult miValueResult2("disp", miValueConst2);
1029         bOk = miOutOfBandRecord.Add(miValueResult2);
1030         const CMIUtilString strBkp(CMIUtilString::Format("%d", vBrkPtId));
1031         const CMICmnMIValueConst miValueConst3(strBkp);
1032         CMICmnMIValueResult miValueResult3("bkptno", miValueConst3);
1033         bOk = bOk && miOutOfBandRecord.Add(miValueResult3);
1034         const CMICmnMIValueConst miValueConst4("{}");
1035         const CMICmnMIValueResult miValueResult4("frame", miValueConst4);
1036         bOk = bOk && miOutOfBandRecord.Add(miValueResult4);
1037         const CMIUtilString strThreadId(CMIUtilString::Format("%d", vBrkPt.GetThreadIndex()));
1038         const CMICmnMIValueConst miValueConst5(strThreadId);
1039         const CMICmnMIValueResult miValueResult5("thread-id", miValueConst5);
1040         bOk = bOk && miOutOfBandRecord.Add(miValueResult5);
1041         const CMICmnMIValueConst miValueConst6("all");
1042         const CMICmnMIValueResult miValueResult6("stopped-threads", miValueConst6);
1043         bOk = bOk && miOutOfBandRecord.Add(miValueResult6);
1044         bOk = bOk && MiOutOfBandRecordToStdout(miOutOfBandRecord);
1045         bOk = bOk && TextToStdout("(gdb)");
1046         return bOk;
1047     }
1048
1049     CMICmnLLDBDebugSessionInfo &rSession = CMICmnLLDBDebugSessionInfo::Instance();
1050
1051     lldb::SBFrame frame = thread.GetFrameAtIndex(0);
1052     lldb::addr_t pc = 0;
1053     CMIUtilString fnName;
1054     CMIUtilString fileName;
1055     CMIUtilString path;
1056     MIuint nLine = 0;
1057     if (!rSession.GetFrameInfo(frame, pc, fnName, fileName, path, nLine))
1058     {
1059         SetErrorDescription(CMIUtilString::Format(MIRSRC(IDS_LLDBOUTOFBAND_ERR_FRAME_INFO_GET), "MiStoppedAtBreakPoint()"));
1060         return MIstatus::failure;
1061     }
1062
1063     // MI print
1064     // "*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\""
1065     const CMICmnMIValueConst miValueConst("breakpoint-hit");
1066     const CMICmnMIValueResult miValueResult("reason", miValueConst);
1067     CMICmnMIOutOfBandRecord miOutOfBandRecord(CMICmnMIOutOfBandRecord::eOutOfBand_Stopped, miValueResult);
1068     const CMICmnMIValueConst miValueConstA("del");
1069     const CMICmnMIValueResult miValueResultA("disp", miValueConstA);
1070     bOk = miOutOfBandRecord.Add(miValueResultA);
1071     const CMIUtilString strBkp(CMIUtilString::Format("%d", vBrkPtId));
1072     const CMICmnMIValueConst miValueConstB(strBkp);
1073     CMICmnMIValueResult miValueResultB("bkptno", miValueConstB);
1074     bOk = bOk && miOutOfBandRecord.Add(miValueResultB);
1075
1076     // frame={addr=\"0x%08x\",func=\"%s\",args=[],file=\"%s\",fullname=\"%s\",line=\"%d\"}
1077     if (bOk)
1078     {
1079         CMICmnMIValueList miValueList(true);
1080         const MIuint maskVarTypes = CMICmnLLDBDebugSessionInfo::eVariableType_Arguments;
1081         bOk = rSession.MIResponseFormVariableInfo2(frame, maskVarTypes, miValueList);
1082
1083         CMICmnMIValueTuple miValueTuple;
1084         bOk = bOk && rSession.MIResponseFormFrameInfo2(pc, miValueList.GetString(), fnName, fileName, path, nLine, miValueTuple);
1085         const CMICmnMIValueResult miValueResult8("frame", miValueTuple);
1086         bOk = bOk && miOutOfBandRecord.Add(miValueResult8);
1087     }
1088
1089     // Add to MI thread-id=\"%d\",stopped-threads=\"all\"
1090     if (bOk)
1091     {
1092         const CMIUtilString strThreadId(CMIUtilString::Format("%d", thread.GetIndexID()));
1093         const CMICmnMIValueConst miValueConst8(strThreadId);
1094         const CMICmnMIValueResult miValueResult8("thread-id", miValueConst8);
1095         bOk = miOutOfBandRecord.Add(miValueResult8);
1096     }
1097     if (bOk)
1098     {
1099         const CMICmnMIValueConst miValueConst9("all");
1100         const CMICmnMIValueResult miValueResult9("stopped-threads", miValueConst9);
1101         bOk = miOutOfBandRecord.Add(miValueResult9);
1102         bOk = MiOutOfBandRecordToStdout(miOutOfBandRecord);
1103         bOk = bOk && TextToStdout("(gdb)");
1104     }
1105
1106     return MIstatus::success;
1107 }
1108
1109 //++ ------------------------------------------------------------------------------------
1110 // Details: Asynchronous event handler for LLDB Process stop reason trace.
1111 // Type:    Method.
1112 // Args:    None.
1113 // Return:  MIstatus::success - Functionality succeeded.
1114 //          MIstatus::failure - Functionality failed.
1115 // Throws:  None.
1116 //--
1117 bool
1118 CMICmnLLDBDebuggerHandleEvents::HandleProcessEventStopReasonTrace(void)
1119 {
1120     bool bOk = true;
1121     lldb::SBProcess &rProcess = CMICmnLLDBDebugSessionInfo::Instance().m_lldbProcess;
1122     lldb::SBThread thread = rProcess.GetSelectedThread();
1123     const MIuint nFrame = thread.GetNumFrames();
1124     if (nFrame == 0)
1125     {
1126         // MI print "*stopped,reason=\"trace\",stopped-threads=\"all\""
1127         const CMICmnMIValueConst miValueConst("trace");
1128         const CMICmnMIValueResult miValueResult("reason", miValueConst);
1129         CMICmnMIOutOfBandRecord miOutOfBandRecord(CMICmnMIOutOfBandRecord::eOutOfBand_Stopped, miValueResult);
1130         const CMICmnMIValueConst miValueConst2("all");
1131         const CMICmnMIValueResult miValueResult2("stopped-threads", miValueConst2);
1132         bOk = miOutOfBandRecord.Add(miValueResult2);
1133         bOk = MiOutOfBandRecordToStdout(miOutOfBandRecord);
1134         bOk = bOk && TextToStdout("(gdb)");
1135         return bOk;
1136     }
1137
1138     CMICmnLLDBDebugSessionInfo &rSession = CMICmnLLDBDebugSessionInfo::Instance();
1139
1140     // MI print
1141     // "*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\""
1142     lldb::SBFrame frame = thread.GetFrameAtIndex(0);
1143     lldb::addr_t pc = 0;
1144     CMIUtilString fnName;
1145     CMIUtilString fileName;
1146     CMIUtilString path;
1147     MIuint nLine = 0;
1148     if (!rSession.GetFrameInfo(frame, pc, fnName, fileName, path, nLine))
1149     {
1150         SetErrorDescription(CMIUtilString::Format(MIRSRC(IDS_LLDBOUTOFBAND_ERR_FRAME_INFO_GET), "HandleProcessEventStopReasonTrace()"));
1151         return MIstatus::failure;
1152     }
1153
1154     // Function args
1155     CMICmnMIValueList miValueList(true);
1156     const MIuint maskVarTypes = CMICmnLLDBDebugSessionInfo::eVariableType_Arguments;
1157     if (!rSession.MIResponseFormVariableInfo2(frame, maskVarTypes, miValueList))
1158         return MIstatus::failure;
1159     CMICmnMIValueTuple miValueTuple;
1160     if (!rSession.MIResponseFormFrameInfo2(pc, miValueList.GetString(), fnName, fileName, path, nLine, miValueTuple))
1161         return MIstatus::failure;
1162
1163     const CMICmnMIValueConst miValueConst("end-stepping-range");
1164     const CMICmnMIValueResult miValueResult("reason", miValueConst);
1165     CMICmnMIOutOfBandRecord miOutOfBandRecord(CMICmnMIOutOfBandRecord::eOutOfBand_Stopped, miValueResult);
1166     const CMICmnMIValueResult miValueResult2("frame", miValueTuple);
1167     bOk = miOutOfBandRecord.Add(miValueResult2);
1168
1169     // Add to MI thread-id=\"%d\",stopped-threads=\"all\"
1170     if (bOk)
1171     {
1172         const CMIUtilString strThreadId(CMIUtilString::Format("%d", thread.GetIndexID()));
1173         const CMICmnMIValueConst miValueConst8(strThreadId);
1174         const CMICmnMIValueResult miValueResult8("thread-id", miValueConst8);
1175         bOk = miOutOfBandRecord.Add(miValueResult8);
1176     }
1177     if (bOk)
1178     {
1179         const CMICmnMIValueConst miValueConst9("all");
1180         const CMICmnMIValueResult miValueResult9("stopped-threads", miValueConst9);
1181         bOk = miOutOfBandRecord.Add(miValueResult9);
1182         bOk = MiOutOfBandRecordToStdout(miOutOfBandRecord);
1183         bOk = bOk && TextToStdout("(gdb)");
1184     }
1185
1186     return bOk;
1187 }
1188
1189 //++ ------------------------------------------------------------------------------------
1190 // Details: Asynchronous function update selected thread.
1191 // Type:    Method.
1192 // Args:    None.
1193 // Return:  MIstatus::success - Functionality succeeded.
1194 //          MIstatus::failure - Functionality failed.
1195 // Throws:  None.
1196 //--
1197 bool
1198 CMICmnLLDBDebuggerHandleEvents::UpdateSelectedThread(void)
1199 {
1200     lldb::SBProcess process = CMICmnLLDBDebugSessionInfo::Instance().m_rLldbDebugger.GetSelectedTarget().GetProcess();
1201     if (!process.IsValid())
1202         return MIstatus::success;
1203
1204     lldb::SBThread currentThread = process.GetSelectedThread();
1205     lldb::SBThread thread;
1206     const lldb::StopReason eCurrentThreadStoppedReason = currentThread.GetStopReason();
1207     if (!currentThread.IsValid() || (eCurrentThreadStoppedReason == lldb::eStopReasonInvalid) ||
1208         (eCurrentThreadStoppedReason == lldb::eStopReasonNone))
1209     {
1210         // Prefer a thread that has just completed its plan over another thread as current thread
1211         lldb::SBThread planThread;
1212         lldb::SBThread otherThread;
1213         const size_t nThread = process.GetNumThreads();
1214         for (MIuint i = 0; i < nThread; i++)
1215         {
1216             //  GetThreadAtIndex() uses a base 0 index
1217             //  GetThreadByIndexID() uses a base 1 index
1218             thread = process.GetThreadAtIndex(i);
1219             const lldb::StopReason eThreadStopReason = thread.GetStopReason();
1220             switch (eThreadStopReason)
1221             {
1222                 case lldb::eStopReasonTrace:
1223                 case lldb::eStopReasonBreakpoint:
1224                 case lldb::eStopReasonWatchpoint:
1225                 case lldb::eStopReasonSignal:
1226                 case lldb::eStopReasonException:
1227                     if (!otherThread.IsValid())
1228                         otherThread = thread;
1229                     break;
1230                 case lldb::eStopReasonPlanComplete:
1231                     if (!planThread.IsValid())
1232                         planThread = thread;
1233                     break;
1234                 case lldb::eStopReasonInvalid:
1235                 case lldb::eStopReasonNone:
1236                 default:
1237                     break;
1238             }
1239         }
1240         if (planThread.IsValid())
1241             process.SetSelectedThread(planThread);
1242         else if (otherThread.IsValid())
1243             process.SetSelectedThread(otherThread);
1244         else
1245         {
1246             if (currentThread.IsValid())
1247                 thread = currentThread;
1248             else
1249                 thread = process.GetThreadAtIndex(0);
1250
1251             if (thread.IsValid())
1252                 process.SetSelectedThread(thread);
1253         }
1254     } // if( !currentThread.IsValid() || (eCurrentThreadStoppedReason == lldb::eStopReasonInvalid) || (eCurrentThreadStoppedReason ==
1255       // lldb::eStopReasonNone) )
1256
1257     return MIstatus::success;
1258 }
1259
1260 //++ ------------------------------------------------------------------------------------
1261 // Details: Print to stdout "*running,thread-id=\"all\"", "(gdb)".
1262 // Type:    Method.
1263 // Args:    None.
1264 // Return:  MIstatus::success - Functionality succeeded.
1265 //          MIstatus::failure - Functionality failed.
1266 // Throws:  None.
1267 //--
1268 bool
1269 CMICmnLLDBDebuggerHandleEvents::HandleProcessEventStateRunning(void)
1270 {
1271     CMICmnMIValueConst miValueConst("all");
1272     CMICmnMIValueResult miValueResult("thread-id", miValueConst);
1273     CMICmnMIOutOfBandRecord miOutOfBandRecord(CMICmnMIOutOfBandRecord::eOutOfBand_Running, miValueResult);
1274     bool bOk = MiOutOfBandRecordToStdout(miOutOfBandRecord);
1275     bOk = bOk && TextToStdout("(gdb)");
1276
1277     return bOk;
1278 }
1279
1280 //++ ------------------------------------------------------------------------------------
1281 // Details: Print to stdout "=thread-exited,id=\"%ld\",group-id=\"i1\"",
1282 //                          "=thread-group-exited,id=\"i1\",exit-code=\"0\""),
1283 //                          "*stopped,reason=\"exited-normally\"",
1284 //                          "(gdb)"
1285 // Type:    Method.
1286 // Args:    None.
1287 // Return:  MIstatus::success - Functionality succeeded.
1288 //          MIstatus::failure - Functionality failed.
1289 // Throws:  None.
1290 //--
1291 bool
1292 CMICmnLLDBDebuggerHandleEvents::HandleProcessEventStateExited(void)
1293 {
1294     const CMIUtilString strId(CMIUtilString::Format("%ld", 1));
1295     CMICmnMIValueConst miValueConst(strId);
1296     CMICmnMIValueResult miValueResult("id", miValueConst);
1297     CMICmnMIOutOfBandRecord miOutOfBandRecord(CMICmnMIOutOfBandRecord::eOutOfBand_ThreadExited, miValueResult);
1298     CMICmnMIValueConst miValueConst2("i1");
1299     CMICmnMIValueResult miValueResult2("group-id", miValueConst2);
1300     bool bOk = miOutOfBandRecord.Add(miValueResult2);
1301     bOk = bOk && MiOutOfBandRecordToStdout(miOutOfBandRecord);
1302     if (bOk)
1303     {
1304         CMICmnMIValueConst miValueConst3("i1");
1305         CMICmnMIValueResult miValueResult3("id", miValueConst3);
1306         CMICmnMIOutOfBandRecord miOutOfBandRecord2(CMICmnMIOutOfBandRecord::eOutOfBand_ThreadGroupExited, miValueResult3);
1307         CMICmnMIValueConst miValueConst2("0");
1308         CMICmnMIValueResult miValueResult2("exit-code", miValueConst2);
1309         bOk = miOutOfBandRecord2.Add(miValueResult2);
1310         bOk = bOk && MiOutOfBandRecordToStdout(miOutOfBandRecord2);
1311     }
1312     if (bOk)
1313     {
1314         CMICmnMIValueConst miValueConst4("exited-normally");
1315         CMICmnMIValueResult miValueResult4("reason", miValueConst4);
1316         CMICmnMIOutOfBandRecord miOutOfBandRecord3(CMICmnMIOutOfBandRecord::eOutOfBand_Stopped, miValueResult4);
1317         bOk = MiOutOfBandRecordToStdout(miOutOfBandRecord3);
1318     }
1319     bOk = bOk && TextToStdout("(gdb)");
1320
1321     return bOk;
1322 }
1323
1324 //++ ------------------------------------------------------------------------------------
1325 // Details: Drain all stdout so we don't see any output come after we print our prompts.
1326 //          The process has stuff waiting for stdout; get it and write it out to the
1327 //          appropriate place.
1328 // Type:    Method.
1329 // Args:    None.
1330 // Return:  MIstatus::success - Functionality succeeded.
1331 //          MIstatus::failure - Functionality failed.
1332 // Throws:  None.
1333 //--
1334 bool
1335 CMICmnLLDBDebuggerHandleEvents::GetProcessStdout(void)
1336 {
1337     bool bOk = MIstatus::success;
1338
1339     char c;
1340     size_t nBytes = 0;
1341     CMIUtilString text;
1342     lldb::SBProcess process = CMICmnLLDBDebugSessionInfo::Instance().m_rLldbDebugger.GetSelectedTarget().GetProcess();
1343     while (process.GetSTDOUT(&c, 1) > 0)
1344     {
1345         CMIUtilString str;
1346         if (ConvertPrintfCtrlCodeToString(c, str))
1347             text += str;
1348         nBytes++;
1349     }
1350     if (nBytes > 0)
1351     {
1352         const CMIUtilString t(CMIUtilString::Format("~\"%s\"", text.c_str()));
1353         bOk = TextToStdout(t);
1354     }
1355
1356     return bOk;
1357 }
1358
1359 //++ ------------------------------------------------------------------------------------
1360 // Details: Drain all stderr so we don't see any output come after we print our prompts.
1361 //          The process has stuff waiting for stderr; get it and write it out to the
1362 //          appropriate place.
1363 // Type:    Method.
1364 // Args:    None.
1365 // Return:  MIstatus::success - Functionality succeeded.
1366 //          MIstatus::failure - Functionality failed.
1367 // Throws:  None.
1368 //--
1369 bool
1370 CMICmnLLDBDebuggerHandleEvents::GetProcessStderr(void)
1371 {
1372     bool bOk = MIstatus::success;
1373
1374     char c;
1375     size_t nBytes = 0;
1376     CMIUtilString text;
1377     lldb::SBProcess process = CMICmnLLDBDebugSessionInfo::Instance().m_rLldbDebugger.GetSelectedTarget().GetProcess();
1378     while (process.GetSTDERR(&c, 1) > 0)
1379     {
1380         CMIUtilString str;
1381         if (ConvertPrintfCtrlCodeToString(c, str))
1382             text += str;
1383         nBytes++;
1384     }
1385     if (nBytes > 0)
1386     {
1387         const CMIUtilString t(CMIUtilString::Format("~\"%s\"", text.c_str()));
1388         bOk = TextToStdout(t);
1389     }
1390
1391     return bOk;
1392 }
1393
1394 //++ ------------------------------------------------------------------------------------
1395 // Details: Convert text stream control codes to text equivalent.
1396 // Type:    Method.
1397 // Args:    vCtrl             - (R) The control code.
1398 //          vwrStrEquivalent  - (W) The text equivalent.
1399 // Return:  MIstatus::success - Functionality succeeded.
1400 //          MIstatus::failure - Functionality failed.
1401 // Throws:  None.
1402 //--
1403 bool
1404 CMICmnLLDBDebuggerHandleEvents::ConvertPrintfCtrlCodeToString(const MIchar vCtrl, CMIUtilString &vwrStrEquivalent)
1405 {
1406     switch (vCtrl)
1407     {
1408         case '\033':
1409             vwrStrEquivalent = "\\e";
1410             break;
1411         case '\a':
1412             vwrStrEquivalent = "\\a";
1413             break;
1414         case '\b':
1415             vwrStrEquivalent = "\\b";
1416             break;
1417         case '\f':
1418             vwrStrEquivalent = "\\f";
1419             break;
1420         case '\n':
1421             vwrStrEquivalent = "\\n";
1422             break;
1423         case '\r':
1424             vwrStrEquivalent = "\\r";
1425             break;
1426         case '\t':
1427             vwrStrEquivalent = "\\t";
1428             break;
1429         case '\v':
1430             vwrStrEquivalent = "\\v";
1431             break;
1432         default:
1433             vwrStrEquivalent = CMIUtilString::Format("%c", vCtrl);
1434             break;
1435     }
1436
1437     return MIstatus::success;
1438 }
1439
1440 //++ ------------------------------------------------------------------------------------
1441 // Details: Asynchronous event function check for state changes.
1442 // Type:    Method.
1443 // Args:    None.
1444 // Return:  MIstatus::success - Functionality succeeded.
1445 //          MIstatus::failure - Functionality failed.
1446 // Throws:  None.
1447 //--
1448 bool
1449 CMICmnLLDBDebuggerHandleEvents::ChkForStateChanges(void)
1450 {
1451     lldb::SBProcess &rProcess = CMICmnLLDBDebugSessionInfo::Instance().m_lldbProcess;
1452     if (!rProcess.IsValid())
1453         return MIstatus::success;
1454     lldb::SBTarget &rTarget = CMICmnLLDBDebugSessionInfo::Instance().m_lldbTarget;
1455     if (!rTarget.IsValid())
1456         return MIstatus::success;
1457
1458     bool bOk = MIstatus::success;
1459
1460     // Check for created threads
1461     const MIuint nThread = rProcess.GetNumThreads();
1462     for (MIuint i = 0; i < nThread; i++)
1463     {
1464         //  GetThreadAtIndex() uses a base 0 index
1465         //  GetThreadByIndexID() uses a base 1 index
1466         lldb::SBThread thread = rProcess.GetThreadAtIndex(i);
1467         if (!thread.IsValid())
1468             continue;
1469
1470         CMICmnLLDBDebugSessionInfo::VecActiveThreadId_t::const_iterator it =
1471             CMICmnLLDBDebugSessionInfo::Instance().m_vecActiveThreadId.begin();
1472         bool bFound = false;
1473         while (it != CMICmnLLDBDebugSessionInfo::Instance().m_vecActiveThreadId.end())
1474         {
1475             const MIuint nThreadId = *it;
1476             if (nThreadId == i)
1477             {
1478                 bFound = true;
1479                 break;
1480             }
1481
1482             // Next
1483             ++it;
1484         }
1485         if (!bFound)
1486         {
1487             CMICmnLLDBDebugSessionInfo::Instance().m_vecActiveThreadId.push_back(i);
1488
1489             // Form MI "=thread-created,id=\"%d\",group-id=\"i1\""
1490             const CMIUtilString strValue(CMIUtilString::Format("%d", thread.GetIndexID()));
1491             const CMICmnMIValueConst miValueConst(strValue);
1492             const CMICmnMIValueResult miValueResult("id", miValueConst);
1493             CMICmnMIOutOfBandRecord miOutOfBand(CMICmnMIOutOfBandRecord::eOutOfBand_ThreadCreated, miValueResult);
1494             const CMICmnMIValueConst miValueConst2("i1");
1495             const CMICmnMIValueResult miValueResult2("group-id", miValueConst2);
1496             bOk = miOutOfBand.Add(miValueResult2);
1497             bOk = bOk && MiOutOfBandRecordToStdout(miOutOfBand);
1498             if (!bOk)
1499                 return MIstatus::failure;
1500         }
1501     }
1502
1503     lldb::SBThread currentThread = rProcess.GetSelectedThread();
1504     if (currentThread.IsValid())
1505     {
1506         const MIuint threadId = currentThread.GetIndexID();
1507         if (CMICmnLLDBDebugSessionInfo::Instance().m_currentSelectedThread != threadId)
1508         {
1509             CMICmnLLDBDebugSessionInfo::Instance().m_currentSelectedThread = threadId;
1510
1511             // Form MI "=thread-selected,id=\"%d\""
1512             const CMIUtilString strValue(CMIUtilString::Format("%d", currentThread.GetIndexID()));
1513             const CMICmnMIValueConst miValueConst(strValue);
1514             const CMICmnMIValueResult miValueResult("id", miValueConst);
1515             CMICmnMIOutOfBandRecord miOutOfBand(CMICmnMIOutOfBandRecord::eOutOfBand_ThreadSelected, miValueResult);
1516             if (!MiOutOfBandRecordToStdout(miOutOfBand))
1517                 return MIstatus::failure;
1518         }
1519     }
1520
1521     // Check for invalid (removed) threads
1522     CMICmnLLDBDebugSessionInfo::VecActiveThreadId_t::const_iterator it = CMICmnLLDBDebugSessionInfo::Instance().m_vecActiveThreadId.begin();
1523     while (it != CMICmnLLDBDebugSessionInfo::Instance().m_vecActiveThreadId.end())
1524     {
1525         const MIuint nThreadId = *it;
1526         lldb::SBThread thread = rProcess.GetThreadAtIndex(nThreadId);
1527         if (!thread.IsValid())
1528         {
1529             // Form MI "=thread-exited,id=\"%ld\",group-id=\"i1\""
1530             const CMIUtilString strValue(CMIUtilString::Format("%ld", thread.GetIndexID()));
1531             const CMICmnMIValueConst miValueConst(strValue);
1532             const CMICmnMIValueResult miValueResult("id", miValueConst);
1533             CMICmnMIOutOfBandRecord miOutOfBand(CMICmnMIOutOfBandRecord::eOutOfBand_ThreadExited, miValueResult);
1534             const CMICmnMIValueConst miValueConst2("i1");
1535             const CMICmnMIValueResult miValueResult2("group-id", miValueConst2);
1536             bOk = miOutOfBand.Add(miValueResult2);
1537             bOk = bOk && MiOutOfBandRecordToStdout(miOutOfBand);
1538             if (!bOk)
1539                 return MIstatus::failure;
1540         }
1541
1542         // Next
1543         ++it;
1544     }
1545
1546     return TextToStdout("(gdb)");
1547 }
1548
1549 //++ ------------------------------------------------------------------------------------
1550 // Details: Take a fully formed MI result record and send to the stdout stream.
1551 //          Also output to the MI Log file.
1552 // Type:    Method.
1553 // Args:    vrMiResultRecord  - (R) MI result record object.
1554 // Return:  MIstatus::success - Functionality succeeded.
1555 //          MIstatus::failure - Functionality failed.
1556 // Throws:  None.
1557 //--
1558 bool
1559 CMICmnLLDBDebuggerHandleEvents::MiResultRecordToStdout(const CMICmnMIResultRecord &vrMiResultRecord)
1560 {
1561     return TextToStdout(vrMiResultRecord.GetString());
1562 }
1563
1564 //++ ------------------------------------------------------------------------------------
1565 // Details: Take a fully formed MI Out-of-band record and send to the stdout stream.
1566 //          Also output to the MI Log file.
1567 // Type:    Method.
1568 // Args:    vrMiOutOfBandRecord - (R) MI Out-of-band record object.
1569 // Return:  MIstatus::success - Functionality succeeded.
1570 //          MIstatus::failure - Functionality failed.
1571 // Throws:  None.
1572 //--
1573 bool
1574 CMICmnLLDBDebuggerHandleEvents::MiOutOfBandRecordToStdout(const CMICmnMIOutOfBandRecord &vrMiOutOfBandRecord)
1575 {
1576     return TextToStdout(vrMiOutOfBandRecord.GetString());
1577 }
1578
1579 //++ ------------------------------------------------------------------------------------
1580 // Details: Take a text data and send to the stdout stream. Also output to the MI Log
1581 //          file.
1582 // Type:    Method.
1583 // Args:    vrTxt   - (R) Text.
1584 // Return:  MIstatus::success - Functionality succeeded.
1585 //          MIstatus::failure - Functionality failed.
1586 // Throws:  None.
1587 //--
1588 bool
1589 CMICmnLLDBDebuggerHandleEvents::TextToStdout(const CMIUtilString &vrTxt)
1590 {
1591     return CMICmnStreamStdout::TextToStdout(vrTxt);
1592 }
1593
1594 //++ ------------------------------------------------------------------------------------
1595 // Details: Take a text data and send to the stderr stream. Also output to the MI Log
1596 //          file.
1597 // Type:    Method.
1598 // Args:    vrTxt   - (R) Text.
1599 // Return:  MIstatus::success - Functionality succeeded.
1600 //          MIstatus::failure - Functionality failed.
1601 // Throws:  None.
1602 //--
1603 bool
1604 CMICmnLLDBDebuggerHandleEvents::TextToStderr(const CMIUtilString &vrTxt)
1605 {
1606     return CMICmnStreamStderr::TextToStderr(vrTxt);
1607 }