1 //===-- MICmnLLDBDebugSessionInfo.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/SBThread.h"
12 #include <inttypes.h>
13 #ifdef _WIN32
14 #include <io.h>
15 #else
16 #include <unistd.h>
17 #endif // _WIN32
18 #include "lldb/API/SBBreakpointLocation.h"
19
20 // In-house headers:
21 #include "MICmdData.h"
22 #include "MICmnLLDBDebugSessionInfo.h"
23 #include "MICmnLLDBDebugger.h"
24 #include "MICmnLLDBUtilSBValue.h"
25 #include "MICmnMIResultRecord.h"
26 #include "MICmnMIValueConst.h"
27 #include "MICmnMIValueList.h"
28 #include "MICmnMIValueTuple.h"
29 #include "MICmnResources.h"
30 #include "Platform.h"
31
32 //++
33 //------------------------------------------------------------------------------------
34 // Details: CMICmnLLDBDebugSessionInfo constructor.
35 // Type: Method.
36 // Args: None.
37 // Return: None.
38 // Throws: None.
39 //--
CMICmnLLDBDebugSessionInfo()40 CMICmnLLDBDebugSessionInfo::CMICmnLLDBDebugSessionInfo()
41 : m_nBrkPointCntMax(INT32_MAX),
42 m_currentSelectedThread(LLDB_INVALID_THREAD_ID),
43 m_constStrSharedDataKeyWkDir("Working Directory"),
44 m_constStrSharedDataSolibPath("Solib Path"),
45 m_constStrPrintCharArrayAsString("Print CharArrayAsString"),
46 m_constStrPrintExpandAggregates("Print ExpandAggregates"),
47 m_constStrPrintAggregateFieldNames("Print AggregateFieldNames") {}
48
49 //++
50 //------------------------------------------------------------------------------------
51 // Details: CMICmnLLDBDebugSessionInfo destructor.
52 // Type: Overridable.
53 // Args: None.
54 // Return: None.
55 // Throws: None.
56 //--
~CMICmnLLDBDebugSessionInfo()57 CMICmnLLDBDebugSessionInfo::~CMICmnLLDBDebugSessionInfo() { Shutdown(); }
58
59 //++
60 //------------------------------------------------------------------------------------
61 // Details: Initialize resources for *this object.
62 // Type: Method.
63 // Args: None.
64 // Return: MIstatus::success - Functionality succeeded.
65 // MIstatus::failure - Functionality failed.
66 // Throws: None.
67 //--
Initialize()68 bool CMICmnLLDBDebugSessionInfo::Initialize() {
69 m_clientUsageRefCnt++;
70
71 if (m_bInitialized)
72 return MIstatus::success;
73
74 m_currentSelectedThread = LLDB_INVALID_THREAD_ID;
75 CMICmnLLDBDebugSessionInfoVarObj::VarObjIdResetToZero();
76
77 m_bInitialized = MIstatus::success;
78
79 return m_bInitialized;
80 }
81
82 //++
83 //------------------------------------------------------------------------------------
84 // Details: Release resources for *this object.
85 // Type: Method.
86 // Args: None.
87 // Return: MIstatus::success - Functionality succeeded.
88 // MIstatus::failure - Functionality failed.
89 // Throws: None.
90 //--
Shutdown()91 bool CMICmnLLDBDebugSessionInfo::Shutdown() {
92 if (--m_clientUsageRefCnt > 0)
93 return MIstatus::success;
94
95 if (!m_bInitialized)
96 return MIstatus::success;
97
98 // Tidy up
99 SharedDataDestroy();
100
101 m_vecActiveThreadId.clear();
102 CMICmnLLDBDebugSessionInfoVarObj::VarObjClear();
103
104 m_bInitialized = false;
105
106 return MIstatus::success;
107 }
108
109 //++
110 //------------------------------------------------------------------------------------
111 // Details: Command instances can create and share data between other instances
112 // of commands.
113 // Data can also be assigned by a command and retrieved by LLDB event
114 // handler.
115 // This function takes down those resources build up over the use of
116 // the commands.
117 // This function should be called when the creation and running of
118 // command has
119 // stopped i.e. application shutdown.
120 // Type: Method.
121 // Args: None.
122 // Return: None.
123 // Throws: None.
124 //--
SharedDataDestroy()125 void CMICmnLLDBDebugSessionInfo::SharedDataDestroy() {
126 m_mapIdToSessionData.Clear();
127 m_vecVarObj.clear();
128 m_mapBrkPtIdToBrkPtInfo.clear();
129 }
130
131 //++
132 //------------------------------------------------------------------------------------
133 // Details: Record information about a LLDB break point so that is can be
134 // recalled in other
135 // commands or LLDB event handling functions.
136 // Type: Method.
137 // Args: vBrkPtId - (R) LLDB break point ID.
138 // vrBrkPtInfo - (R) Break point information object.
139 // Return: MIstatus::success - Functional succeeded.
140 // MIstatus::failure - Functional failed.
141 // Throws: None.
142 //--
RecordBrkPtInfo(const MIuint vnBrkPtId,const SBrkPtInfo & vrBrkPtInfo)143 bool CMICmnLLDBDebugSessionInfo::RecordBrkPtInfo(
144 const MIuint vnBrkPtId, const SBrkPtInfo &vrBrkPtInfo) {
145 MapPairBrkPtIdToBrkPtInfo_t pr(vnBrkPtId, vrBrkPtInfo);
146 m_mapBrkPtIdToBrkPtInfo.insert(pr);
147
148 return MIstatus::success;
149 }
150
151 //++
152 //------------------------------------------------------------------------------------
153 // Details: Retrieve information about a LLDB break point previous recorded
154 // either by
155 // commands or LLDB event handling functions.
156 // Type: Method.
157 // Args: vBrkPtId - (R) LLDB break point ID.
158 // vrwBrkPtInfo - (W) Break point information object.
159 // Return: MIstatus::success - Functional succeeded.
160 // MIstatus::failure - Functional failed.
161 // Throws: None.
162 //--
RecordBrkPtInfoGet(const MIuint vnBrkPtId,SBrkPtInfo & vrwBrkPtInfo) const163 bool CMICmnLLDBDebugSessionInfo::RecordBrkPtInfoGet(
164 const MIuint vnBrkPtId, SBrkPtInfo &vrwBrkPtInfo) const {
165 const MapBrkPtIdToBrkPtInfo_t::const_iterator it =
166 m_mapBrkPtIdToBrkPtInfo.find(vnBrkPtId);
167 if (it != m_mapBrkPtIdToBrkPtInfo.end()) {
168 vrwBrkPtInfo = (*it).second;
169 return MIstatus::success;
170 }
171
172 return MIstatus::failure;
173 }
174
175 //++
176 //------------------------------------------------------------------------------------
177 // Details: Delete information about a specific LLDB break point object. This
178 // function
179 // should be called when a LLDB break point is deleted.
180 // Type: Method.
181 // Args: vBrkPtId - (R) LLDB break point ID.
182 // Return: MIstatus::success - Functional succeeded.
183 // MIstatus::failure - Functional failed.
184 // Throws: None.
185 //--
RecordBrkPtInfoDelete(const MIuint vnBrkPtId)186 bool CMICmnLLDBDebugSessionInfo::RecordBrkPtInfoDelete(const MIuint vnBrkPtId) {
187 const MapBrkPtIdToBrkPtInfo_t::const_iterator it =
188 m_mapBrkPtIdToBrkPtInfo.find(vnBrkPtId);
189 if (it != m_mapBrkPtIdToBrkPtInfo.end()) {
190 m_mapBrkPtIdToBrkPtInfo.erase(it);
191 return MIstatus::success;
192 }
193
194 return MIstatus::failure;
195 }
196
197 //++
198 //------------------------------------------------------------------------------------
199 // Details: Retrieve the specified thread's frame information.
200 // Type: Method.
201 // Args: vCmdData - (R) A command's information.
202 // vThreadIdx - (R) Thread index.
203 // vwrThreadFrames - (W) Frame data.
204 // Return: MIstatus::success - Functional succeeded.
205 // MIstatus::failure - Functional failed.
206 // Throws: None.
207 //--
GetThreadFrames(const SMICmdData & vCmdData,const MIuint vThreadIdx,const FrameInfoFormat_e veFrameInfoFormat,CMIUtilString & vwrThreadFrames)208 bool CMICmnLLDBDebugSessionInfo::GetThreadFrames(
209 const SMICmdData &vCmdData, const MIuint vThreadIdx,
210 const FrameInfoFormat_e veFrameInfoFormat, CMIUtilString &vwrThreadFrames) {
211 lldb::SBThread thread = GetProcess().GetThreadByIndexID(vThreadIdx);
212 const uint32_t nFrames = thread.GetNumFrames();
213 if (nFrames == 0) {
214 // MI print "frame={}"
215 CMICmnMIValueTuple miValueTuple;
216 CMICmnMIValueResult miValueResult("frame", miValueTuple);
217 vwrThreadFrames = miValueResult.GetString();
218 return MIstatus::success;
219 }
220
221 // MI print
222 // "frame={level=\"%d\",addr=\"0x%016" PRIx64
223 // "\",func=\"%s\",args=[%s],file=\"%s\",fullname=\"%s\",line=\"%d\"},frame={level=\"%d\",addr=\"0x%016"
224 // PRIx64 "\",func=\"%s\",args=[%s],file=\"%s\",fullname=\"%s\",line=\"%d\"},
225 // ..."
226 CMIUtilString strListCommaSeparated;
227 for (MIuint nLevel = 0; nLevel < nFrames; nLevel++) {
228 CMICmnMIValueTuple miValueTuple;
229 if (!MIResponseFormFrameInfo(thread, nLevel, veFrameInfoFormat,
230 miValueTuple))
231 return MIstatus::failure;
232
233 const CMICmnMIValueResult miValueResult2("frame", miValueTuple);
234 if (nLevel != 0)
235 strListCommaSeparated += ",";
236 strListCommaSeparated += miValueResult2.GetString();
237 }
238
239 vwrThreadFrames = strListCommaSeparated;
240
241 return MIstatus::success;
242 }
243
244 //++
245 //------------------------------------------------------------------------------------
246 // Details: Return the resolved file's path for the given file.
247 // Type: Method.
248 // Args: vCmdData - (R) A command's information.
249 // vPath - (R) Original path.
250 // vwrResolvedPath - (W) Resolved path.
251 // Return: MIstatus::success - Functional succeeded.
252 // MIstatus::failure - Functional failed.
253 // Throws: None.
254 //--
ResolvePath(const SMICmdData & vCmdData,const CMIUtilString & vPath,CMIUtilString & vwrResolvedPath)255 bool CMICmnLLDBDebugSessionInfo::ResolvePath(const SMICmdData &vCmdData,
256 const CMIUtilString &vPath,
257 CMIUtilString &vwrResolvedPath) {
258 // ToDo: Verify this code as it does not work as vPath is always empty
259
260 CMIUtilString strResolvedPath;
261 if (!SharedDataRetrieve<CMIUtilString>(m_constStrSharedDataKeyWkDir,
262 strResolvedPath)) {
263 vwrResolvedPath = "";
264 SetErrorDescription(CMIUtilString::Format(
265 MIRSRC(IDS_CMD_ERR_SHARED_DATA_NOT_FOUND), vCmdData.strMiCmd.c_str(),
266 m_constStrSharedDataKeyWkDir.c_str()));
267 return MIstatus::failure;
268 }
269
270 vwrResolvedPath = vPath;
271
272 return ResolvePath(strResolvedPath, vwrResolvedPath);
273 }
274
275 //++
276 //------------------------------------------------------------------------------------
277 // Details: Return the resolved file's path for the given file.
278 // Type: Method.
279 // Args: vstrUnknown - (R) String assigned to path when resolved path
280 // is empty.
281 // vwrResolvedPath - (RW) The original path overwritten with resolved
282 // path.
283 // Return: MIstatus::success - Functional succeeded.
284 // MIstatus::failure - Functional failed.
285 // Throws: None.
286 //--
ResolvePath(const CMIUtilString & vstrUnknown,CMIUtilString & vwrResolvedPath)287 bool CMICmnLLDBDebugSessionInfo::ResolvePath(const CMIUtilString &vstrUnknown,
288 CMIUtilString &vwrResolvedPath) {
289 if (vwrResolvedPath.size() < 1) {
290 vwrResolvedPath = vstrUnknown;
291 return MIstatus::success;
292 }
293
294 bool bOk = MIstatus::success;
295
296 CMIUtilString::VecString_t vecPathFolders;
297 const MIuint nSplits = vwrResolvedPath.Split("/", vecPathFolders);
298 MIunused(nSplits);
299 MIuint nFoldersBack = 1; // 1 is just the file (last element of vector)
300 while (bOk && (vecPathFolders.size() >= nFoldersBack)) {
301 CMIUtilString strTestPath;
302 MIuint nFoldersToAdd = nFoldersBack;
303 while (nFoldersToAdd > 0) {
304 strTestPath += "/";
305 strTestPath += vecPathFolders[vecPathFolders.size() - nFoldersToAdd];
306 nFoldersToAdd--;
307 }
308 bool bYesAccessible = false;
309 bOk = AccessPath(strTestPath, bYesAccessible);
310 if (bYesAccessible) {
311 vwrResolvedPath = strTestPath;
312 return MIstatus::success;
313 } else
314 nFoldersBack++;
315 }
316
317 // No files exist in the union of working directory and debuginfo path
318 // Simply use the debuginfo path and let the IDE handle it.
319
320 return bOk;
321 }
322
323 //++
324 //------------------------------------------------------------------------------------
325 // Details: Determine the given file path exists or not.
326 // Type: Method.
327 // Args: vPath - (R) File name path.
328 // vwbYesAccessible - (W) True - file exists, false = does not
329 // exist.
330 // Return: MIstatus::success - Functional succeeded.
331 // MIstatus::failure - Functional failed.
332 // Throws: None.
333 //--
AccessPath(const CMIUtilString & vPath,bool & vwbYesAccessible)334 bool CMICmnLLDBDebugSessionInfo::AccessPath(const CMIUtilString &vPath,
335 bool &vwbYesAccessible) {
336 #ifdef _WIN32
337 vwbYesAccessible = (::_access(vPath.c_str(), 0) == 0);
338 #else
339 vwbYesAccessible = (::access(vPath.c_str(), 0) == 0);
340 #endif // _WIN32
341
342 return MIstatus::success;
343 }
344
345 //++
346 //------------------------------------------------------------------------------------
347 // Details: Form MI partial response by appending more MI value type objects to
348 // the
349 // tuple type object past in.
350 // Type: Method.
351 // Args: vCmdData - (R) A command's information.
352 // vrThread - (R) LLDB thread object.
353 // vwrMIValueTuple - (W) MI value tuple object.
354 // Return: MIstatus::success - Functional succeeded.
355 // MIstatus::failure - Functional failed.
356 // Throws: None.
357 //--
MIResponseFormThreadInfo(const SMICmdData & vCmdData,const lldb::SBThread & vrThread,const ThreadInfoFormat_e veThreadInfoFormat,CMICmnMIValueTuple & vwrMIValueTuple)358 bool CMICmnLLDBDebugSessionInfo::MIResponseFormThreadInfo(
359 const SMICmdData &vCmdData, const lldb::SBThread &vrThread,
360 const ThreadInfoFormat_e veThreadInfoFormat,
361 CMICmnMIValueTuple &vwrMIValueTuple) {
362 lldb::SBThread &rThread = const_cast<lldb::SBThread &>(vrThread);
363
364 const bool bSuspended = rThread.IsSuspended();
365 const lldb::StopReason eReason = rThread.GetStopReason();
366 const bool bValidReason = !((eReason == lldb::eStopReasonNone) ||
367 (eReason == lldb::eStopReasonInvalid));
368 const CMIUtilString strState((bSuspended || bValidReason) ? "stopped"
369 : "running");
370
371 // Add "id"
372 const CMIUtilString strId(CMIUtilString::Format("%d", rThread.GetIndexID()));
373 const CMICmnMIValueConst miValueConst1(strId);
374 const CMICmnMIValueResult miValueResult1("id", miValueConst1);
375 vwrMIValueTuple.Add(miValueResult1);
376
377 // Add "target-id"
378 const char *pThreadName = rThread.GetName();
379 const MIuint len =
380 (pThreadName != nullptr) ? CMIUtilString(pThreadName).length() : 0;
381 const bool bHaveName = ((pThreadName != nullptr) && (len > 0) && (len < 32) &&
382 CMIUtilString::IsAllValidAlphaAndNumeric(
383 pThreadName)); // 32 is arbitrary number
384 const char *pThrdFmt = bHaveName ? "%s" : "Thread %d";
385 CMIUtilString strThread;
386 if (bHaveName)
387 strThread = CMIUtilString::Format(pThrdFmt, pThreadName);
388 else
389 strThread = CMIUtilString::Format(pThrdFmt, rThread.GetIndexID());
390 const CMICmnMIValueConst miValueConst2(strThread);
391 const CMICmnMIValueResult miValueResult2("target-id", miValueConst2);
392 vwrMIValueTuple.Add(miValueResult2);
393
394 // Add "frame"
395 if (veThreadInfoFormat != eThreadInfoFormat_NoFrames) {
396 CMIUtilString strFrames;
397 if (!GetThreadFrames(vCmdData, rThread.GetIndexID(),
398 eFrameInfoFormat_AllArgumentsInSimpleForm, strFrames))
399 return MIstatus::failure;
400
401 const CMICmnMIValueConst miValueConst3(strFrames, true);
402 vwrMIValueTuple.Add(miValueConst3, false);
403 }
404
405 // Add "state"
406 const CMICmnMIValueConst miValueConst4(strState);
407 const CMICmnMIValueResult miValueResult4("state", miValueConst4);
408 vwrMIValueTuple.Add(miValueResult4);
409
410 return MIstatus::success;
411 }
412
413 //++
414 //------------------------------------------------------------------------------------
415 // Details: Form MI partial response by appending more MI value type objects to
416 // the
417 // tuple type object past in.
418 // Type: Method.
419 // Args: vrFrame - (R) LLDB thread object.
420 // vMaskVarTypes - (R) Construed according to VariableType_e.
421 // veVarInfoFormat - (R) The type of variable info that should be
422 // shown.
423 // vwrMIValueList - (W) MI value list object.
424 // Return: MIstatus::success - Functional succeeded.
425 // MIstatus::failure - Functional failed.
426 // Throws: None.
427 //--
MIResponseFormVariableInfo(const lldb::SBFrame & vrFrame,const MIuint vMaskVarTypes,const VariableInfoFormat_e veVarInfoFormat,CMICmnMIValueList & vwrMiValueList,const MIuint vnMaxDepth,const bool vbMarkArgs)428 bool CMICmnLLDBDebugSessionInfo::MIResponseFormVariableInfo(
429 const lldb::SBFrame &vrFrame, const MIuint vMaskVarTypes,
430 const VariableInfoFormat_e veVarInfoFormat,
431 CMICmnMIValueList &vwrMiValueList, const MIuint vnMaxDepth, /* = 10 */
432 const bool vbMarkArgs /* = false*/) {
433 bool bOk = MIstatus::success;
434 lldb::SBFrame &rFrame = const_cast<lldb::SBFrame &>(vrFrame);
435
436 const bool bArg = (vMaskVarTypes & eVariableType_Arguments);
437 const bool bLocals = (vMaskVarTypes & eVariableType_Locals);
438 const bool bStatics = (vMaskVarTypes & eVariableType_Statics);
439 const bool bInScopeOnly = (vMaskVarTypes & eVariableType_InScope);
440
441 // Handle arguments first
442 lldb::SBValueList listArg = rFrame.GetVariables(bArg, false, false, false);
443 bOk = bOk && MIResponseForVariableInfoInternal(veVarInfoFormat,
444 vwrMiValueList, listArg,
445 vnMaxDepth, true, vbMarkArgs);
446
447 // Handle remaining variables
448 lldb::SBValueList listVars =
449 rFrame.GetVariables(false, bLocals, bStatics, bInScopeOnly);
450 bOk = bOk && MIResponseForVariableInfoInternal(veVarInfoFormat,
451 vwrMiValueList, listVars,
452 vnMaxDepth, false, vbMarkArgs);
453
454 return bOk;
455 }
456
MIResponseForVariableInfoInternal(const VariableInfoFormat_e veVarInfoFormat,CMICmnMIValueList & vwrMiValueList,const lldb::SBValueList & vwrSBValueList,const MIuint vnMaxDepth,const bool vbIsArgs,const bool vbMarkArgs)457 bool CMICmnLLDBDebugSessionInfo::MIResponseForVariableInfoInternal(
458 const VariableInfoFormat_e veVarInfoFormat,
459 CMICmnMIValueList &vwrMiValueList, const lldb::SBValueList &vwrSBValueList,
460 const MIuint vnMaxDepth, const bool vbIsArgs, const bool vbMarkArgs) {
461 const MIuint nArgs = vwrSBValueList.GetSize();
462 for (MIuint i = 0; i < nArgs; i++) {
463 CMICmnMIValueTuple miValueTuple;
464 lldb::SBValue value = vwrSBValueList.GetValueAtIndex(i);
465 // If one stops inside try block with, which catch clause type is unnamed
466 // (e.g std::exception&) then value name will be nullptr as well as value
467 // pointer
468 const char *name = value.GetName();
469 if (name == nullptr)
470 continue;
471 const CMICmnMIValueConst miValueConst(name);
472 const CMICmnMIValueResult miValueResultName("name", miValueConst);
473 if (vbMarkArgs && vbIsArgs) {
474 const CMICmnMIValueConst miValueConstArg("1");
475 const CMICmnMIValueResult miValueResultArg("arg", miValueConstArg);
476 miValueTuple.Add(miValueResultArg);
477 }
478 if (veVarInfoFormat != eVariableInfoFormat_NoValues) {
479 miValueTuple.Add(miValueResultName); // name
480 if (veVarInfoFormat == eVariableInfoFormat_SimpleValues) {
481 const CMICmnMIValueConst miValueConst3(value.GetTypeName());
482 const CMICmnMIValueResult miValueResult3("type", miValueConst3);
483 miValueTuple.Add(miValueResult3);
484 }
485 const MIuint nChildren = value.GetNumChildren();
486 const bool bIsPointerType = value.GetType().IsPointerType();
487 if (nChildren == 0 || // no children
488 (bIsPointerType && nChildren == 1) || // pointers
489 veVarInfoFormat == eVariableInfoFormat_AllValues) // show all values
490 {
491 CMIUtilString strValue;
492 if (GetVariableInfo(value, vnMaxDepth == 0, strValue)) {
493 const CMICmnMIValueConst miValueConst2(
494 strValue.Escape().AddSlashes());
495 const CMICmnMIValueResult miValueResult2("value", miValueConst2);
496 miValueTuple.Add(miValueResult2);
497 }
498 }
499 vwrMiValueList.Add(miValueTuple);
500 continue;
501 }
502
503 if (vbMarkArgs) {
504 // If we are printing names only with vbMarkArgs, we still need to add the
505 // name to the value tuple
506 miValueTuple.Add(miValueResultName); // name
507 vwrMiValueList.Add(miValueTuple);
508 } else {
509 // If we are printing name only then no need to put it in the tuple.
510 vwrMiValueList.Add(miValueResultName);
511 }
512 }
513 return MIstatus::success;
514 }
515
516 //++
517 //------------------------------------------------------------------------------------
518 // Details: Extract the value's name and value or recurse into child value
519 // object.
520 // Type: Method.
521 // Args: vrValue - (R) LLDB value object.
522 // vbInSimpleForm - (R) True = Get variable info in simple form (i.e.
523 // don't expand aggregates).
524 // - False = Get variable info (and expand
525 // aggregates if any).
526 // vwrStrValue t - (W) The string representation of this value.
527 // Return: MIstatus::success - Functional succeeded.
528 // MIstatus::failure - Functional failed.
529 // Throws: None.
530 //--
GetVariableInfo(const lldb::SBValue & vrValue,const bool vbInSimpleForm,CMIUtilString & vwrStrValue)531 bool CMICmnLLDBDebugSessionInfo::GetVariableInfo(const lldb::SBValue &vrValue,
532 const bool vbInSimpleForm,
533 CMIUtilString &vwrStrValue) {
534 const CMICmnLLDBUtilSBValue utilValue(vrValue, true, false);
535 const bool bExpandAggregates = !vbInSimpleForm;
536 vwrStrValue = utilValue.GetValue(bExpandAggregates);
537 return MIstatus::success;
538 }
539
540 //++
541 //------------------------------------------------------------------------------------
542 // Details: Form MI partial response by appending more MI value type objects to
543 // the
544 // tuple type object past in.
545 // Type: Method.
546 // Args: vrThread - (R) LLDB thread object.
547 // vwrMIValueTuple - (W) MI value tuple object.
548 // vArgInfo - (R) Args information in MI response form.
549 // Return: MIstatus::success - Functional succeeded.
550 // MIstatus::failure - Functional failed.
551 // Throws: None.
552 //--
MIResponseFormFrameInfo(const lldb::SBThread & vrThread,const MIuint vnLevel,const FrameInfoFormat_e veFrameInfoFormat,CMICmnMIValueTuple & vwrMiValueTuple)553 bool CMICmnLLDBDebugSessionInfo::MIResponseFormFrameInfo(
554 const lldb::SBThread &vrThread, const MIuint vnLevel,
555 const FrameInfoFormat_e veFrameInfoFormat,
556 CMICmnMIValueTuple &vwrMiValueTuple) {
557 lldb::SBThread &rThread = const_cast<lldb::SBThread &>(vrThread);
558
559 lldb::SBFrame frame = rThread.GetFrameAtIndex(vnLevel);
560 lldb::addr_t pc = 0;
561 CMIUtilString fnName;
562 CMIUtilString fileName;
563 CMIUtilString path;
564 MIuint nLine = 0;
565 if (!GetFrameInfo(frame, pc, fnName, fileName, path, nLine))
566 return MIstatus::failure;
567
568 // MI print "{level=\"0\",addr=\"0x%016" PRIx64
569 // "\",func=\"%s\",file=\"%s\",fullname=\"%s\",line=\"%d\"}"
570 const CMIUtilString strLevel(CMIUtilString::Format("%d", vnLevel));
571 const CMICmnMIValueConst miValueConst(strLevel);
572 const CMICmnMIValueResult miValueResult("level", miValueConst);
573 vwrMiValueTuple.Add(miValueResult);
574 const CMIUtilString strAddr(CMIUtilString::Format("0x%016" PRIx64, pc));
575 const CMICmnMIValueConst miValueConst2(strAddr);
576 const CMICmnMIValueResult miValueResult2("addr", miValueConst2);
577 vwrMiValueTuple.Add(miValueResult2);
578 const CMICmnMIValueConst miValueConst3(fnName);
579 const CMICmnMIValueResult miValueResult3("func", miValueConst3);
580 vwrMiValueTuple.Add(miValueResult3);
581 if (veFrameInfoFormat != eFrameInfoFormat_NoArguments) {
582 CMICmnMIValueList miValueList(true);
583 const MIuint maskVarTypes = eVariableType_Arguments;
584 if (veFrameInfoFormat == eFrameInfoFormat_AllArgumentsInSimpleForm) {
585 if (!MIResponseFormVariableInfo(frame, maskVarTypes,
586 eVariableInfoFormat_AllValues,
587 miValueList, 0))
588 return MIstatus::failure;
589 } else if (!MIResponseFormVariableInfo(frame, maskVarTypes,
590 eVariableInfoFormat_AllValues,
591 miValueList))
592 return MIstatus::failure;
593
594 const CMICmnMIValueResult miValueResult4("args", miValueList);
595 vwrMiValueTuple.Add(miValueResult4);
596 }
597 const CMICmnMIValueConst miValueConst5(fileName);
598 const CMICmnMIValueResult miValueResult5("file", miValueConst5);
599 vwrMiValueTuple.Add(miValueResult5);
600 const CMICmnMIValueConst miValueConst6(path);
601 const CMICmnMIValueResult miValueResult6("fullname", miValueConst6);
602 vwrMiValueTuple.Add(miValueResult6);
603 const CMIUtilString strLine(CMIUtilString::Format("%d", nLine));
604 const CMICmnMIValueConst miValueConst7(strLine);
605 const CMICmnMIValueResult miValueResult7("line", miValueConst7);
606 vwrMiValueTuple.Add(miValueResult7);
607
608 return MIstatus::success;
609 }
610
611 //++
612 //------------------------------------------------------------------------------------
613 // Details: Retrieve the frame information from LLDB frame object.
614 // Type: Method.
615 // Args: vrFrame - (R) LLDB thread object.
616 // vPc - (W) Address number.
617 // vFnName - (W) Function name.
618 // vFileName - (W) File name text.
619 // vPath - (W) Full file name and path text.
620 // vnLine - (W) File line number.
621 // Return: MIstatus::success - Functional succeeded.
622 // MIstatus::failure - Functional failed.
623 // Throws: None.
624 //--
GetFrameInfo(const lldb::SBFrame & vrFrame,lldb::addr_t & vwPc,CMIUtilString & vwFnName,CMIUtilString & vwFileName,CMIUtilString & vwPath,MIuint & vwnLine)625 bool CMICmnLLDBDebugSessionInfo::GetFrameInfo(
626 const lldb::SBFrame &vrFrame, lldb::addr_t &vwPc, CMIUtilString &vwFnName,
627 CMIUtilString &vwFileName, CMIUtilString &vwPath, MIuint &vwnLine) {
628 lldb::SBFrame &rFrame = const_cast<lldb::SBFrame &>(vrFrame);
629
630 static char pBuffer[PATH_MAX];
631 const MIuint nBytes =
632 rFrame.GetLineEntry().GetFileSpec().GetPath(&pBuffer[0], sizeof(pBuffer));
633 MIunused(nBytes);
634 CMIUtilString strResolvedPath(&pBuffer[0]);
635 const char *pUnkwn = "??";
636 if (!ResolvePath(pUnkwn, strResolvedPath))
637 return MIstatus::failure;
638 vwPath = strResolvedPath;
639
640 vwPc = rFrame.GetPC();
641
642 const char *pFnName = rFrame.GetFunctionName();
643 vwFnName = (pFnName != nullptr) ? pFnName : pUnkwn;
644
645 const char *pFileName = rFrame.GetLineEntry().GetFileSpec().GetFilename();
646 vwFileName = (pFileName != nullptr) ? pFileName : pUnkwn;
647
648 vwnLine = rFrame.GetLineEntry().GetLine();
649
650 return MIstatus::success;
651 }
652
653 //++
654 //------------------------------------------------------------------------------------
655 // Details: Form MI partial response by appending more MI value type objects to
656 // the
657 // tuple type object past in.
658 // Type: Method.
659 // Args: vrBrkPtInfo - (R) Break point information object.
660 // vwrMIValueTuple - (W) MI value tuple object.
661 // Return: None.
662 // Throws: None.
663 //--
MIResponseFormBrkPtFrameInfo(const SBrkPtInfo & vrBrkPtInfo,CMICmnMIValueTuple & vwrMiValueTuple)664 void CMICmnLLDBDebugSessionInfo::MIResponseFormBrkPtFrameInfo(
665 const SBrkPtInfo &vrBrkPtInfo, CMICmnMIValueTuple &vwrMiValueTuple) {
666 const CMIUtilString strAddr(
667 CMIUtilString::Format("0x%016" PRIx64, vrBrkPtInfo.m_pc));
668 const CMICmnMIValueConst miValueConst2(strAddr);
669 const CMICmnMIValueResult miValueResult2("addr", miValueConst2);
670 vwrMiValueTuple.Add(miValueResult2);
671 const CMICmnMIValueConst miValueConst3(vrBrkPtInfo.m_fnName);
672 const CMICmnMIValueResult miValueResult3("func", miValueConst3);
673 vwrMiValueTuple.Add(miValueResult3);
674 const CMICmnMIValueConst miValueConst5(vrBrkPtInfo.m_fileName);
675 const CMICmnMIValueResult miValueResult5("file", miValueConst5);
676 vwrMiValueTuple.Add(miValueResult5);
677 const CMIUtilString strN5 = CMIUtilString::Format(
678 "%s/%s", vrBrkPtInfo.m_path.c_str(), vrBrkPtInfo.m_fileName.c_str());
679 const CMICmnMIValueConst miValueConst6(strN5);
680 const CMICmnMIValueResult miValueResult6("fullname", miValueConst6);
681 vwrMiValueTuple.Add(miValueResult6);
682 const CMIUtilString strLine(CMIUtilString::Format("%d", vrBrkPtInfo.m_nLine));
683 const CMICmnMIValueConst miValueConst7(strLine);
684 const CMICmnMIValueResult miValueResult7("line", miValueConst7);
685 vwrMiValueTuple.Add(miValueResult7);
686 }
687
688 //++
689 //------------------------------------------------------------------------------------
690 // Details: Form MI partial response by appending more MI value type objects to
691 // the
692 // tuple type object past in.
693 // Type: Method.
694 // Args: vrBrkPtInfo - (R) Break point information object.
695 // vwrMIValueTuple - (W) MI value tuple object.
696 // Return: MIstatus::success - Functional succeeded.
697 // MIstatus::failure - Functional failed.
698 // Throws: None.
699 //--
MIResponseFormBrkPtInfo(const SBrkPtInfo & vrBrkPtInfo,CMICmnMIValueTuple & vwrMiValueTuple)700 bool CMICmnLLDBDebugSessionInfo::MIResponseFormBrkPtInfo(
701 const SBrkPtInfo &vrBrkPtInfo, CMICmnMIValueTuple &vwrMiValueTuple) {
702 // MI print
703 // "=breakpoint-modified,bkpt={number=\"%d\",type=\"breakpoint\",disp=\"%s\",enabled=\"%c\",addr=\"0x%016"
704 // PRIx64 "\",
705 // func=\"%s\",file=\"%s\",fullname=\"%s/%s\",line=\"%d\",times=\"%d\",original-location=\"%s\"}"
706
707 // "number="
708 const CMICmnMIValueConst miValueConst(
709 CMIUtilString::Format("%d", vrBrkPtInfo.m_id));
710 const CMICmnMIValueResult miValueResult("number", miValueConst);
711 CMICmnMIValueTuple miValueTuple(miValueResult);
712 // "type="
713 const CMICmnMIValueConst miValueConst2(vrBrkPtInfo.m_strType);
714 const CMICmnMIValueResult miValueResult2("type", miValueConst2);
715 miValueTuple.Add(miValueResult2);
716 // "disp="
717 const CMICmnMIValueConst miValueConst3(vrBrkPtInfo.m_bDisp ? "del" : "keep");
718 const CMICmnMIValueResult miValueResult3("disp", miValueConst3);
719 miValueTuple.Add(miValueResult3);
720 // "enabled="
721 const CMICmnMIValueConst miValueConst4(vrBrkPtInfo.m_bEnabled ? "y" : "n");
722 const CMICmnMIValueResult miValueResult4("enabled", miValueConst4);
723 miValueTuple.Add(miValueResult4);
724 // "addr="
725 // "func="
726 // "file="
727 // "fullname="
728 // "line="
729 MIResponseFormBrkPtFrameInfo(vrBrkPtInfo, miValueTuple);
730 // "pending="
731 if (vrBrkPtInfo.m_bPending) {
732 const CMICmnMIValueConst miValueConst(vrBrkPtInfo.m_strOrigLoc);
733 const CMICmnMIValueList miValueList(miValueConst);
734 const CMICmnMIValueResult miValueResult("pending", miValueList);
735 miValueTuple.Add(miValueResult);
736 }
737 if (vrBrkPtInfo.m_bHaveArgOptionThreadGrp) {
738 const CMICmnMIValueConst miValueConst(vrBrkPtInfo.m_strOptThrdGrp);
739 const CMICmnMIValueList miValueList(miValueConst);
740 const CMICmnMIValueResult miValueResult("thread-groups", miValueList);
741 miValueTuple.Add(miValueResult);
742 }
743 // "times="
744 const CMICmnMIValueConst miValueConstB(
745 CMIUtilString::Format("%d", vrBrkPtInfo.m_nTimes));
746 const CMICmnMIValueResult miValueResultB("times", miValueConstB);
747 miValueTuple.Add(miValueResultB);
748 // "thread="
749 if (vrBrkPtInfo.m_bBrkPtThreadId) {
750 const CMICmnMIValueConst miValueConst(
751 CMIUtilString::Format("%d", vrBrkPtInfo.m_nBrkPtThreadId));
752 const CMICmnMIValueResult miValueResult("thread", miValueConst);
753 miValueTuple.Add(miValueResult);
754 }
755 // "cond="
756 if (vrBrkPtInfo.m_bCondition) {
757 const CMICmnMIValueConst miValueConst(vrBrkPtInfo.m_strCondition);
758 const CMICmnMIValueResult miValueResult("cond", miValueConst);
759 miValueTuple.Add(miValueResult);
760 }
761 // "ignore="
762 if (vrBrkPtInfo.m_nIgnore != 0) {
763 const CMICmnMIValueConst miValueConst(
764 CMIUtilString::Format("%d", vrBrkPtInfo.m_nIgnore));
765 const CMICmnMIValueResult miValueResult("ignore", miValueConst);
766 miValueTuple.Add(miValueResult);
767 }
768 // "original-location="
769 const CMICmnMIValueConst miValueConstC(vrBrkPtInfo.m_strOrigLoc);
770 const CMICmnMIValueResult miValueResultC("original-location", miValueConstC);
771 miValueTuple.Add(miValueResultC);
772
773 vwrMiValueTuple = miValueTuple;
774
775 return MIstatus::success;
776 }
777
778 //++
779 //------------------------------------------------------------------------------------
780 // Details: Retrieve breakpoint information and write into the given breakpoint
781 // information
782 // object. Note not all possible information is retrieved and so the
783 // information
784 // object may need to be filled in with more information after calling
785 // this
786 // function. Mainly breakpoint location information of information that
787 // is
788 // unlikely to change.
789 // Type: Method.
790 // Args: vBrkPt - (R) LLDB break point object.
791 // vrBrkPtInfo - (W) Break point information object.
792 // Return: MIstatus::success - Functional succeeded.
793 // MIstatus::failure - Functional failed.
794 // Throws: None.
795 //--
GetBrkPtInfo(const lldb::SBBreakpoint & vBrkPt,SBrkPtInfo & vrwBrkPtInfo) const796 bool CMICmnLLDBDebugSessionInfo::GetBrkPtInfo(const lldb::SBBreakpoint &vBrkPt,
797 SBrkPtInfo &vrwBrkPtInfo) const {
798 lldb::SBBreakpoint &rBrkPt = const_cast<lldb::SBBreakpoint &>(vBrkPt);
799 lldb::SBBreakpointLocation brkPtLoc = rBrkPt.GetLocationAtIndex(0);
800 lldb::SBAddress brkPtAddr = brkPtLoc.GetAddress();
801 lldb::SBSymbolContext symbolCntxt =
802 brkPtAddr.GetSymbolContext(lldb::eSymbolContextEverything);
803 const char *pUnkwn = "??";
804 lldb::SBModule rModule = symbolCntxt.GetModule();
805 const char *pModule =
806 rModule.IsValid() ? rModule.GetFileSpec().GetFilename() : pUnkwn;
807 MIunused(pModule);
808 const char *pFile = pUnkwn;
809 const char *pFn = pUnkwn;
810 const char *pFilePath = pUnkwn;
811 size_t nLine = 0;
812 lldb::addr_t nAddr = brkPtAddr.GetLoadAddress(GetTarget());
813 if (nAddr == LLDB_INVALID_ADDRESS)
814 nAddr = brkPtAddr.GetFileAddress();
815
816 lldb::SBCompileUnit rCmplUnit = symbolCntxt.GetCompileUnit();
817 if (rCmplUnit.IsValid()) {
818 lldb::SBFileSpec rFileSpec = rCmplUnit.GetFileSpec();
819 pFile = rFileSpec.GetFilename();
820 pFilePath = rFileSpec.GetDirectory();
821 lldb::SBFunction rFn = symbolCntxt.GetFunction();
822 if (rFn.IsValid())
823 pFn = rFn.GetName();
824 lldb::SBLineEntry rLnEntry = symbolCntxt.GetLineEntry();
825 if (rLnEntry.GetLine() > 0)
826 nLine = rLnEntry.GetLine();
827 }
828
829 vrwBrkPtInfo.m_id = vBrkPt.GetID();
830 vrwBrkPtInfo.m_strType = "breakpoint";
831 vrwBrkPtInfo.m_pc = nAddr;
832 vrwBrkPtInfo.m_fnName = pFn;
833 vrwBrkPtInfo.m_fileName = pFile;
834 vrwBrkPtInfo.m_path = pFilePath;
835 vrwBrkPtInfo.m_nLine = nLine;
836 vrwBrkPtInfo.m_nTimes = vBrkPt.GetHitCount();
837
838 return MIstatus::success;
839 }
840
841 //++
842 //------------------------------------------------------------------------------------
843 // Details: Get current debugger.
844 // Type: Method.
845 // Args: None.
846 // Return: lldb::SBDebugger - current debugger.
847 // Throws: None.
848 //--
GetDebugger() const849 lldb::SBDebugger &CMICmnLLDBDebugSessionInfo::GetDebugger() const {
850 return CMICmnLLDBDebugger::Instance().GetTheDebugger();
851 }
852
853 //++
854 //------------------------------------------------------------------------------------
855 // Details: Get current listener.
856 // Type: Method.
857 // Args: None.
858 // Return: lldb::SBListener - current listener.
859 // Throws: None.
860 //--
GetListener() const861 lldb::SBListener &CMICmnLLDBDebugSessionInfo::GetListener() const {
862 return CMICmnLLDBDebugger::Instance().GetTheListener();
863 }
864
865 //++
866 //------------------------------------------------------------------------------------
867 // Details: Get current target.
868 // Type: Method.
869 // Args: None.
870 // Return: lldb::SBTarget - current target.
871 // Throws: None.
872 //--
GetTarget() const873 lldb::SBTarget CMICmnLLDBDebugSessionInfo::GetTarget() const {
874 auto target = GetDebugger().GetSelectedTarget();
875 if (target.IsValid())
876 return target;
877 return GetDebugger().GetDummyTarget();
878 }
879
880 //++
881 //------------------------------------------------------------------------------------
882 // Details: Get current process.
883 // Type: Method.
884 // Args: None.
885 // Return: lldb::SBProcess - current process.
886 // Throws: None.
887 //--
GetProcess() const888 lldb::SBProcess CMICmnLLDBDebugSessionInfo::GetProcess() const {
889 return GetTarget().GetProcess();
890 }
891