]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/lldb/tools/lldb-mi/MICmnLLDBDebuggerHandleEvents.cpp
Merge OpenSSL 1.0.2e.
[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 // Third party headers:
11 #include "lldb/API/SBAddress.h"
12 #include "lldb/API/SBEvent.h"
13 #include "lldb/API/SBProcess.h"
14 #include "lldb/API/SBBreakpoint.h"
15 #include "lldb/API/SBStream.h"
16 #include "lldb/API/SBTarget.h"
17 #include "lldb/API/SBThread.h"
18 #include "lldb/API/SBCommandInterpreter.h"
19 #include "lldb/API/SBCommandReturnObject.h"
20 #include "lldb/API/SBUnixSignals.h"
21 #ifdef _WIN32
22 #include <io.h> // For the ::_access()
23 #else
24 #include <unistd.h> // For the ::access()
25 #endif              // _WIN32
26
27 // In-house headers:
28 #include "MICmnLLDBDebuggerHandleEvents.h"
29 #include "MICmnResources.h"
30 #include "MICmnLog.h"
31 #include "MICmnLLDBDebugger.h"
32 #include "MICmnLLDBDebugSessionInfo.h"
33 #include "MICmnMIResultRecord.h"
34 #include "MICmnMIValueConst.h"
35 #include "MICmnMIValueList.h"
36 #include "MICmnMIOutOfBandRecord.h"
37 #include "MICmnStreamStdout.h"
38 #include "MICmnStreamStderr.h"
39 #include "MIUtilDebug.h"
40 #include "MIDriver.h"
41 #include "Platform.h" // for PATH_MAX
42
43 //++ ------------------------------------------------------------------------------------
44 // Details: CMICmnLLDBDebuggerHandleEvents constructor.
45 // Type:    Method.
46 // Args:    None.
47 // Return:  None.
48 // Throws:  None.
49 //--
50 CMICmnLLDBDebuggerHandleEvents::CMICmnLLDBDebuggerHandleEvents(void)
51 {
52 }
53
54 //++ ------------------------------------------------------------------------------------
55 // Details: CMICmnLLDBDebuggerHandleEvents destructor.
56 // Type:    Overridable.
57 // Args:    None.
58 // Return:  None.
59 // Throws:  None.
60 //--
61 CMICmnLLDBDebuggerHandleEvents::~CMICmnLLDBDebuggerHandleEvents(void)
62 {
63     Shutdown();
64 }
65
66 //++ ------------------------------------------------------------------------------------
67 // Details: Initialize resources for *this broadcaster object.
68 // Type:    Method.
69 // Args:    None.
70 // Return:  MIstatus::success - Functionality succeeded.
71 //          MIstatus::failure - Functionality failed.
72 // Throws:  None.
73 //--
74 bool
75 CMICmnLLDBDebuggerHandleEvents::Initialize(void)
76 {
77     m_clientUsageRefCnt++;
78
79     if (m_bInitialized)
80         return MIstatus::success;
81
82     m_bInitialized = MIstatus::success;
83     m_bSignalsInitialized = false;
84     m_SIGINT = 0;
85     m_SIGSTOP = 0;
86     m_SIGSEGV = 0;
87     m_SIGTRAP = 0;
88
89     return m_bInitialized;
90 }
91
92 //++ ------------------------------------------------------------------------------------
93 // Details: Release resources for *this broadcaster object.
94 // Type:    Method.
95 // Args:    None.
96 // Return:  MIstatus::success - Functionality succeeded.
97 //          MIstatus::failure - Functionality failed.
98 // Throws:  None.
99 //--
100 bool
101 CMICmnLLDBDebuggerHandleEvents::Shutdown(void)
102 {
103     if (--m_clientUsageRefCnt > 0)
104         return MIstatus::success;
105
106     if (!m_bInitialized)
107         return MIstatus::success;
108
109     m_bInitialized = false;
110
111     return MIstatus::success;
112 }
113
114 //++ ------------------------------------------------------------------------------------
115 // Details: Interpret the event object to ascertain the action to take or information to
116 //          to form and put in a MI Out-of-band record object which is given to stdout.
117 // Type:    Method.
118 // Args:    vEvent          - (R) An LLDB broadcast event.
119 //          vrbHandledEvent - (W) True - event handled, false = not handled.
120 // Return:  MIstatus::success - Functionality succeeded.
121 //          MIstatus::failure - Functionality failed.
122 // Throws:  None.
123 //--
124 bool
125 CMICmnLLDBDebuggerHandleEvents::HandleEvent(const lldb::SBEvent &vEvent, bool &vrbHandledEvent)
126 {
127     bool bOk = MIstatus::success;
128     vrbHandledEvent = false;
129
130     if (lldb::SBProcess::EventIsProcessEvent(vEvent))
131     {
132         vrbHandledEvent = true;
133         bOk = HandleEventSBProcess(vEvent);
134     }
135     else if (lldb::SBBreakpoint::EventIsBreakpointEvent(vEvent))
136     {
137         vrbHandledEvent = true;
138         bOk = HandleEventSBBreakPoint(vEvent);
139     }
140     else if (lldb::SBThread::EventIsThreadEvent(vEvent))
141     {
142         vrbHandledEvent = true;
143         bOk = HandleEventSBThread(vEvent);
144     }
145     else if (lldb::SBTarget::EventIsTargetEvent(vEvent))
146     {
147         vrbHandledEvent = true;
148         bOk = HandleEventSBTarget(vEvent);
149     }
150     else if (lldb::SBCommandInterpreter::EventIsCommandInterpreterEvent(vEvent))
151     {
152         vrbHandledEvent = true;
153         bOk = HandleEventSBCommandInterpreter(vEvent);
154     }
155
156     return bOk;
157 }
158
159 //++ ------------------------------------------------------------------------------------
160 // Details: Handle a LLDB SBProcess event.
161 // Type:    Method.
162 // Args:    vEvent          - (R) An LLDB broadcast event.
163 // Return:  MIstatus::success - Functionality succeeded.
164 //          MIstatus::failure - Functionality failed.
165 // Throws:  None.
166 //--
167 bool
168 CMICmnLLDBDebuggerHandleEvents::HandleEventSBProcess(const lldb::SBEvent &vEvent)
169 {
170     bool bOk = MIstatus::success;
171
172     const char *pEventType = "";
173     const MIuint nEventType = vEvent.GetType();
174     switch (nEventType)
175     {
176         case lldb::SBProcess::eBroadcastBitInterrupt:
177             pEventType = "eBroadcastBitInterrupt";
178             break;
179         case lldb::SBProcess::eBroadcastBitProfileData:
180             pEventType = "eBroadcastBitProfileData";
181             break;
182         case lldb::SBProcess::eBroadcastBitStateChanged:
183             pEventType = "eBroadcastBitStateChanged";
184             bOk = HandleProcessEventBroadcastBitStateChanged(vEvent);
185             break;
186         case lldb::SBProcess::eBroadcastBitSTDERR:
187             pEventType = "eBroadcastBitSTDERR";
188             bOk = GetProcessStderr();
189             break;
190         case lldb::SBProcess::eBroadcastBitSTDOUT:
191             pEventType = "eBroadcastBitSTDOUT";
192             bOk = GetProcessStdout();
193             break;
194         default:
195         {
196             const CMIUtilString msg(CMIUtilString::Format(MIRSRC(IDS_LLDBOUTOFBAND_ERR_UNKNOWN_EVENT), "SBProcess", (MIuint)nEventType));
197             SetErrorDescription(msg);
198             return MIstatus::failure;
199         }
200     }
201     m_pLog->WriteLog(CMIUtilString::Format("##### An SB Process event occurred: %s", pEventType));
202
203     return bOk;
204 }
205
206 //++ ------------------------------------------------------------------------------------
207 // Details: Handle a LLDB SBBreakpoint event.
208 // Type:    Method.
209 // Args:    vEvent  - (R) An LLDB broadcast event.
210 // Return:  MIstatus::success - Functionality succeeded.
211 //          MIstatus::failure - Functionality failed.
212 // Throws:  None.
213 //--
214 bool
215 CMICmnLLDBDebuggerHandleEvents::HandleEventSBBreakPoint(const lldb::SBEvent &vEvent)
216 {
217     bool bOk = MIstatus::success;
218
219     const char *pEventType = "";
220     const lldb::BreakpointEventType eEvent = lldb::SBBreakpoint::GetBreakpointEventTypeFromEvent(vEvent);
221     switch (eEvent)
222     {
223         case lldb::eBreakpointEventTypeThreadChanged:
224             pEventType = "eBreakpointEventTypeThreadChanged";
225             break;
226         case lldb::eBreakpointEventTypeLocationsRemoved:
227             pEventType = "eBreakpointEventTypeLocationsRemoved";
228             break;
229         case lldb::eBreakpointEventTypeInvalidType:
230             pEventType = "eBreakpointEventTypeInvalidType";
231             break;
232         case lldb::eBreakpointEventTypeLocationsAdded:
233             pEventType = "eBreakpointEventTypeLocationsAdded";
234             bOk = HandleEventSBBreakpointLocationsAdded(vEvent);
235             break;
236         case lldb::eBreakpointEventTypeAdded:
237             pEventType = "eBreakpointEventTypeAdded";
238             bOk = HandleEventSBBreakpointAdded(vEvent);
239             break;
240         case lldb::eBreakpointEventTypeRemoved:
241             pEventType = "eBreakpointEventTypeRemoved";
242             bOk = HandleEventSBBreakpointCmn(vEvent);
243             break;
244         case lldb::eBreakpointEventTypeLocationsResolved:
245             pEventType = "eBreakpointEventTypeLocationsResolved";
246             bOk = HandleEventSBBreakpointCmn(vEvent);
247             break;
248         case lldb::eBreakpointEventTypeEnabled:
249             pEventType = "eBreakpointEventTypeEnabled";
250             bOk = HandleEventSBBreakpointCmn(vEvent);
251             break;
252         case lldb::eBreakpointEventTypeDisabled:
253             pEventType = "eBreakpointEventTypeDisabled";
254             bOk = HandleEventSBBreakpointCmn(vEvent);
255             break;
256         case lldb::eBreakpointEventTypeCommandChanged:
257             pEventType = "eBreakpointEventTypeCommandChanged";
258             bOk = HandleEventSBBreakpointCmn(vEvent);
259             break;
260         case lldb::eBreakpointEventTypeConditionChanged:
261             pEventType = "eBreakpointEventTypeConditionChanged";
262             bOk = HandleEventSBBreakpointCmn(vEvent);
263             break;
264         case lldb::eBreakpointEventTypeIgnoreChanged:
265             pEventType = "eBreakpointEventTypeIgnoreChanged";
266             bOk = HandleEventSBBreakpointCmn(vEvent);
267             break;
268     }
269     m_pLog->WriteLog(CMIUtilString::Format("##### An SB Breakpoint event occurred: %s", pEventType));
270
271     return bOk;
272 }
273
274 //++ ------------------------------------------------------------------------------------
275 // Details: Handle a LLDB SBBreakpoint event.
276 // Type:    Method.
277 // Args:    vEvent  - (R) An LLDB broadcast event.
278 // Return:  MIstatus::success - Functionality succeeded.
279 //          MIstatus::failure - Functionality failed.
280 // Throws:  None.
281 //--
282 bool
283 CMICmnLLDBDebuggerHandleEvents::HandleEventSBBreakpointLocationsAdded(const lldb::SBEvent &vEvent)
284 {
285     const MIuint nLoc = lldb::SBBreakpoint::GetNumBreakpointLocationsFromEvent(vEvent);
286     if (nLoc == 0)
287         return MIstatus::success;
288
289     lldb::SBBreakpoint brkPt = lldb::SBBreakpoint::GetBreakpointFromEvent(vEvent);
290     const CMIUtilString plural((nLoc == 1) ? "" : "s");
291     const CMIUtilString msg(CMIUtilString::Format("%d location%s added to breakpoint %d", nLoc, plural.c_str(), brkPt.GetID()));
292
293     return TextToStdout(msg);
294 }
295
296 //++ ------------------------------------------------------------------------------------
297 // Details: Handle a LLDB SBBreakpoint event.
298 // Type:    Method.
299 // Args:    vEvent  - (R) An LLDB broadcast event.
300 // Return:  MIstatus::success - Functionality succeeded.
301 //          MIstatus::failure - Functionality failed.
302 // Throws:  None.
303 //--
304 bool
305 CMICmnLLDBDebuggerHandleEvents::HandleEventSBBreakpointCmn(const lldb::SBEvent &vEvent)
306 {
307     lldb::SBBreakpoint brkPt = lldb::SBBreakpoint::GetBreakpointFromEvent(vEvent);
308     if (!brkPt.IsValid())
309         return MIstatus::success;
310
311     CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance());
312     CMICmnLLDBDebugSessionInfo::SBrkPtInfo sBrkPtInfo;
313     if (!rSessionInfo.GetBrkPtInfo(brkPt, sBrkPtInfo))
314     {
315         SetErrorDescription(
316             CMIUtilString::Format(MIRSRC(IDS_LLDBOUTOFBAND_ERR_BRKPT_INFO_GET), "HandleEventSBBreakpointCmn()", brkPt.GetID()));
317         return MIstatus::failure;
318     }
319
320     // CODETAG_LLDB_BREAKPOINT_CREATION
321     // This is in a worker thread
322     // Add more breakpoint information or overwrite existing information
323     CMICmnLLDBDebugSessionInfo::SBrkPtInfo sBrkPtInfoRec;
324     if (!rSessionInfo.RecordBrkPtInfoGet(brkPt.GetID(), sBrkPtInfoRec))
325     {
326         SetErrorDescription(
327             CMIUtilString::Format(MIRSRC(IDS_LLDBOUTOFBAND_ERR_BRKPT_NOTFOUND), "HandleEventSBBreakpointCmn()", brkPt.GetID()));
328         return MIstatus::failure;
329     }
330     sBrkPtInfo.m_bDisp = sBrkPtInfoRec.m_bDisp;
331     sBrkPtInfo.m_bEnabled = brkPt.IsEnabled();
332     sBrkPtInfo.m_bHaveArgOptionThreadGrp = false;
333     sBrkPtInfo.m_strOptThrdGrp = "";
334     sBrkPtInfo.m_nTimes = brkPt.GetHitCount();
335     sBrkPtInfo.m_strOrigLoc = sBrkPtInfoRec.m_strOrigLoc;
336     sBrkPtInfo.m_nIgnore = sBrkPtInfoRec.m_nIgnore;
337     sBrkPtInfo.m_bPending = sBrkPtInfoRec.m_bPending;
338     sBrkPtInfo.m_bCondition = sBrkPtInfoRec.m_bCondition;
339     sBrkPtInfo.m_strCondition = sBrkPtInfoRec.m_strCondition;
340     sBrkPtInfo.m_bBrkPtThreadId = sBrkPtInfoRec.m_bBrkPtThreadId;
341     sBrkPtInfo.m_nBrkPtThreadId = sBrkPtInfoRec.m_nBrkPtThreadId;
342
343     // MI print "=breakpoint-modified,bkpt={number=\"%d\",type=\"breakpoint\",disp=\"%s\",enabled=\"%c\",addr=\"0x%016" PRIx64 "\",
344     // func=\"%s\",file=\"%s\",fullname=\"%s/%s\",line=\"%d\",times=\"%d\",original-location=\"%s\"}"
345     CMICmnMIValueTuple miValueTuple;
346     if (!rSessionInfo.MIResponseFormBrkPtInfo(sBrkPtInfo, miValueTuple))
347     {
348         SetErrorDescription(CMIUtilString::Format(MIRSRC(IDS_LLDBOUTOFBAND_ERR_FORM_MI_RESPONSE), "HandleEventSBBreakpointCmn()"));
349         return MIstatus::failure;
350     }
351
352     const CMICmnMIValueResult miValueResultC("bkpt", miValueTuple);
353     const CMICmnMIOutOfBandRecord miOutOfBandRecord(CMICmnMIOutOfBandRecord::eOutOfBand_BreakPointModified, miValueResultC);
354     const bool bOk = MiOutOfBandRecordToStdout(miOutOfBandRecord);
355
356     return bOk;
357 }
358
359 //++ ------------------------------------------------------------------------------------
360 // Details: Handle a LLDB SBBreakpoint added event.
361 //          Add more breakpoint information or overwrite existing information.
362 //          Normally a break point session info objects exists by now when an MI command
363 //          was issued to insert a break so the retrieval would normally always succeed
364 //          however should a user type "b main" into a console then LLDB will create a
365 //          breakpoint directly, hence no MI command, hence no previous record of the
366 //          breakpoint so RecordBrkPtInfoGet() will fail. We still get the event though
367 //          so need to create a breakpoint info object here and send appropriate MI
368 //          response.
369 // Type:    Method.
370 // Args:    vEvent  - (R) An LLDB broadcast event.
371 // Return:  MIstatus::success - Functionality succeeded.
372 //          MIstatus::failure - Functionality failed.
373 // Throws:  None.
374 //--
375 bool
376 CMICmnLLDBDebuggerHandleEvents::HandleEventSBBreakpointAdded(const lldb::SBEvent &vEvent)
377 {
378     lldb::SBBreakpoint brkPt = lldb::SBBreakpoint::GetBreakpointFromEvent(vEvent);
379     if (!brkPt.IsValid())
380         return MIstatus::success;
381
382     CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance());
383     CMICmnLLDBDebugSessionInfo::SBrkPtInfo sBrkPtInfo;
384     if (!rSessionInfo.GetBrkPtInfo(brkPt, sBrkPtInfo))
385     {
386         SetErrorDescription(
387             CMIUtilString::Format(MIRSRC(IDS_LLDBOUTOFBAND_ERR_BRKPT_INFO_GET), "HandleEventSBBreakpointAdded()", brkPt.GetID()));
388         return MIstatus::failure;
389     }
390
391     // CODETAG_LLDB_BREAKPOINT_CREATION
392     // This is in a worker thread
393     CMICmnLLDBDebugSessionInfo::SBrkPtInfo sBrkPtInfoRec;
394     const bool bBrkPtExistAlready = rSessionInfo.RecordBrkPtInfoGet(brkPt.GetID(), sBrkPtInfoRec);
395     if (bBrkPtExistAlready)
396     {
397         // Update breakpoint information object
398         sBrkPtInfo.m_bDisp = sBrkPtInfoRec.m_bDisp;
399         sBrkPtInfo.m_bEnabled = brkPt.IsEnabled();
400         sBrkPtInfo.m_bHaveArgOptionThreadGrp = false;
401         sBrkPtInfo.m_strOptThrdGrp.clear();
402         sBrkPtInfo.m_nTimes = brkPt.GetHitCount();
403         sBrkPtInfo.m_strOrigLoc = sBrkPtInfoRec.m_strOrigLoc;
404         sBrkPtInfo.m_nIgnore = sBrkPtInfoRec.m_nIgnore;
405         sBrkPtInfo.m_bPending = sBrkPtInfoRec.m_bPending;
406         sBrkPtInfo.m_bCondition = sBrkPtInfoRec.m_bCondition;
407         sBrkPtInfo.m_strCondition = sBrkPtInfoRec.m_strCondition;
408         sBrkPtInfo.m_bBrkPtThreadId = sBrkPtInfoRec.m_bBrkPtThreadId;
409         sBrkPtInfo.m_nBrkPtThreadId = sBrkPtInfoRec.m_nBrkPtThreadId;
410     }
411     else
412     {
413         // Create a breakpoint information object
414         sBrkPtInfo.m_bDisp = brkPt.IsOneShot();
415         sBrkPtInfo.m_bEnabled = brkPt.IsEnabled();
416         sBrkPtInfo.m_bHaveArgOptionThreadGrp = false;
417         sBrkPtInfo.m_strOptThrdGrp.clear();
418         sBrkPtInfo.m_strOrigLoc = CMIUtilString::Format("%s:%d", sBrkPtInfo.m_fileName.c_str(), sBrkPtInfo.m_nLine);
419         sBrkPtInfo.m_nIgnore = brkPt.GetIgnoreCount();
420         sBrkPtInfo.m_bPending = false;
421         const char *pStrCondition = brkPt.GetCondition();
422         sBrkPtInfo.m_bCondition = (pStrCondition != nullptr) ? true : false;
423         sBrkPtInfo.m_strCondition = (pStrCondition != nullptr) ? pStrCondition : "??";
424         sBrkPtInfo.m_bBrkPtThreadId = (brkPt.GetThreadID() != 0) ? true : false;
425         sBrkPtInfo.m_nBrkPtThreadId = brkPt.GetThreadID();
426     }
427
428     CMICmnMIValueTuple miValueTuple;
429     if (!rSessionInfo.MIResponseFormBrkPtInfo(sBrkPtInfo, miValueTuple))
430     {
431         SetErrorDescription(CMIUtilString::Format(MIRSRC(IDS_LLDBOUTOFBAND_ERR_FORM_MI_RESPONSE), "HandleEventSBBreakpointAdded()"));
432         return MIstatus::failure;
433     }
434
435     bool bOk = MIstatus::success;
436     if (bBrkPtExistAlready)
437     {
438         // MI print
439         // "=breakpoint-modified,bkpt={number=\"%d\",type=\"breakpoint\",disp=\"%s\",enabled=\"%c\",addr=\"0x%016" PRIx64 "\",func=\"%s\",file=\"%s\",fullname=\"%s/%s\",line=\"%d\",times=\"%d\",original-location=\"%s\"}"
440         const CMICmnMIValueResult miValueResult("bkpt", miValueTuple);
441         const CMICmnMIOutOfBandRecord miOutOfBandRecord(CMICmnMIOutOfBandRecord::eOutOfBand_BreakPointModified, miValueResult);
442         bOk = MiOutOfBandRecordToStdout(miOutOfBandRecord);
443     }
444     else
445     {
446         // CODETAG_LLDB_BRKPT_ID_MAX
447         if (brkPt.GetID() > (lldb::break_id_t)rSessionInfo.m_nBrkPointCntMax)
448         {
449             SetErrorDescription(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_BRKPT_CNT_EXCEEDED), "HandleEventSBBreakpointAdded()",
450                                                       rSessionInfo.m_nBrkPointCntMax, sBrkPtInfo.m_id));
451             return MIstatus::failure;
452         }
453         if (!rSessionInfo.RecordBrkPtInfo(brkPt.GetID(), sBrkPtInfo))
454         {
455             SetErrorDescription(
456                 CMIUtilString::Format(MIRSRC(IDS_LLDBOUTOFBAND_ERR_BRKPT_INFO_SET), "HandleEventSBBreakpointAdded()", sBrkPtInfo.m_id));
457             return MIstatus::failure;
458         }
459
460         // MI print
461         // "=breakpoint-created,bkpt={number=\"%d\",type=\"breakpoint\",disp=\"%s\",enabled=\"%c\",addr=\"0x%016" PRIx64 "\",func=\"%s\",file=\"%s\",fullname=\"%s/%s\",line=\"%d\",times=\"%d\",original-location=\"%s\"}"
462         const CMICmnMIValueResult miValueResult("bkpt", miValueTuple);
463         const CMICmnMIOutOfBandRecord miOutOfBandRecord(CMICmnMIOutOfBandRecord::eOutOfBand_BreakPointCreated, miValueResult);
464         bOk = MiOutOfBandRecordToStdout(miOutOfBandRecord);
465     }
466
467     return bOk;
468 }
469
470 //++ ------------------------------------------------------------------------------------
471 // Details: Handle a LLDB SBThread event.
472 // Type:    Method.
473 // Args:    vEvent  - (R) An LLDB broadcast event.
474 // Return:  MIstatus::success - Functionality succeeded.
475 //          MIstatus::failure - Functionality failed.
476 // Throws:  None.
477 //--
478 bool
479 CMICmnLLDBDebuggerHandleEvents::HandleEventSBThread(const lldb::SBEvent &vEvent)
480 {
481     if (!ChkForStateChanges())
482         return MIstatus::failure;
483
484     bool bOk = MIstatus::success;
485     const char *pEventType = "";
486     const MIuint nEventType = vEvent.GetType();
487     switch (nEventType)
488     {
489         case lldb::SBThread::eBroadcastBitStackChanged:
490             pEventType = "eBroadcastBitStackChanged";
491             bOk = HandleEventSBThreadBitStackChanged(vEvent);
492             break;
493         case lldb::SBThread::eBroadcastBitThreadSuspended:
494             pEventType = "eBroadcastBitThreadSuspended";
495             bOk = HandleEventSBThreadSuspended(vEvent);
496             break;
497         case lldb::SBThread::eBroadcastBitThreadResumed:
498             pEventType = "eBroadcastBitThreadResumed";
499             break;
500         case lldb::SBThread::eBroadcastBitSelectedFrameChanged:
501             pEventType = "eBroadcastBitSelectedFrameChanged";
502             break;
503         case lldb::SBThread::eBroadcastBitThreadSelected:
504             pEventType = "eBroadcastBitThreadSelected";
505             break;
506         default:
507         {
508             const CMIUtilString msg(CMIUtilString::Format(MIRSRC(IDS_LLDBOUTOFBAND_ERR_UNKNOWN_EVENT), "SBThread", (MIuint)nEventType));
509             SetErrorDescription(msg);
510             return MIstatus::failure;
511         }
512     }
513     m_pLog->WriteLog(CMIUtilString::Format("##### An SBThread event occurred: %s", pEventType));
514
515     return bOk;
516 }
517
518 //++ ------------------------------------------------------------------------------------
519 // Details: Handle a LLDB SBThread event.
520 // Type:    Method.
521 // Args:    vEvent  - (R) An LLDB broadcast event.
522 // Return:  MIstatus::success - Functionality succeeded.
523 //          MIstatus::failure - Functionality failed.
524 // Throws:  None.
525 //--
526 bool
527 CMICmnLLDBDebuggerHandleEvents::HandleEventSBThreadSuspended(const lldb::SBEvent &vEvent)
528 {
529     lldb::SBThread thread = lldb::SBThread::GetThreadFromEvent(vEvent);
530     if (!thread.IsValid())
531         return MIstatus::success;
532
533     const lldb::StopReason eStopReason = thread.GetStopReason();
534     if (eStopReason != lldb::eStopReasonSignal)
535         return MIstatus::success;
536
537     // MI print "@thread=%d,signal=%lld"
538     const MIuint64 nId = thread.GetStopReasonDataAtIndex(0);
539     const CMIUtilString strThread(CMIUtilString::Format("%d", thread.GetThreadID()));
540     const CMICmnMIValueConst miValueConst(strThread);
541     const CMICmnMIValueResult miValueResult("thread", miValueConst);
542     CMICmnMIOutOfBandRecord miOutOfBandRecord(CMICmnMIOutOfBandRecord::eOutOfBand_Thread, miValueResult);
543     const CMIUtilString strSignal(CMIUtilString::Format("%lld", nId));
544     const CMICmnMIValueConst miValueConst2(strSignal);
545     const CMICmnMIValueResult miValueResult2("signal", miValueConst2);
546     bool bOk = miOutOfBandRecord.Add(miValueResult2);
547     bOk = bOk && MiOutOfBandRecordToStdout(miOutOfBandRecord);
548
549     return bOk;
550 }
551
552 //++ ------------------------------------------------------------------------------------
553 // Details: Handle a LLDB SBThread event.
554 // Type:    Method.
555 // Args:    vEvent  - (R) An LLDB broadcast event.
556 // Return:  MIstatus::success - Functionality succeeded.
557 //          MIstatus::failure - Functionality failed.
558 // Throws:  None.
559 //--
560 bool
561 CMICmnLLDBDebuggerHandleEvents::HandleEventSBThreadBitStackChanged(const lldb::SBEvent &vEvent)
562 {
563     lldb::SBThread thread = lldb::SBThread::GetThreadFromEvent(vEvent);
564     if (!thread.IsValid())
565         return MIstatus::success;
566
567     lldb::SBStream streamOut;
568     const bool bOk = thread.GetStatus(streamOut);
569     return bOk && TextToStdout(streamOut.GetData());
570 }
571
572 //++ ------------------------------------------------------------------------------------
573 // Details: Handle a LLDB SBTarget event.
574 // Type:    Method.
575 // Args:    vEvent  - (R) An LLDB broadcast event.
576 // Return:  MIstatus::success - Functional succeeded.
577 //          MIstatus::failure - Functional failed.
578 // Throws:  None.
579 //--
580 bool
581 CMICmnLLDBDebuggerHandleEvents::HandleEventSBTarget(const lldb::SBEvent &vEvent)
582 {
583     if (!ChkForStateChanges())
584         return MIstatus::failure;
585
586     bool bOk = MIstatus::success;
587     const char *pEventType = "";
588     const MIuint nEventType = vEvent.GetType();
589     switch (nEventType)
590     {
591         case lldb::SBTarget::eBroadcastBitBreakpointChanged:
592             pEventType = "eBroadcastBitBreakpointChanged";
593             break;
594         case lldb::SBTarget::eBroadcastBitModulesLoaded:
595             pEventType = "eBroadcastBitModulesLoaded";
596             bOk = HandleTargetEventBroadcastBitModulesLoaded(vEvent);
597             break;
598         case lldb::SBTarget::eBroadcastBitModulesUnloaded:
599             pEventType = "eBroadcastBitModulesUnloaded";
600             bOk = HandleTargetEventBroadcastBitModulesUnloaded(vEvent);
601             break;
602         case lldb::SBTarget::eBroadcastBitWatchpointChanged:
603             pEventType = "eBroadcastBitWatchpointChanged";
604             break;
605         case lldb::SBTarget::eBroadcastBitSymbolsLoaded:
606             pEventType = "eBroadcastBitSymbolsLoaded";
607             break;
608         default:
609         {
610             const CMIUtilString msg(CMIUtilString::Format(MIRSRC(IDS_LLDBOUTOFBAND_ERR_UNKNOWN_EVENT), "SBTarget", (MIuint)nEventType));
611             SetErrorDescription(msg);
612             return MIstatus::failure;
613         }
614     }
615     m_pLog->WriteLog(CMIUtilString::Format("##### An SBTarget event occurred: %s", pEventType));
616
617     return bOk;
618 }
619
620 //++ ------------------------------------------------------------------------------------
621 // Details: Print to stdout "=library-loaded,id=\"%s\",target-name=\"%s\",host-name=\"%s\",symbols-loaded="%d"[,symbols-path=\"%s\"],loaded_addr=\"0x%016" PRIx64"\""
622 // Type:    Method.
623 // Args:    None.
624 // Return:  MIstatus::success - Function succeeded.
625 //          MIstatus::failure - Function failed.
626 // Throws:  None.
627 //--
628 bool
629 CMICmnLLDBDebuggerHandleEvents::HandleTargetEventBroadcastBitModulesLoaded(const lldb::SBEvent &vEvent)
630 {
631     bool bOk = MIstatus::failure;
632     const MIuint nSize = lldb::SBTarget::GetNumModulesFromEvent(vEvent);
633     for (MIuint nIndex = 0; nIndex < nSize; ++nIndex)
634     {
635         const lldb::SBModule sbModule = lldb::SBTarget::GetModuleAtIndexFromEvent(nIndex, vEvent);
636         CMICmnMIOutOfBandRecord miOutOfBandRecord(CMICmnMIOutOfBandRecord::eOutOfBand_TargetModuleLoaded);
637         const bool bWithExtraFields = true;
638         bOk = MiHelpGetModuleInfo(sbModule, bWithExtraFields, miOutOfBandRecord);
639         bOk = bOk && MiOutOfBandRecordToStdout(miOutOfBandRecord);
640         if (!bOk)
641             break;
642     }
643
644     return bOk;
645 }
646
647 //++ ------------------------------------------------------------------------------------
648 // Details: Print to stdout "=library-unloaded,id=\"%s\",target-name=\"%s\",host-name=\"%s\",symbols-loaded="%d"[,symbols-path=\"%s\"],loaded_addr=\"0x%016" PRIx64"\""
649 // Type:    Method.
650 // Args:    None.
651 // Return:  MIstatus::success - Function succeeded.
652 //          MIstatus::failure - Function failed.
653 // Throws:  None.
654 //--
655 bool
656 CMICmnLLDBDebuggerHandleEvents::HandleTargetEventBroadcastBitModulesUnloaded(const lldb::SBEvent &vEvent)
657 {
658     bool bOk = MIstatus::failure;
659     const MIuint nSize = lldb::SBTarget::GetNumModulesFromEvent(vEvent);
660     for (MIuint nIndex = 0; nIndex < nSize; ++nIndex)
661     {
662         const lldb::SBModule sbModule = lldb::SBTarget::GetModuleAtIndexFromEvent(nIndex, vEvent);
663         CMICmnMIOutOfBandRecord miOutOfBandRecord(CMICmnMIOutOfBandRecord::eOutOfBand_TargetModuleUnloaded);
664         const bool bWithExtraFields = false;
665         bOk = MiHelpGetModuleInfo(sbModule, bWithExtraFields, miOutOfBandRecord);
666         bOk = bOk && MiOutOfBandRecordToStdout(miOutOfBandRecord);
667         if (!bOk)
668             break;
669     }
670
671     return bOk;
672 }
673
674 //++ ------------------------------------------------------------------------------------
675 // Details: Build module information for =library-loaded/=library-unloaded: "id=\"%s\",target-name=\"%s\",host-name=\"%s\",symbols-loaded="%d"[,symbols-path=\"%s\"],loaded_addr=\"0x%016" PRIx64"\""
676 // Type:    Method.
677 // Args:    vwrMiValueList    - (W) MI value list object.
678 // Return:  MIstatus::success - Function succeeded.
679 //          MIstatus::failure - Function failed.
680 // Throws:  None.
681 //--
682 bool
683 CMICmnLLDBDebuggerHandleEvents::MiHelpGetModuleInfo(const lldb::SBModule &vModule, const bool vbWithExtraFields,
684                                                     CMICmnMIOutOfBandRecord &vwrMiOutOfBandRecord)
685 {
686     bool bOk = MIstatus::success;
687
688     // First, build standard fields:
689     // Build "id" field
690     std::unique_ptr<char[]> apPath(new char[PATH_MAX]);
691     vModule.GetFileSpec().GetPath(apPath.get(), PATH_MAX);
692     const CMIUtilString strTargetPath(apPath.get());
693     const CMICmnMIValueConst miValueConst(strTargetPath);
694     const CMICmnMIValueResult miValueResult("id", miValueConst);
695     bOk = bOk && vwrMiOutOfBandRecord.Add(miValueResult);
696     // Build "target-name" field
697     const CMICmnMIValueConst miValueConst2(strTargetPath);
698     const CMICmnMIValueResult miValueResult2("target-name", miValueConst2);
699     bOk = bOk && vwrMiOutOfBandRecord.Add(miValueResult2);
700     // Build "host-name" field
701     vModule.GetPlatformFileSpec().GetPath(apPath.get(), PATH_MAX);
702     const CMIUtilString strHostPath(apPath.get());
703     const CMICmnMIValueConst miValueConst3(strHostPath);
704     const CMICmnMIValueResult miValueResult3("host-name", miValueConst3);
705     bOk = bOk && vwrMiOutOfBandRecord.Add(miValueResult3);
706
707     // Then build extra fields if needed:
708     if (vbWithExtraFields)
709     {
710         // Build "symbols-loaded" field
711         vModule.GetSymbolFileSpec().GetPath(apPath.get(), PATH_MAX);
712         const CMIUtilString strSymbolsPath(apPath.get());
713         const bool bSymbolsLoaded = !CMIUtilString::Compare(strHostPath, strSymbolsPath);
714         const CMICmnMIValueConst miValueConst4(CMIUtilString::Format("%d", bSymbolsLoaded));
715         const CMICmnMIValueResult miValueResult4("symbols-loaded", miValueConst4);
716         bOk = bOk && vwrMiOutOfBandRecord.Add(miValueResult4);
717         // Build "symbols-path" field
718         if (bSymbolsLoaded)
719         {
720             const CMICmnMIValueConst miValueConst5(strSymbolsPath);
721             const CMICmnMIValueResult miValueResult5("symbols-path", miValueConst5);
722             bOk = bOk && vwrMiOutOfBandRecord.Add(miValueResult5);
723         }
724         // Build "loaded_addr" field
725         const lldb::SBAddress sbAddress(vModule.GetObjectFileHeaderAddress());
726         CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance());
727         const lldb::addr_t nLoadAddress(sbAddress.GetLoadAddress(rSessionInfo.GetTarget()));
728         const CMIUtilString strLoadedAddr(nLoadAddress != LLDB_INVALID_ADDRESS ?
729                                           CMIUtilString::Format("0x%016" PRIx64, nLoadAddress) : "-");
730         const CMICmnMIValueConst miValueConst6(strLoadedAddr);
731         const CMICmnMIValueResult miValueResult6("loaded_addr", miValueConst6);
732         bOk = bOk && vwrMiOutOfBandRecord.Add(miValueResult6);
733     }
734
735     return bOk;
736 }
737
738 //++ ------------------------------------------------------------------------------------
739 // Details: Handle a LLDB SBCommandInterpreter event.
740 // Type:    Method.
741 // Args:    vEvent  - (R) An LLDB command interpreter event.
742 // Return:  MIstatus::success - Functionality succeeded.
743 //          MIstatus::failure - Functionality failed.
744 // Throws:  None.
745 //--
746 bool
747 CMICmnLLDBDebuggerHandleEvents::HandleEventSBCommandInterpreter(const lldb::SBEvent &vEvent)
748 {
749     // This function is not used
750     // *** This function is under development
751
752     const char *pEventType = "";
753     const MIuint nEventType = vEvent.GetType();
754     switch (nEventType)
755     {
756         case lldb::SBCommandInterpreter::eBroadcastBitThreadShouldExit:
757             pEventType = "eBroadcastBitThreadShouldExit";
758         // ToDo: IOR: Reminder to maybe handle this here
759         // const MIuint nEventType = event.GetType();
760         // if (nEventType & lldb::SBCommandInterpreter::eBroadcastBitThreadShouldExit)
761         //{
762         //  m_pClientDriver->SetExitApplicationFlag();
763         //  vrbYesExit = true;
764         //  return MIstatus::success;
765         //}     break;
766         case lldb::SBCommandInterpreter::eBroadcastBitResetPrompt:
767             pEventType = "eBroadcastBitResetPrompt";
768             break;
769         case lldb::SBCommandInterpreter::eBroadcastBitQuitCommandReceived:
770         {
771             pEventType = "eBroadcastBitQuitCommandReceived";
772             const bool bForceExit = true;
773             CMICmnLLDBDebugger::Instance().GetDriver().SetExitApplicationFlag(bForceExit);
774             break;
775         }
776         case lldb::SBCommandInterpreter::eBroadcastBitAsynchronousOutputData:
777             pEventType = "eBroadcastBitAsynchronousOutputData";
778             break;
779         case lldb::SBCommandInterpreter::eBroadcastBitAsynchronousErrorData:
780             pEventType = "eBroadcastBitAsynchronousErrorData";
781             break;
782         default:
783         {
784             const CMIUtilString msg(
785                 CMIUtilString::Format(MIRSRC(IDS_LLDBOUTOFBAND_ERR_UNKNOWN_EVENT), "SBCommandInterpreter", (MIuint)nEventType));
786             SetErrorDescription(msg);
787             return MIstatus::failure;
788         }
789     }
790     m_pLog->WriteLog(CMIUtilString::Format("##### An SBCommandInterpreter event occurred: %s", pEventType));
791
792     return MIstatus::success;
793 }
794
795 //++ ------------------------------------------------------------------------------------
796 // Details: Handle SBProcess event eBroadcastBitStateChanged.
797 // Type:    Method.
798 // Args:    vEvent          - (R) An LLDB event object.
799 // Return:  MIstatus::success - Functionality succeeded.
800 //          MIstatus::failure - Functionality failed.
801 // Throws:  None.
802 //--
803 bool
804 CMICmnLLDBDebuggerHandleEvents::HandleProcessEventBroadcastBitStateChanged(const lldb::SBEvent &vEvent)
805 {
806     // Make sure the program hasn't been auto-restarted:
807     if (lldb::SBProcess::GetRestartedFromEvent(vEvent))
808         return MIstatus::success;
809
810     bool bOk = ChkForStateChanges();
811     bOk = bOk && GetProcessStdout();
812     bOk = bOk && GetProcessStderr();
813     if (!bOk)
814         return MIstatus::failure;
815
816     // Something changed in the process; get the event and report the process's current
817     // status and location
818     const lldb::StateType eEventState = lldb::SBProcess::GetStateFromEvent(vEvent);
819     if (eEventState == lldb::eStateInvalid)
820         return MIstatus::success;
821
822     lldb::SBProcess process = lldb::SBProcess::GetProcessFromEvent(vEvent);
823     if (!process.IsValid())
824     {
825         const CMIUtilString msg(CMIUtilString::Format(MIRSRC(IDS_LLDBOUTOFBAND_ERR_PROCESS_INVALID), "SBProcess",
826                                                       "HandleProcessEventBroadcastBitStateChanged()"));
827         SetErrorDescription(msg);
828         return MIstatus::failure;
829     }
830
831     bool bShouldBrk = true;
832     const char *pEventType = "";
833     switch (eEventState)
834     {
835         case lldb::eStateUnloaded:
836             pEventType = "eStateUnloaded";
837             break;
838         case lldb::eStateConnected:
839             pEventType = "eStateConnected";
840             break;
841         case lldb::eStateAttaching:
842             pEventType = "eStateAttaching";
843             break;
844         case lldb::eStateLaunching:
845             pEventType = "eStateLaunching";
846             break;
847         case lldb::eStateStopped:
848             pEventType = "eStateStopped";
849             bOk = HandleProcessEventStateStopped(vEvent, bShouldBrk);
850             if (bShouldBrk)
851                 break;
852         case lldb::eStateCrashed:
853         case lldb::eStateSuspended:
854             pEventType = "eStateSuspended";
855             bOk = HandleProcessEventStateSuspended(vEvent);
856             break;
857         case lldb::eStateRunning:
858             pEventType = "eStateRunning";
859             bOk = HandleProcessEventStateRunning();
860             break;
861         case lldb::eStateStepping:
862             pEventType = "eStateStepping";
863             break;
864         case lldb::eStateDetached:
865             pEventType = "eStateDetached";
866             break;
867         case lldb::eStateExited:
868             // Don't exit from lldb-mi here. We should be able to re-run target.
869             pEventType = "eStateExited";
870             bOk = HandleProcessEventStateExited();
871             break;
872         default:
873         {
874             const CMIUtilString msg(CMIUtilString::Format(MIRSRC(IDS_LLDBOUTOFBAND_ERR_UNKNOWN_EVENT), "SBProcess BroadcastBitStateChanged",
875                                                           (MIuint)eEventState));
876             SetErrorDescription(msg);
877             return MIstatus::failure;
878         }
879     }
880
881     // ToDo: Remove when finished coding application
882     m_pLog->WriteLog(CMIUtilString::Format("##### An SB Process event BroadcastBitStateChanged occurred: %s", pEventType));
883
884     return bOk;
885 }
886
887 //++ ------------------------------------------------------------------------------------
888 // Details: Asynchronous event handler for LLDB Process state suspended.
889 // Type:    Method.
890 // Args:    vEvent  - (R) An LLDB event object.
891 // Return:  MIstatus::success - Functionality succeeded.
892 //          MIstatus::failure - Functionality failed.
893 // Throws:  None.
894 //--
895 bool
896 CMICmnLLDBDebuggerHandleEvents::HandleProcessEventStateSuspended(const lldb::SBEvent &vEvent)
897 {
898     bool bOk = MIstatus::success;
899     lldb::SBDebugger &rDebugger = CMICmnLLDBDebugSessionInfo::Instance().GetDebugger();
900     lldb::SBProcess sbProcess = CMICmnLLDBDebugSessionInfo::Instance().GetProcess();
901     lldb::SBTarget target = sbProcess.GetTarget();
902     if (rDebugger.GetSelectedTarget() == target)
903     {
904         if (!UpdateSelectedThread())
905             return MIstatus::failure;
906
907         lldb::SBCommandReturnObject result;
908         const lldb::ReturnStatus status = rDebugger.GetCommandInterpreter().HandleCommand("process status", result, false);
909         MIunused(status);
910         bOk = TextToStderr(result.GetError());
911         bOk = bOk && TextToStdout(result.GetOutput());
912     }
913     else
914     {
915         lldb::SBStream streamOut;
916         const MIuint nTargetIndex = rDebugger.GetIndexOfTarget(target);
917         if (nTargetIndex != UINT_MAX)
918             streamOut.Printf("Target %d: (", nTargetIndex);
919         else
920             streamOut.Printf("Target <unknown index>: (");
921         target.GetDescription(streamOut, lldb::eDescriptionLevelBrief);
922         streamOut.Printf(") stopped.\n");
923         bOk = TextToStdout(streamOut.GetData());
924     }
925
926     return bOk;
927 }
928
929 //++ ------------------------------------------------------------------------------------
930 // Details: Print to stdout MI formatted text to indicate process stopped.
931 // Type:    Method.
932 // Args:    vwrbShouldBrk   - (W) True = Yes break, false = do not.
933 // Return:  MIstatus::success - Functionality succeeded.
934 //          MIstatus::failure - Functionality failed.
935 // Throws:  None.
936 //--
937 bool
938 CMICmnLLDBDebuggerHandleEvents::HandleProcessEventStateStopped(const lldb::SBEvent &vrEvent, bool &vwrbShouldBrk)
939 {
940     if (!UpdateSelectedThread())
941         return MIstatus::failure;
942
943     const char *pEventType = "";
944     bool bOk = MIstatus::success;
945     lldb::SBProcess sbProcess = CMICmnLLDBDebugSessionInfo::Instance().GetProcess();
946     const lldb::StopReason eStoppedReason = sbProcess.GetSelectedThread().GetStopReason();
947     switch (eStoppedReason)
948     {
949         case lldb::eStopReasonInvalid:
950             pEventType = "eStopReasonInvalid";
951             vwrbShouldBrk = false;
952             break;
953         case lldb::eStopReasonNone:
954             pEventType = "eStopReasonNone";
955             break;
956         case lldb::eStopReasonTrace:
957             pEventType = "eStopReasonTrace";
958             bOk = HandleProcessEventStopReasonTrace();
959             break;
960         case lldb::eStopReasonBreakpoint:
961             pEventType = "eStopReasonBreakpoint";
962             bOk = HandleProcessEventStopReasonBreakpoint();
963             break;
964         case lldb::eStopReasonWatchpoint:
965             pEventType = "eStopReasonWatchpoint";
966             break;
967         case lldb::eStopReasonSignal:
968             pEventType = "eStopReasonSignal";
969             bOk = HandleProcessEventStopSignal(vrEvent);
970             break;
971         case lldb::eStopReasonException:
972             pEventType = "eStopReasonException";
973             bOk = HandleProcessEventStopException();
974             break;
975         case lldb::eStopReasonExec:
976             pEventType = "eStopReasonExec";
977             break;
978         case lldb::eStopReasonPlanComplete:
979             pEventType = "eStopReasonPlanComplete";
980             bOk = HandleProcessEventStopReasonTrace();
981             break;
982         case lldb::eStopReasonThreadExiting:
983             pEventType = "eStopReasonThreadExiting";
984             break;
985         case lldb::eStopReasonInstrumentation:
986             pEventType = "eStopReasonInstrumentation";
987             break;
988     }
989
990     // ToDo: Remove when finished coding application
991     m_pLog->WriteLog(CMIUtilString::Format("##### An SB Process event stop state occurred: %s", pEventType));
992
993     return bOk;
994 }
995
996 //++ ------------------------------------------------------------------------------------
997 // Details: Asynchronous event handler for LLDB Process stop signal.
998 // Type:    Method.
999 // Args:    vrEvent           - (R) An LLDB broadcast event.
1000 // Return:  MIstatus::success - Functionality succeeded.
1001 //          MIstatus::failure - Functionality failed.
1002 // Throws:  None.
1003 //--
1004 bool
1005 CMICmnLLDBDebuggerHandleEvents::HandleProcessEventStopSignal(const lldb::SBEvent &vrEvent)
1006 {
1007     bool bOk = MIstatus::success;
1008
1009     InitializeSignals ();
1010     lldb::SBProcess sbProcess = CMICmnLLDBDebugSessionInfo::Instance().GetProcess();
1011     const MIuint64 nStopReason = sbProcess.GetSelectedThread().GetStopReasonDataAtIndex(0);
1012     const bool bInterrupted = lldb::SBProcess::GetInterruptedFromEvent(vrEvent);
1013     if (nStopReason == m_SIGINT || (nStopReason == m_SIGSTOP && bInterrupted))
1014     {
1015         // MI print "*stopped,reason=\"signal-received\",signal-name=\"SIGINT\",signal-meaning=\"Interrupt\",frame={%s},thread-id=\"%d\",stopped-threads=\"all\""
1016         const CMICmnMIValueConst miValueConst("signal-received");
1017         const CMICmnMIValueResult miValueResult("reason", miValueConst);
1018         CMICmnMIOutOfBandRecord miOutOfBandRecord(CMICmnMIOutOfBandRecord::eOutOfBand_Stopped, miValueResult);
1019         const CMICmnMIValueConst miValueConst2("SIGINT");
1020         const CMICmnMIValueResult miValueResult2("signal-name", miValueConst2);
1021         bOk = miOutOfBandRecord.Add(miValueResult2);
1022         const CMICmnMIValueConst miValueConst3("Interrupt");
1023         const CMICmnMIValueResult miValueResult3("signal-meaning", miValueConst3);
1024         bOk = bOk && miOutOfBandRecord.Add(miValueResult3);
1025         CMICmnMIValueTuple miValueTuple;
1026         bOk = bOk && MiHelpGetCurrentThreadFrame(miValueTuple);
1027         const CMICmnMIValueResult miValueResult4("frame", miValueTuple);
1028         bOk = bOk && miOutOfBandRecord.Add(miValueResult4);
1029         const CMIUtilString strThreadId(CMIUtilString::Format("%" PRIu32, sbProcess.GetSelectedThread().GetIndexID()));
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 && CMICmnStreamStdout::WritePrompt();
1038     }
1039     else if (nStopReason == m_SIGSTOP)
1040     {
1041         // MI print "*stopped,reason=\"signal-received\",signal-name=\"SIGSTOP\",signal-meaning=\"Stop\",frame={%s},thread-id=\"%d\",stopped-threads=\"all\""
1042         const CMICmnMIValueConst miValueConst("signal-received");
1043         const CMICmnMIValueResult miValueResult("reason", miValueConst);
1044         CMICmnMIOutOfBandRecord miOutOfBandRecord(CMICmnMIOutOfBandRecord::eOutOfBand_Stopped, miValueResult);
1045         const CMICmnMIValueConst miValueConst2("SIGSTOP");
1046         const CMICmnMIValueResult miValueResult2("signal-name", miValueConst2);
1047         bOk = miOutOfBandRecord.Add(miValueResult2);
1048         const CMICmnMIValueConst miValueConst3("Stop");
1049         const CMICmnMIValueResult miValueResult3("signal-meaning", miValueConst3);
1050         bOk = bOk && miOutOfBandRecord.Add(miValueResult3);
1051         CMICmnMIValueTuple miValueTuple;
1052         bOk = bOk && MiHelpGetCurrentThreadFrame(miValueTuple);
1053         const CMICmnMIValueResult miValueResult4("frame", miValueTuple);
1054         bOk = bOk && miOutOfBandRecord.Add(miValueResult4);
1055         const CMIUtilString strThreadId(CMIUtilString::Format("%" PRIu32, sbProcess.GetSelectedThread().GetIndexID()));
1056         const CMICmnMIValueConst miValueConst5(strThreadId);
1057         const CMICmnMIValueResult miValueResult5("thread-id", miValueConst5);
1058         bOk = bOk && miOutOfBandRecord.Add(miValueResult5);
1059         const CMICmnMIValueConst miValueConst6("all");
1060         const CMICmnMIValueResult miValueResult6("stopped-threads", miValueConst6);
1061         bOk = bOk && miOutOfBandRecord.Add(miValueResult6);
1062         bOk = bOk && MiOutOfBandRecordToStdout(miOutOfBandRecord);
1063         bOk = bOk && CMICmnStreamStdout::WritePrompt();
1064     }
1065     else if (nStopReason == m_SIGSEGV)
1066     {
1067         // MI print "*stopped,reason=\"signal-received\",signal-name=\"SIGSEGV\",signal-meaning=\"Segmentation fault\",thread-id=\"%d\",frame={%s}"
1068         const CMICmnMIValueConst miValueConst("signal-received");
1069         const CMICmnMIValueResult miValueResult("reason", miValueConst);
1070         CMICmnMIOutOfBandRecord miOutOfBandRecord(CMICmnMIOutOfBandRecord::eOutOfBand_Stopped, miValueResult);
1071         const CMICmnMIValueConst miValueConst2("SIGSEGV");
1072         const CMICmnMIValueResult miValueResult2("signal-name", miValueConst2);
1073         bOk = miOutOfBandRecord.Add(miValueResult2);
1074         const CMICmnMIValueConst miValueConst3("Segmentation fault");
1075         const CMICmnMIValueResult miValueResult3("signal-meaning", miValueConst3);
1076         bOk = bOk && miOutOfBandRecord.Add(miValueResult3);
1077         CMICmnMIValueTuple miValueTuple;
1078         bOk = bOk && MiHelpGetCurrentThreadFrame(miValueTuple);
1079         const CMICmnMIValueResult miValueResult4("frame", miValueTuple);
1080         bOk = bOk && miOutOfBandRecord.Add(miValueResult4);
1081         const CMIUtilString strThreadId(CMIUtilString::Format("%d", sbProcess.GetSelectedThread().GetIndexID()));
1082         const CMICmnMIValueConst miValueConst5(strThreadId);
1083         const CMICmnMIValueResult miValueResult5("thread-id", miValueConst5);
1084         bOk = bOk && miOutOfBandRecord.Add(miValueResult5);
1085         bOk = bOk && MiOutOfBandRecordToStdout(miOutOfBandRecord);
1086         // Note no "(gdb)" output here
1087     }
1088     else if (nStopReason == m_SIGTRAP)
1089     {
1090         lldb::SBThread thread = sbProcess.GetSelectedThread();
1091         const MIuint nFrames = thread.GetNumFrames();
1092         if (nFrames > 0)
1093         {
1094             lldb::SBFrame frame = thread.GetFrameAtIndex(0);
1095             const char *pFnName = frame.GetFunctionName();
1096             if (pFnName != nullptr)
1097             {
1098                 const CMIUtilString fnName = CMIUtilString(pFnName);
1099                 static const CMIUtilString threadCloneFn = CMIUtilString("__pthread_clone");
1100
1101                 if (CMIUtilString::Compare(threadCloneFn, fnName))
1102                 {
1103                     if (sbProcess.IsValid())
1104                         sbProcess.Continue();
1105                 }
1106             }
1107         }
1108     }
1109     else
1110     {
1111         // MI print "*stopped,reason=\"signal-received\",signal-name=\"%s\",thread-id=\"%d\",stopped-threads=\"all\""
1112         // MI print "*stopped,reason=\"signal-received\",signal=\"%d\",thread-id=\"%d\",stopped-threads=\"all\""
1113         const CMICmnMIValueConst miValueConst("signal-received");
1114         const CMICmnMIValueResult miValueResult("reason", miValueConst);
1115         CMICmnMIOutOfBandRecord miOutOfBandRecord(CMICmnMIOutOfBandRecord::eOutOfBand_Stopped, miValueResult);
1116         lldb::SBUnixSignals sbUnixSignals = sbProcess.GetUnixSignals();
1117         const char *pSignal = sbUnixSignals.GetSignalAsCString(nStopReason);
1118         if (pSignal)
1119         {
1120             const CMICmnMIValueConst miValueConst2(pSignal);
1121             const CMICmnMIValueResult miValueResult2("signal-name", miValueConst2);
1122             bOk = miOutOfBandRecord.Add(miValueResult2);
1123         }
1124         else
1125         {
1126             const CMIUtilString strSignal(CMIUtilString::Format("%" PRIu64, nStopReason));
1127             const CMICmnMIValueConst miValueConst2(strSignal);
1128             const CMICmnMIValueResult miValueResult2("signal", miValueConst2);
1129             bOk = miOutOfBandRecord.Add(miValueResult2);
1130         }
1131         const CMIUtilString strThreadId(CMIUtilString::Format("%d", sbProcess.GetSelectedThread().GetIndexID()));
1132         const CMICmnMIValueConst miValueConst3(strThreadId);
1133         const CMICmnMIValueResult miValueResult3("thread-id", miValueConst3);
1134         bOk = bOk && miOutOfBandRecord.Add(miValueResult3);
1135         const CMICmnMIValueConst miValueConst4("all");
1136         const CMICmnMIValueResult miValueResult4("stopped-threads", miValueConst4);
1137         bOk = bOk && miOutOfBandRecord.Add(miValueResult4);
1138         bOk = bOk && MiOutOfBandRecordToStdout(miOutOfBandRecord);
1139         bOk = bOk && CMICmnStreamStdout::WritePrompt();
1140     }
1141     return bOk;
1142 }
1143
1144 //++ ------------------------------------------------------------------------------------
1145 // Details: Asynchronous event handler for LLDB Process stop exception.
1146 // Type:    Method.
1147 // Args:    None.
1148 // Return:  MIstatus::success - Functional succeeded.
1149 //          MIstatus::failure - Functional failed.
1150 // Throws:  None.
1151 //--
1152 bool
1153 CMICmnLLDBDebuggerHandleEvents::HandleProcessEventStopException(void)
1154 {
1155     const lldb::SBProcess sbProcess = CMICmnLLDBDebugSessionInfo::Instance().GetProcess();
1156     lldb::SBThread sbThread = sbProcess.GetSelectedThread();
1157     const size_t nStopDescriptionLen = sbThread.GetStopDescription(nullptr, 0);
1158     std::unique_ptr<char[]> apStopDescription(new char[nStopDescriptionLen]);
1159     sbThread.GetStopDescription(apStopDescription.get(), nStopDescriptionLen);
1160
1161     // MI print "*stopped,reason=\"exception-received\",exception=\"%s\",thread-id=\"%d\",stopped-threads=\"all\""
1162     const CMICmnMIValueConst miValueConst("exception-received");
1163     const CMICmnMIValueResult miValueResult("reason", miValueConst);
1164     CMICmnMIOutOfBandRecord miOutOfBandRecord(CMICmnMIOutOfBandRecord::eOutOfBand_Stopped, miValueResult);
1165     const CMIUtilString strReason(apStopDescription.get());
1166     const CMICmnMIValueConst miValueConst2(strReason);
1167     const CMICmnMIValueResult miValueResult2("exception", miValueConst2);
1168     bool bOk = miOutOfBandRecord.Add(miValueResult2);
1169     const CMIUtilString strThreadId(CMIUtilString::Format("%d", sbThread.GetIndexID()));
1170     const CMICmnMIValueConst miValueConst3(strThreadId);
1171     const CMICmnMIValueResult miValueResult3("thread-id", miValueConst3);
1172     bOk = bOk && miOutOfBandRecord.Add(miValueResult3);
1173     const CMICmnMIValueConst miValueConst4("all");
1174     const CMICmnMIValueResult miValueResult4("stopped-threads", miValueConst4);
1175     bOk = bOk && miOutOfBandRecord.Add(miValueResult4);
1176     bOk = bOk && MiOutOfBandRecordToStdout(miOutOfBandRecord);
1177     bOk = bOk && CMICmnStreamStdout::WritePrompt();
1178
1179     return bOk;
1180 }
1181
1182 //++ ------------------------------------------------------------------------------------
1183 // Details: Form partial MI response in a MI value tuple object.
1184 // Type:    Method.
1185 // Args:    vwrMiValueTuple   - (W) MI value tuple object.
1186 // Return:  MIstatus::success - Functionality succeeded.
1187 //          MIstatus::failure - Functionality failed.
1188 // Throws:  None.
1189 //--
1190 bool
1191 CMICmnLLDBDebuggerHandleEvents::MiHelpGetCurrentThreadFrame(CMICmnMIValueTuple &vwrMiValueTuple)
1192 {
1193     CMIUtilString strThreadFrame;
1194     lldb::SBProcess sbProcess = CMICmnLLDBDebugSessionInfo::Instance().GetProcess();
1195     lldb::SBThread thread = sbProcess.GetSelectedThread();
1196     const MIuint nFrame = thread.GetNumFrames();
1197     if (nFrame == 0)
1198     {
1199         // MI print "addr=\"??\",func=\"??\",file=\"??\",fullname=\"??\",line=\"??\""
1200         const CMICmnMIValueConst miValueConst("??");
1201         const CMICmnMIValueResult miValueResult("addr", miValueConst);
1202         CMICmnMIValueTuple miValueTuple(miValueResult);
1203         const CMICmnMIValueResult miValueResult2("func", miValueConst);
1204         miValueTuple.Add(miValueResult2);
1205         const CMICmnMIValueResult miValueResult4("file", miValueConst);
1206         miValueTuple.Add(miValueResult4);
1207         const CMICmnMIValueResult miValueResult5("fullname", miValueConst);
1208         miValueTuple.Add(miValueResult5);
1209         const CMICmnMIValueResult miValueResult6("line", miValueConst);
1210         miValueTuple.Add(miValueResult6);
1211
1212         vwrMiValueTuple = miValueTuple;
1213
1214         return MIstatus::success;
1215     }
1216
1217     CMICmnMIValueTuple miValueTuple;
1218     if (!CMICmnLLDBDebugSessionInfo::Instance().MIResponseFormFrameInfo(thread, 0, CMICmnLLDBDebugSessionInfo::eFrameInfoFormat_NoArguments, miValueTuple))
1219     {
1220         SetErrorDescription(CMIUtilString::Format(MIRSRC(IDS_LLDBOUTOFBAND_ERR_FORM_MI_RESPONSE), "MiHelpGetCurrentThreadFrame()"));
1221         return MIstatus::failure;
1222     }
1223
1224     vwrMiValueTuple = miValueTuple;
1225
1226     return MIstatus::success;
1227 }
1228
1229 //++ ------------------------------------------------------------------------------------
1230 // Details: Asynchronous event handler for LLDB Process stop reason breakpoint.
1231 // Type:    Method.
1232 // Args:    None.
1233 // Return:  MIstatus::success - Functionality succeeded.
1234 //          MIstatus::failure - Functionality failed.
1235 // Throws:  None.
1236 //--
1237 bool
1238 CMICmnLLDBDebuggerHandleEvents::HandleProcessEventStopReasonBreakpoint(void)
1239 {
1240     // CODETAG_DEBUG_SESSION_RUNNING_PROG_RECEIVED_SIGINT_PAUSE_PROGRAM
1241     if (!CMIDriver::Instance().SetDriverStateRunningNotDebugging())
1242     {
1243         const CMIUtilString &rErrMsg(CMIDriver::Instance().GetErrorDescription());
1244         SetErrorDescription(CMIUtilString::Format(MIRSRC(IDS_LLDBOUTOFBAND_ERR_SETNEWDRIVERSTATE),
1245                                                   "HandleProcessEventStopReasonBreakpoint()", rErrMsg.c_str()));
1246         return MIstatus::failure;
1247     }
1248
1249     lldb::SBProcess sbProcess = CMICmnLLDBDebugSessionInfo::Instance().GetProcess();
1250     const MIuint64 brkPtId = sbProcess.GetSelectedThread().GetStopReasonDataAtIndex(0);
1251     lldb::SBBreakpoint brkPt = CMICmnLLDBDebugSessionInfo::Instance().GetTarget().GetBreakpointAtIndex((MIuint)brkPtId);
1252
1253     return MiStoppedAtBreakPoint(brkPtId, brkPt);
1254 }
1255
1256 //++ ------------------------------------------------------------------------------------
1257 // Details: Form the MI Out-of-band response for stopped reason on hitting a break point.
1258 // Type:    Method.
1259 // Args:    vBrkPtId    - (R) The LLDB break point's ID
1260 //          vBrkPt      - (R) THe LLDB break point object.
1261 // Return:  MIstatus::success - Functionality succeeded.
1262 //          MIstatus::failure - Functionality failed.
1263 // Throws:  None.
1264 //--
1265 bool
1266 CMICmnLLDBDebuggerHandleEvents::MiStoppedAtBreakPoint(const MIuint64 vBrkPtId, const lldb::SBBreakpoint &vBrkPt)
1267 {
1268     bool bOk = MIstatus::success;
1269
1270     lldb::SBProcess sbProcess = CMICmnLLDBDebugSessionInfo::Instance().GetProcess();
1271     lldb::SBThread thread = sbProcess.GetSelectedThread();
1272     const MIuint nFrame = thread.GetNumFrames();
1273     if (nFrame == 0)
1274     {
1275         // MI print "*stopped,reason=\"breakpoint-hit\",disp=\"del\",bkptno=\"%d\",frame={},thread-id=\"%d\",stopped-threads=\"all\""
1276         const CMICmnMIValueConst miValueConst("breakpoint-hit");
1277         const CMICmnMIValueResult miValueResult("reason", miValueConst);
1278         CMICmnMIOutOfBandRecord miOutOfBandRecord(CMICmnMIOutOfBandRecord::eOutOfBand_Stopped, miValueResult);
1279         const CMICmnMIValueConst miValueConst2("del");
1280         const CMICmnMIValueResult miValueResult2("disp", miValueConst2);
1281         bOk = miOutOfBandRecord.Add(miValueResult2);
1282         const CMIUtilString strBkp(CMIUtilString::Format("%d", vBrkPtId));
1283         const CMICmnMIValueConst miValueConst3(strBkp);
1284         CMICmnMIValueResult miValueResult3("bkptno", miValueConst3);
1285         bOk = bOk && miOutOfBandRecord.Add(miValueResult3);
1286         const CMICmnMIValueConst miValueConst4("{}");
1287         const CMICmnMIValueResult miValueResult4("frame", miValueConst4);
1288         bOk = bOk && miOutOfBandRecord.Add(miValueResult4);
1289         const CMIUtilString strThreadId(CMIUtilString::Format("%d", vBrkPt.GetThreadIndex()));
1290         const CMICmnMIValueConst miValueConst5(strThreadId);
1291         const CMICmnMIValueResult miValueResult5("thread-id", miValueConst5);
1292         bOk = bOk && miOutOfBandRecord.Add(miValueResult5);
1293         const CMICmnMIValueConst miValueConst6("all");
1294         const CMICmnMIValueResult miValueResult6("stopped-threads", miValueConst6);
1295         bOk = bOk && miOutOfBandRecord.Add(miValueResult6);
1296         bOk = bOk && MiOutOfBandRecordToStdout(miOutOfBandRecord);
1297         bOk = bOk && CMICmnStreamStdout::WritePrompt();
1298         return bOk;
1299     }
1300
1301     CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance());
1302
1303     // MI print
1304     // "*stopped,reason=\"breakpoint-hit\",disp=\"del\",bkptno=\"%d\",frame={addr=\"0x%016" PRIx64 "\",func=\"%s\",args=[],file=\"%s\",fullname=\"%s\",line=\"%d\"},thread-id=\"%d\",stopped-threads=\"all\""
1305     const CMICmnMIValueConst miValueConst("breakpoint-hit");
1306     const CMICmnMIValueResult miValueResult("reason", miValueConst);
1307     CMICmnMIOutOfBandRecord miOutOfBandRecord(CMICmnMIOutOfBandRecord::eOutOfBand_Stopped, miValueResult);
1308     const CMICmnMIValueConst miValueConstA("del");
1309     const CMICmnMIValueResult miValueResultA("disp", miValueConstA);
1310     bOk = miOutOfBandRecord.Add(miValueResultA);
1311     const CMIUtilString strBkp(CMIUtilString::Format("%d", vBrkPtId));
1312     const CMICmnMIValueConst miValueConstB(strBkp);
1313     CMICmnMIValueResult miValueResultB("bkptno", miValueConstB);
1314     bOk = bOk && miOutOfBandRecord.Add(miValueResultB);
1315
1316     // frame={addr=\"0x%016" PRIx64 "\",func=\"%s\",args=[],file=\"%s\",fullname=\"%s\",line=\"%d\"}
1317     if (bOk)
1318     {
1319         CMICmnMIValueTuple miValueTuple;
1320         bOk = bOk && rSessionInfo.MIResponseFormFrameInfo(thread, 0, CMICmnLLDBDebugSessionInfo::eFrameInfoFormat_AllArguments, miValueTuple);
1321         const CMICmnMIValueResult miValueResult8("frame", miValueTuple);
1322         bOk = bOk && miOutOfBandRecord.Add(miValueResult8);
1323     }
1324
1325     // Add to MI thread-id=\"%d\",stopped-threads=\"all\"
1326     if (bOk)
1327     {
1328         const CMIUtilString strThreadId(CMIUtilString::Format("%d", thread.GetIndexID()));
1329         const CMICmnMIValueConst miValueConst8(strThreadId);
1330         const CMICmnMIValueResult miValueResult8("thread-id", miValueConst8);
1331         bOk = miOutOfBandRecord.Add(miValueResult8);
1332     }
1333     if (bOk)
1334     {
1335         const CMICmnMIValueConst miValueConst9("all");
1336         const CMICmnMIValueResult miValueResult9("stopped-threads", miValueConst9);
1337         bOk = miOutOfBandRecord.Add(miValueResult9);
1338         bOk = MiOutOfBandRecordToStdout(miOutOfBandRecord);
1339         bOk = bOk && CMICmnStreamStdout::WritePrompt();
1340     }
1341
1342     return MIstatus::success;
1343 }
1344
1345 //++ ------------------------------------------------------------------------------------
1346 // Details: Asynchronous event handler for LLDB Process stop reason trace.
1347 // Type:    Method.
1348 // Args:    None.
1349 // Return:  MIstatus::success - Functionality succeeded.
1350 //          MIstatus::failure - Functionality failed.
1351 // Throws:  None.
1352 //--
1353 bool
1354 CMICmnLLDBDebuggerHandleEvents::HandleProcessEventStopReasonTrace(void)
1355 {
1356     bool bOk = true;
1357     lldb::SBProcess sbProcess = CMICmnLLDBDebugSessionInfo::Instance().GetProcess();
1358     lldb::SBThread thread = sbProcess.GetSelectedThread();
1359     const MIuint nFrame = thread.GetNumFrames();
1360     if (nFrame == 0)
1361     {
1362         // MI print "*stopped,reason=\"trace\",stopped-threads=\"all\""
1363         const CMICmnMIValueConst miValueConst("trace");
1364         const CMICmnMIValueResult miValueResult("reason", miValueConst);
1365         CMICmnMIOutOfBandRecord miOutOfBandRecord(CMICmnMIOutOfBandRecord::eOutOfBand_Stopped, miValueResult);
1366         const CMICmnMIValueConst miValueConst2("all");
1367         const CMICmnMIValueResult miValueResult2("stopped-threads", miValueConst2);
1368         bOk = miOutOfBandRecord.Add(miValueResult2);
1369         bOk = MiOutOfBandRecordToStdout(miOutOfBandRecord);
1370         bOk = bOk && CMICmnStreamStdout::WritePrompt();
1371         return bOk;
1372     }
1373
1374     CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance());
1375
1376     // MI print
1377     // "*stopped,reason=\"end-stepping-range\",frame={addr=\"0x%016" PRIx64 "\",func=\"%s\",args=[\"%s\"],file=\"%s\",fullname=\"%s\",line=\"%d\"},thread-id=\"%d\",stopped-threads=\"all\""
1378
1379     // Function args
1380     CMICmnMIValueTuple miValueTuple;
1381     if (!rSessionInfo.MIResponseFormFrameInfo(thread, 0, CMICmnLLDBDebugSessionInfo::eFrameInfoFormat_AllArguments, miValueTuple))
1382         return MIstatus::failure;
1383
1384     const CMICmnMIValueConst miValueConst("end-stepping-range");
1385     const CMICmnMIValueResult miValueResult("reason", miValueConst);
1386     CMICmnMIOutOfBandRecord miOutOfBandRecord(CMICmnMIOutOfBandRecord::eOutOfBand_Stopped, miValueResult);
1387     const CMICmnMIValueResult miValueResult2("frame", miValueTuple);
1388     bOk = miOutOfBandRecord.Add(miValueResult2);
1389
1390     // Add to MI thread-id=\"%d\",stopped-threads=\"all\"
1391     if (bOk)
1392     {
1393         const CMIUtilString strThreadId(CMIUtilString::Format("%d", thread.GetIndexID()));
1394         const CMICmnMIValueConst miValueConst8(strThreadId);
1395         const CMICmnMIValueResult miValueResult8("thread-id", miValueConst8);
1396         bOk = miOutOfBandRecord.Add(miValueResult8);
1397     }
1398     if (bOk)
1399     {
1400         const CMICmnMIValueConst miValueConst9("all");
1401         const CMICmnMIValueResult miValueResult9("stopped-threads", miValueConst9);
1402         bOk = miOutOfBandRecord.Add(miValueResult9);
1403         bOk = MiOutOfBandRecordToStdout(miOutOfBandRecord);
1404         bOk = bOk && CMICmnStreamStdout::WritePrompt();
1405     }
1406
1407     return bOk;
1408 }
1409
1410 //++ ------------------------------------------------------------------------------------
1411 // Details: Asynchronous function update selected thread.
1412 // Type:    Method.
1413 // Args:    None.
1414 // Return:  MIstatus::success - Functionality succeeded.
1415 //          MIstatus::failure - Functionality failed.
1416 // Throws:  None.
1417 //--
1418 bool
1419 CMICmnLLDBDebuggerHandleEvents::UpdateSelectedThread(void)
1420 {
1421     lldb::SBProcess process = CMICmnLLDBDebugSessionInfo::Instance().GetDebugger().GetSelectedTarget().GetProcess();
1422     if (!process.IsValid())
1423         return MIstatus::success;
1424
1425     lldb::SBThread currentThread = process.GetSelectedThread();
1426     lldb::SBThread thread;
1427     const lldb::StopReason eCurrentThreadStoppedReason = currentThread.GetStopReason();
1428     if (!currentThread.IsValid() || (eCurrentThreadStoppedReason == lldb::eStopReasonInvalid) ||
1429         (eCurrentThreadStoppedReason == lldb::eStopReasonNone))
1430     {
1431         // Prefer a thread that has just completed its plan over another thread as current thread
1432         lldb::SBThread planThread;
1433         lldb::SBThread otherThread;
1434         const size_t nThread = process.GetNumThreads();
1435         for (MIuint i = 0; i < nThread; i++)
1436         {
1437             //  GetThreadAtIndex() uses a base 0 index
1438             //  GetThreadByIndexID() uses a base 1 index
1439             thread = process.GetThreadAtIndex(i);
1440             const lldb::StopReason eThreadStopReason = thread.GetStopReason();
1441             switch (eThreadStopReason)
1442             {
1443                 case lldb::eStopReasonTrace:
1444                 case lldb::eStopReasonBreakpoint:
1445                 case lldb::eStopReasonWatchpoint:
1446                 case lldb::eStopReasonSignal:
1447                 case lldb::eStopReasonException:
1448                     if (!otherThread.IsValid())
1449                         otherThread = thread;
1450                     break;
1451                 case lldb::eStopReasonPlanComplete:
1452                     if (!planThread.IsValid())
1453                         planThread = thread;
1454                     break;
1455                 case lldb::eStopReasonInvalid:
1456                 case lldb::eStopReasonNone:
1457                 default:
1458                     break;
1459             }
1460         }
1461         if (planThread.IsValid())
1462             process.SetSelectedThread(planThread);
1463         else if (otherThread.IsValid())
1464             process.SetSelectedThread(otherThread);
1465         else
1466         {
1467             if (currentThread.IsValid())
1468                 thread = currentThread;
1469             else
1470                 thread = process.GetThreadAtIndex(0);
1471
1472             if (thread.IsValid())
1473                 process.SetSelectedThread(thread);
1474         }
1475     } // if( !currentThread.IsValid() || (eCurrentThreadStoppedReason == lldb::eStopReasonInvalid) || (eCurrentThreadStoppedReason ==
1476       // lldb::eStopReasonNone) )
1477
1478     return MIstatus::success;
1479 }
1480
1481 //++ ------------------------------------------------------------------------------------
1482 // Details: Print to stdout "*running,thread-id=\"all\"", "(gdb)".
1483 // Type:    Method.
1484 // Args:    None.
1485 // Return:  MIstatus::success - Functionality succeeded.
1486 //          MIstatus::failure - Functionality failed.
1487 // Throws:  None.
1488 //--
1489 bool
1490 CMICmnLLDBDebuggerHandleEvents::HandleProcessEventStateRunning(void)
1491 {
1492     CMICmnMIValueConst miValueConst("all");
1493     CMICmnMIValueResult miValueResult("thread-id", miValueConst);
1494     CMICmnMIOutOfBandRecord miOutOfBandRecord(CMICmnMIOutOfBandRecord::eOutOfBand_Running, miValueResult);
1495     bool bOk = MiOutOfBandRecordToStdout(miOutOfBandRecord);
1496     bOk = bOk && CMICmnStreamStdout::WritePrompt();
1497
1498     return bOk;
1499 }
1500
1501 //++ ------------------------------------------------------------------------------------
1502 // Details: Print to stdout "=thread-exited,id=\"%ld\",group-id=\"i1\"",
1503 //                          "=thread-group-exited,id=\"i1\",exit-code=\"0\""),
1504 //                          "*stopped,reason=\"exited-normally\"",
1505 //                          "(gdb)"
1506 // Type:    Method.
1507 // Args:    None.
1508 // Return:  MIstatus::success - Functionality succeeded.
1509 //          MIstatus::failure - Functionality failed.
1510 // Throws:  None.
1511 //--
1512 bool
1513 CMICmnLLDBDebuggerHandleEvents::HandleProcessEventStateExited(void)
1514 {
1515     const CMIUtilString strId(CMIUtilString::Format("%ld", 1));
1516     CMICmnMIValueConst miValueConst(strId);
1517     CMICmnMIValueResult miValueResult("id", miValueConst);
1518     CMICmnMIOutOfBandRecord miOutOfBandRecord(CMICmnMIOutOfBandRecord::eOutOfBand_ThreadExited, miValueResult);
1519     CMICmnMIValueConst miValueConst2("i1");
1520     CMICmnMIValueResult miValueResult2("group-id", miValueConst2);
1521     bool bOk = miOutOfBandRecord.Add(miValueResult2);
1522     bOk = bOk && MiOutOfBandRecordToStdout(miOutOfBandRecord);
1523     if (bOk)
1524     {
1525         CMICmnMIValueConst miValueConst3("i1");
1526         CMICmnMIValueResult miValueResult3("id", miValueConst3);
1527         CMICmnMIOutOfBandRecord miOutOfBandRecord2(CMICmnMIOutOfBandRecord::eOutOfBand_ThreadGroupExited, miValueResult3);
1528         CMICmnMIValueConst miValueConst2("0");
1529         CMICmnMIValueResult miValueResult2("exit-code", miValueConst2);
1530         bOk = miOutOfBandRecord2.Add(miValueResult2);
1531         bOk = bOk && MiOutOfBandRecordToStdout(miOutOfBandRecord2);
1532     }
1533     if (bOk)
1534     {
1535         CMICmnMIValueConst miValueConst4("exited-normally");
1536         CMICmnMIValueResult miValueResult4("reason", miValueConst4);
1537         CMICmnMIOutOfBandRecord miOutOfBandRecord3(CMICmnMIOutOfBandRecord::eOutOfBand_Stopped, miValueResult4);
1538         bOk = MiOutOfBandRecordToStdout(miOutOfBandRecord3);
1539     }
1540     bOk = bOk && CMICmnStreamStdout::WritePrompt();
1541
1542     return bOk;
1543 }
1544
1545 //++ ------------------------------------------------------------------------------------
1546 // Details: Drain all stdout so we don't see any output come after we print our prompts.
1547 //          The process has stuff waiting for stdout; get it and write it out to the
1548 //          appropriate place.
1549 // Type:    Method.
1550 // Args:    None.
1551 // Return:  MIstatus::success - Functionality succeeded.
1552 //          MIstatus::failure - Functionality failed.
1553 // Throws:  None.
1554 //--
1555 bool
1556 CMICmnLLDBDebuggerHandleEvents::GetProcessStdout(void)
1557 {
1558     CMIUtilString text;
1559     std::unique_ptr<char[]> apStdoutBuffer(new char[1024]);
1560     lldb::SBProcess process = CMICmnLLDBDebugSessionInfo::Instance().GetDebugger().GetSelectedTarget().GetProcess();
1561     while (1)
1562     {
1563         const size_t nBytes = process.GetSTDOUT(apStdoutBuffer.get(), 1024);
1564         text.append(apStdoutBuffer.get(), nBytes);
1565
1566         while (1)
1567         {
1568             const size_t nNewLine = text.find('\n');
1569             if (nNewLine == std::string::npos)
1570                 break;
1571
1572             const CMIUtilString line(text.substr(0, nNewLine + 1).c_str());
1573             text.erase(0, nNewLine + 1);
1574             const bool bEscapeQuotes(true);
1575             CMICmnMIValueConst miValueConst(line.Escape(bEscapeQuotes));
1576             CMICmnMIOutOfBandRecord miOutOfBandRecord(CMICmnMIOutOfBandRecord::eOutOfBand_TargetStreamOutput, miValueConst);
1577             const bool bOk = MiOutOfBandRecordToStdout(miOutOfBandRecord);
1578             if (!bOk)
1579                 return MIstatus::failure;
1580         }
1581
1582         if (nBytes == 0)
1583         {
1584             if (!text.empty())
1585             {
1586                 const bool bEscapeQuotes(true);
1587                 CMICmnMIValueConst miValueConst(text.Escape(bEscapeQuotes));
1588                 CMICmnMIOutOfBandRecord miOutOfBandRecord(CMICmnMIOutOfBandRecord::eOutOfBand_TargetStreamOutput, miValueConst);
1589                 return MiOutOfBandRecordToStdout(miOutOfBandRecord);
1590             }
1591             break;
1592         }
1593     }
1594
1595     return MIstatus::success;
1596 }
1597
1598 //++ ------------------------------------------------------------------------------------
1599 // Details: Drain all stderr so we don't see any output come after we print our prompts.
1600 //          The process has stuff waiting for stderr; get it and write it out to the
1601 //          appropriate place.
1602 // Type:    Method.
1603 // Args:    None.
1604 // Return:  MIstatus::success - Functionality succeeded.
1605 //          MIstatus::failure - Functionality failed.
1606 // Throws:  None.
1607 //--
1608 bool
1609 CMICmnLLDBDebuggerHandleEvents::GetProcessStderr(void)
1610 {
1611     CMIUtilString text;
1612     std::unique_ptr<char[]> apStderrBuffer(new char[1024]);
1613     lldb::SBProcess process = CMICmnLLDBDebugSessionInfo::Instance().GetDebugger().GetSelectedTarget().GetProcess();
1614     while (1)
1615     {
1616         const size_t nBytes = process.GetSTDERR(apStderrBuffer.get(), 1024);
1617         text.append(apStderrBuffer.get(), nBytes);
1618
1619         while (1)
1620         {
1621             const size_t nNewLine = text.find('\n');
1622             if (nNewLine == std::string::npos)
1623                 break;
1624
1625             const CMIUtilString line(text.substr(0, nNewLine + 1).c_str());
1626             const bool bEscapeQuotes(true);
1627             CMICmnMIValueConst miValueConst(line.Escape(bEscapeQuotes));
1628             CMICmnMIOutOfBandRecord miOutOfBandRecord(CMICmnMIOutOfBandRecord::eOutOfBand_TargetStreamOutput, miValueConst);
1629             const bool bOk = MiOutOfBandRecordToStdout(miOutOfBandRecord);
1630             if (!bOk)
1631                 return MIstatus::failure;
1632         }
1633
1634         if (nBytes == 0)
1635         {
1636             if (!text.empty())
1637             {
1638                 const bool bEscapeQuotes(true);
1639                 CMICmnMIValueConst miValueConst(text.Escape(bEscapeQuotes));
1640                 CMICmnMIOutOfBandRecord miOutOfBandRecord(CMICmnMIOutOfBandRecord::eOutOfBand_TargetStreamOutput, miValueConst);
1641                 return MiOutOfBandRecordToStdout(miOutOfBandRecord);
1642             }
1643             break;
1644         }
1645     }
1646
1647     return MIstatus::success;
1648 }
1649
1650 //++ ------------------------------------------------------------------------------------
1651 // Details: Asynchronous event function check for state changes.
1652 // Type:    Method.
1653 // Args:    None.
1654 // Return:  MIstatus::success - Functionality succeeded.
1655 //          MIstatus::failure - Functionality failed.
1656 // Throws:  None.
1657 //--
1658 bool
1659 CMICmnLLDBDebuggerHandleEvents::ChkForStateChanges(void)
1660 {
1661     CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance());
1662     lldb::SBProcess sbProcess = rSessionInfo.GetProcess();
1663     if (!sbProcess.IsValid())
1664         return MIstatus::success;
1665
1666     // Check for created threads
1667     const MIuint nThread = sbProcess.GetNumThreads();
1668     for (MIuint i = 0; i < nThread; i++)
1669     {
1670         //  GetThreadAtIndex() uses a base 0 index
1671         //  GetThreadByIndexID() uses a base 1 index
1672         lldb::SBThread thread = sbProcess.GetThreadAtIndex(i);
1673         if (!thread.IsValid())
1674             continue;
1675
1676         const MIuint threadIndexID = thread.GetIndexID();
1677         const bool bFound = std::find(rSessionInfo.m_vecActiveThreadId.cbegin(), rSessionInfo.m_vecActiveThreadId.cend(), threadIndexID) != rSessionInfo.m_vecActiveThreadId.end();
1678         if (!bFound)
1679         {
1680             rSessionInfo.m_vecActiveThreadId.push_back(threadIndexID);
1681
1682             // Form MI "=thread-created,id=\"%d\",group-id=\"i1\""
1683             const CMIUtilString strValue(CMIUtilString::Format("%d", threadIndexID));
1684             const CMICmnMIValueConst miValueConst(strValue);
1685             const CMICmnMIValueResult miValueResult("id", miValueConst);
1686             CMICmnMIOutOfBandRecord miOutOfBand(CMICmnMIOutOfBandRecord::eOutOfBand_ThreadCreated, miValueResult);
1687             const CMICmnMIValueConst miValueConst2("i1");
1688             const CMICmnMIValueResult miValueResult2("group-id", miValueConst2);
1689             bool bOk = miOutOfBand.Add(miValueResult2);
1690             bOk = bOk && MiOutOfBandRecordToStdout(miOutOfBand);
1691             if (!bOk)
1692                 return MIstatus::failure;
1693         }
1694     }
1695
1696     lldb::SBThread currentThread = sbProcess.GetSelectedThread();
1697     if (currentThread.IsValid())
1698     {
1699         const MIuint currentThreadIndexID = currentThread.GetIndexID();
1700         if (rSessionInfo.m_currentSelectedThread != currentThreadIndexID)
1701         {
1702             rSessionInfo.m_currentSelectedThread = currentThreadIndexID;
1703
1704             // Form MI "=thread-selected,id=\"%d\""
1705             const CMIUtilString strValue(CMIUtilString::Format("%d", currentThreadIndexID));
1706             const CMICmnMIValueConst miValueConst(strValue);
1707             const CMICmnMIValueResult miValueResult("id", miValueConst);
1708             CMICmnMIOutOfBandRecord miOutOfBand(CMICmnMIOutOfBandRecord::eOutOfBand_ThreadSelected, miValueResult);
1709             if (!MiOutOfBandRecordToStdout(miOutOfBand))
1710                 return MIstatus::failure;
1711         }
1712     }
1713
1714     // Check for invalid (removed) threads
1715     CMICmnLLDBDebugSessionInfo::VecActiveThreadId_t::iterator it = rSessionInfo.m_vecActiveThreadId.begin();
1716     while (it != rSessionInfo.m_vecActiveThreadId.end())
1717     {
1718         const MIuint threadIndexID = *it;
1719         lldb::SBThread thread = sbProcess.GetThreadByIndexID(threadIndexID);
1720         if (!thread.IsValid())
1721         {
1722             // Form MI "=thread-exited,id=\"%ld\",group-id=\"i1\""
1723             const CMIUtilString strValue(CMIUtilString::Format("%ld", threadIndexID));
1724             const CMICmnMIValueConst miValueConst(strValue);
1725             const CMICmnMIValueResult miValueResult("id", miValueConst);
1726             CMICmnMIOutOfBandRecord miOutOfBand(CMICmnMIOutOfBandRecord::eOutOfBand_ThreadExited, miValueResult);
1727             const CMICmnMIValueConst miValueConst2("i1");
1728             const CMICmnMIValueResult miValueResult2("group-id", miValueConst2);
1729             bool bOk = miOutOfBand.Add(miValueResult2);
1730             bOk = bOk && MiOutOfBandRecordToStdout(miOutOfBand);
1731             if (!bOk)
1732                 return MIstatus::failure;
1733
1734             // Remove current thread from cache and get next
1735             it = rSessionInfo.m_vecActiveThreadId.erase(it);
1736         }
1737         else
1738             // Next
1739             ++it;
1740     }
1741
1742     return CMICmnStreamStdout::WritePrompt();
1743 }
1744
1745 //++ ------------------------------------------------------------------------------------
1746 // Details: Take a fully formed MI result record and send to the stdout stream.
1747 //          Also output to the MI Log file.
1748 // Type:    Method.
1749 // Args:    vrMiResultRecord  - (R) MI result record object.
1750 // Return:  MIstatus::success - Functionality succeeded.
1751 //          MIstatus::failure - Functionality failed.
1752 // Throws:  None.
1753 //--
1754 bool
1755 CMICmnLLDBDebuggerHandleEvents::MiResultRecordToStdout(const CMICmnMIResultRecord &vrMiResultRecord)
1756 {
1757     return TextToStdout(vrMiResultRecord.GetString());
1758 }
1759
1760 //++ ------------------------------------------------------------------------------------
1761 // Details: Take a fully formed MI Out-of-band record and send to the stdout stream.
1762 //          Also output to the MI Log file.
1763 // Type:    Method.
1764 // Args:    vrMiOutOfBandRecord - (R) MI Out-of-band record object.
1765 // Return:  MIstatus::success - Functionality succeeded.
1766 //          MIstatus::failure - Functionality failed.
1767 // Throws:  None.
1768 //--
1769 bool
1770 CMICmnLLDBDebuggerHandleEvents::MiOutOfBandRecordToStdout(const CMICmnMIOutOfBandRecord &vrMiOutOfBandRecord)
1771 {
1772     return TextToStdout(vrMiOutOfBandRecord.GetString());
1773 }
1774
1775 //++ ------------------------------------------------------------------------------------
1776 // Details: Take a text data and send to the stdout stream. Also output to the MI Log
1777 //          file.
1778 // Type:    Method.
1779 // Args:    vrTxt   - (R) Text.
1780 // Return:  MIstatus::success - Functionality succeeded.
1781 //          MIstatus::failure - Functionality failed.
1782 // Throws:  None.
1783 //--
1784 bool
1785 CMICmnLLDBDebuggerHandleEvents::TextToStdout(const CMIUtilString &vrTxt)
1786 {
1787     return CMICmnStreamStdout::TextToStdout(vrTxt);
1788 }
1789
1790 //++ ------------------------------------------------------------------------------------
1791 // Details: Take a text data and send to the stderr stream. Also output to the MI Log
1792 //          file.
1793 // Type:    Method.
1794 // Args:    vrTxt   - (R) Text.
1795 // Return:  MIstatus::success - Functionality succeeded.
1796 //          MIstatus::failure - Functionality failed.
1797 // Throws:  None.
1798 //--
1799 bool
1800 CMICmnLLDBDebuggerHandleEvents::TextToStderr(const CMIUtilString &vrTxt)
1801 {
1802     return CMICmnStreamStderr::TextToStderr(vrTxt);
1803 }
1804
1805 //++ ------------------------------------------------------------------------------------
1806 // Details: Initialize the member variables with the signal values in this process
1807 //          file.
1808 // Type:    Method.
1809 // Args:    None
1810 // Return:  Noen
1811 // Throws:  None.
1812 //--
1813 void
1814 CMICmnLLDBDebuggerHandleEvents::InitializeSignals()
1815 {
1816     if (!m_bSignalsInitialized)
1817     {
1818         lldb::SBProcess sbProcess = CMICmnLLDBDebugSessionInfo::Instance().GetProcess();
1819         if (sbProcess.IsValid())
1820         {
1821             lldb::SBUnixSignals unix_signals = sbProcess.GetUnixSignals();
1822             m_SIGINT = unix_signals.GetSignalNumberFromName("SIGINT");
1823             m_SIGSTOP = unix_signals.GetSignalNumberFromName("SIGSTOP");
1824             m_SIGSEGV = unix_signals.GetSignalNumberFromName("SIGSEGV");
1825             m_SIGTRAP = unix_signals.GetSignalNumberFromName("SIGTRAP");
1826             m_bSignalsInitialized = true;
1827         }
1828     }
1829 }