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