1 //===-- MICmdCmdStack.cpp ---------------------------------------*- C++ -*-===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 // Overview: CMICmdCmdStackInfoDepth implementation.
10 // CMICmdCmdStackInfoFrame implementation.
11 // CMICmdCmdStackListFrames implementation.
12 // CMICmdCmdStackListArguments implementation.
13 // CMICmdCmdStackListLocals implementation.
14 // CMICmdCmdStackSelectFrame implementation.
16 // Third Party Headers:
17 #include "lldb/API/SBThread.h"
20 #include "MICmdArgValListOfN.h"
21 #include "MICmdArgValNumber.h"
22 #include "MICmdArgValOptionLong.h"
23 #include "MICmdArgValOptionShort.h"
24 #include "MICmdArgValPrintValues.h"
25 #include "MICmdArgValString.h"
26 #include "MICmdArgValThreadGrp.h"
27 #include "MICmdCmdStack.h"
28 #include "MICmnLLDBDebugSessionInfo.h"
29 #include "MICmnLLDBDebugger.h"
30 #include "MICmnMIOutOfBandRecord.h"
31 #include "MICmnMIResultRecord.h"
32 #include "MICmnMIValueConst.h"
37 // Details: CMICmdCmdStackInfoDepth constructor.
43 CMICmdCmdStackInfoDepth::CMICmdCmdStackInfoDepth()
44 : m_nThreadFrames(0), m_constStrArgMaxDepth("max-depth") {
45 // Command factory matches this name with that received from the stdin stream
46 m_strMiCmd = "stack-info-depth";
48 // Required by the CMICmdFactory when registering *this command
49 m_pSelfCreatorFn = &CMICmdCmdStackInfoDepth::CreateSelf;
53 // Details: CMICmdCmdStackInfoDepth destructor.
54 // Type: Overrideable.
59 CMICmdCmdStackInfoDepth::~CMICmdCmdStackInfoDepth() {}
62 // Details: The invoker requires this function. The parses the command line
64 // arguments to extract values for each of those arguments.
67 // Return: MIstatus::success - Functional succeeded.
68 // MIstatus::failure - Functional failed.
71 bool CMICmdCmdStackInfoDepth::ParseArgs() {
72 m_setCmdArgs.Add(new CMICmdArgValNumber(m_constStrArgMaxDepth, false, false));
73 return ParseValidateCmdOptions();
77 // Details: The invoker requires this function. The command does work in this
79 // The command is likely to communicate with the LLDB SBDebugger in
83 // Return: MIstatus::success - Functional succeeded.
84 // MIstatus::failure - Functional failed.
87 bool CMICmdCmdStackInfoDepth::Execute() {
88 CMICMDBASE_GETOPTION(pArgThread, OptionLong, m_constStrArgThread);
89 CMICMDBASE_GETOPTION(pArgMaxDepth, Number, m_constStrArgMaxDepth);
91 // Retrieve the --thread option's thread ID (only 1)
92 MIuint64 nThreadId = UINT64_MAX;
93 if (pArgThread->GetFound() &&
94 !pArgThread->GetExpectedOption<CMICmdArgValNumber, MIuint64>(nThreadId)) {
95 SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_OPTION_NOT_FOUND),
96 m_cmdData.strMiCmd.c_str(),
97 m_constStrArgThread.c_str()));
98 return MIstatus::failure;
101 CMICmnLLDBDebugSessionInfo &rSessionInfo(
102 CMICmnLLDBDebugSessionInfo::Instance());
103 lldb::SBProcess sbProcess = rSessionInfo.GetProcess();
104 lldb::SBThread thread = (nThreadId != UINT64_MAX)
105 ? sbProcess.GetThreadByIndexID(nThreadId)
106 : sbProcess.GetSelectedThread();
107 m_nThreadFrames = thread.GetNumFrames();
109 return MIstatus::success;
113 // Details: The invoker requires this function. The command prepares a MI Record
115 // for the work carried out in the Execute().
118 // Return: MIstatus::success - Functional succeeded.
119 // MIstatus::failure - Functional failed.
122 bool CMICmdCmdStackInfoDepth::Acknowledge() {
123 const CMIUtilString strDepth(CMIUtilString::Format("%d", m_nThreadFrames));
124 const CMICmnMIValueConst miValueConst(strDepth);
125 const CMICmnMIValueResult miValueResult("depth", miValueConst);
126 const CMICmnMIResultRecord miRecordResult(
127 m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done,
129 m_miResultRecord = miRecordResult;
131 return MIstatus::success;
135 // Details: Required by the CMICmdFactory when registering *this command. The
137 // calls this function to create an instance of *this command.
138 // Type: Static method.
140 // Return: CMICmdBase * - Pointer to a new command.
143 CMICmdBase *CMICmdCmdStackInfoDepth::CreateSelf() {
144 return new CMICmdCmdStackInfoDepth();
149 // Details: CMICmdCmdStackInfoFrame constructor.
155 CMICmdCmdStackInfoFrame::CMICmdCmdStackInfoFrame() {
156 // Command factory matches this name with that received from the stdin stream
157 m_strMiCmd = "stack-info-frame";
159 // Required by the CMICmdFactory when registering *this command
160 m_pSelfCreatorFn = &CMICmdCmdStackInfoFrame::CreateSelf;
164 // Details: CMICmdCmdStackInfoFrame destructor.
165 // Type: Overrideable.
170 CMICmdCmdStackInfoFrame::~CMICmdCmdStackInfoFrame() {}
173 // Details: The invoker requires this function. The parses the command line
175 // arguments to extract values for each of those arguments.
178 // Return: MIstatus::success - Function succeeded.
179 // MIstatus::failure - Function failed.
182 bool CMICmdCmdStackInfoFrame::ParseArgs() { return ParseValidateCmdOptions(); }
185 // Details: The invoker requires this function. The command does work in this
187 // The command is likely to communicate with the LLDB SBDebugger in
191 // Return: MIstatus::success - Function succeeded.
192 // MIstatus::failure - Function failed.
195 bool CMICmdCmdStackInfoFrame::Execute() {
196 CMICmnLLDBDebugSessionInfo &rSessionInfo(
197 CMICmnLLDBDebugSessionInfo::Instance());
198 lldb::SBProcess sbProcess = rSessionInfo.GetProcess();
199 if (!sbProcess.IsValid()) {
200 SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_INVALID_PROCESS),
201 m_cmdData.strMiCmd.c_str()));
202 return MIstatus::failure;
205 lldb::SBThread sbThread = sbProcess.GetSelectedThread();
206 MIuint nFrameId = sbThread.GetSelectedFrame().GetFrameID();
207 if (!rSessionInfo.MIResponseFormFrameInfo(
209 CMICmnLLDBDebugSessionInfo::eFrameInfoFormat_NoArguments,
211 return MIstatus::failure;
213 return MIstatus::success;
217 // Details: The invoker requires this function. The command prepares a MI Record
219 // for the work carried out in the Execute().
222 // Return: MIstatus::success - Function succeeded.
223 // MIstatus::failure - Function failed.
226 bool CMICmdCmdStackInfoFrame::Acknowledge() {
227 const CMICmnMIValueResult miValueResult("frame", m_miValueTuple);
228 const CMICmnMIResultRecord miRecordResult(
229 m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done,
231 m_miResultRecord = miRecordResult;
233 return MIstatus::success;
237 // Details: Required by the CMICmdFactory when registering *this command. The
239 // calls this function to create an instance of *this command.
240 // Type: Static method.
242 // Return: CMICmdBase * - Pointer to a new command.
245 CMICmdBase *CMICmdCmdStackInfoFrame::CreateSelf() {
246 return new CMICmdCmdStackInfoFrame();
251 // Details: CMICmdCmdStackListFrames constructor.
257 CMICmdCmdStackListFrames::CMICmdCmdStackListFrames()
258 : m_nThreadFrames(0), m_constStrArgFrameLow("low-frame"),
259 m_constStrArgFrameHigh("high-frame") {
260 // Command factory matches this name with that received from the stdin stream
261 m_strMiCmd = "stack-list-frames";
263 // Required by the CMICmdFactory when registering *this command
264 m_pSelfCreatorFn = &CMICmdCmdStackListFrames::CreateSelf;
268 // Details: CMICmdCmdStackListFrames destructor.
269 // Type: Overrideable.
274 CMICmdCmdStackListFrames::~CMICmdCmdStackListFrames() {
275 m_vecMIValueResult.clear();
279 // Details: The invoker requires this function. The parses the command line
281 // arguments to extract values for each of those arguments.
284 // Return: MIstatus::success - Functional succeeded.
285 // MIstatus::failure - Functional failed.
288 bool CMICmdCmdStackListFrames::ParseArgs() {
289 m_setCmdArgs.Add(new CMICmdArgValNumber(m_constStrArgFrameLow, false, true));
290 m_setCmdArgs.Add(new CMICmdArgValNumber(m_constStrArgFrameHigh, false, true));
291 return ParseValidateCmdOptions();
295 // Details: The invoker requires this function. The command does work in this
297 // The command is likely to communicate with the LLDB SBDebugger in
301 // Return: MIstatus::success - Functional succeeded.
302 // MIstatus::failure - Functional failed.
305 bool CMICmdCmdStackListFrames::Execute() {
306 CMICMDBASE_GETOPTION(pArgThread, OptionLong, m_constStrArgThread);
307 CMICMDBASE_GETOPTION(pArgFrameLow, Number, m_constStrArgFrameLow);
308 CMICMDBASE_GETOPTION(pArgFrameHigh, Number, m_constStrArgFrameHigh);
310 // Retrieve the --thread option's thread ID (only 1)
311 MIuint64 nThreadId = UINT64_MAX;
312 if (pArgThread->GetFound() &&
313 !pArgThread->GetExpectedOption<CMICmdArgValNumber, MIuint64>(nThreadId)) {
314 SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_OPTION_NOT_FOUND),
315 m_cmdData.strMiCmd.c_str(),
316 m_constStrArgThread.c_str()));
317 return MIstatus::failure;
320 // Frame low and high options are not mandatory
322 pArgFrameHigh->GetFound() ? pArgFrameHigh->GetValue() : UINT32_MAX;
323 const MIuint nFrameLow =
324 pArgFrameLow->GetFound() ? pArgFrameLow->GetValue() : 0;
326 CMICmnLLDBDebugSessionInfo &rSessionInfo(
327 CMICmnLLDBDebugSessionInfo::Instance());
328 lldb::SBProcess sbProcess = rSessionInfo.GetProcess();
329 lldb::SBThread thread = (nThreadId != UINT64_MAX)
330 ? sbProcess.GetThreadByIndexID(nThreadId)
331 : sbProcess.GetSelectedThread();
332 MIuint nThreadFrames = thread.GetNumFrames();
334 // Adjust nThreadFrames for the nFrameHigh argument as we use nFrameHigh+1 in
335 // the min calc as the arg
336 // is not an index, but a frame id value.
337 if (nFrameHigh < UINT32_MAX) {
339 nThreadFrames = (nFrameHigh < nThreadFrames) ? nFrameHigh : nThreadFrames;
342 m_nThreadFrames = nThreadFrames;
343 if (nThreadFrames == 0)
344 return MIstatus::success;
346 m_vecMIValueResult.clear();
347 for (MIuint nLevel = nFrameLow; nLevel < nThreadFrames; nLevel++) {
348 CMICmnMIValueTuple miValueTuple;
349 if (!rSessionInfo.MIResponseFormFrameInfo(
351 CMICmnLLDBDebugSessionInfo::eFrameInfoFormat_NoArguments,
353 return MIstatus::failure;
355 const CMICmnMIValueResult miValueResult8("frame", miValueTuple);
356 m_vecMIValueResult.push_back(miValueResult8);
359 return MIstatus::success;
363 // Details: The invoker requires this function. The command prepares a MI Record
365 // for the work carried out in the Execute().
368 // Return: MIstatus::success - Functional succeeded.
369 // MIstatus::failure - Functional failed.
372 bool CMICmdCmdStackListFrames::Acknowledge() {
373 if (m_nThreadFrames == 0) {
374 // MI print "3^done,stack=[{}]"
375 const CMICmnMIValueTuple miValueTuple;
376 const CMICmnMIValueList miValueList(miValueTuple);
377 const CMICmnMIValueResult miValueResult("stack", miValueList);
378 const CMICmnMIResultRecord miRecordResult(
379 m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done,
381 m_miResultRecord = miRecordResult;
383 return MIstatus::success;
386 // Build up a list of thread information from tuples
387 VecMIValueResult_t::const_iterator it = m_vecMIValueResult.begin();
388 if (it == m_vecMIValueResult.end()) {
389 // MI print "3^done,stack=[{}]"
390 const CMICmnMIValueTuple miValueTuple;
391 const CMICmnMIValueList miValueList(miValueTuple);
392 const CMICmnMIValueResult miValueResult("stack", miValueList);
393 const CMICmnMIResultRecord miRecordResult(
394 m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done,
396 m_miResultRecord = miRecordResult;
397 return MIstatus::success;
399 CMICmnMIValueList miValueList(*it);
401 while (it != m_vecMIValueResult.end()) {
402 const CMICmnMIValueResult &rTuple(*it);
403 miValueList.Add(rTuple);
408 const CMICmnMIValueResult miValueResult("stack", miValueList);
409 const CMICmnMIResultRecord miRecordResult(
410 m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done,
412 m_miResultRecord = miRecordResult;
414 return MIstatus::success;
418 // Details: Required by the CMICmdFactory when registering *this command. The
420 // calls this function to create an instance of *this command.
421 // Type: Static method.
423 // Return: CMICmdBase * - Pointer to a new command.
426 CMICmdBase *CMICmdCmdStackListFrames::CreateSelf() {
427 return new CMICmdCmdStackListFrames();
432 // Details: CMICmdCmdStackListArguments constructor.
438 CMICmdCmdStackListArguments::CMICmdCmdStackListArguments()
439 : m_bThreadInvalid(false), m_miValueList(true),
440 m_constStrArgPrintValues("print-values"),
441 m_constStrArgFrameLow("low-frame"), m_constStrArgFrameHigh("high-frame") {
442 // Command factory matches this name with that received from the stdin stream
443 m_strMiCmd = "stack-list-arguments";
445 // Required by the CMICmdFactory when registering *this command
446 m_pSelfCreatorFn = &CMICmdCmdStackListArguments::CreateSelf;
450 // Details: CMICmdCmdStackListArguments destructor.
451 // Type: Overrideable.
456 CMICmdCmdStackListArguments::~CMICmdCmdStackListArguments() {}
459 // Details: The invoker requires this function. The parses the command line
461 // arguments to extract values for each of those arguments.
464 // Return: MIstatus::success - Functional succeeded.
465 // MIstatus::failure - Functional failed.
468 bool CMICmdCmdStackListArguments::ParseArgs() {
470 new CMICmdArgValPrintValues(m_constStrArgPrintValues, true, true));
471 m_setCmdArgs.Add(new CMICmdArgValNumber(m_constStrArgFrameLow, false, true));
472 m_setCmdArgs.Add(new CMICmdArgValNumber(m_constStrArgFrameHigh, false, true));
473 return ParseValidateCmdOptions();
477 // Details: The invoker requires this function. The command does work in this
479 // The command is likely to communicate with the LLDB SBDebugger in
483 // Return: MIstatus::success - Functional succeeded.
484 // MIstatus::failure - Functional failed.
487 bool CMICmdCmdStackListArguments::Execute() {
488 CMICMDBASE_GETOPTION(pArgThread, OptionLong, m_constStrArgThread);
489 CMICMDBASE_GETOPTION(pArgPrintValues, PrintValues, m_constStrArgPrintValues);
490 CMICMDBASE_GETOPTION(pArgFrameLow, Number, m_constStrArgFrameLow);
491 CMICMDBASE_GETOPTION(pArgFrameHigh, Number, m_constStrArgFrameHigh);
493 // Retrieve the --thread option's thread ID (only 1)
494 MIuint64 nThreadId = UINT64_MAX;
495 if (pArgThread->GetFound()) {
496 if (!pArgThread->GetExpectedOption<CMICmdArgValNumber, MIuint64>(
498 SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_OPTION_NOT_FOUND),
499 m_cmdData.strMiCmd.c_str(),
500 m_constStrArgThread.c_str()));
501 return MIstatus::failure;
505 const CMICmnLLDBDebugSessionInfo::VariableInfoFormat_e eVarInfoFormat =
506 static_cast<CMICmnLLDBDebugSessionInfo::VariableInfoFormat_e>(
507 pArgPrintValues->GetValue());
509 MIuint nFrameLow = 0;
510 MIuint nFrameHigh = UINT32_MAX;
511 if (pArgFrameLow->GetFound() && pArgFrameHigh->GetFound()) {
512 nFrameLow = pArgFrameLow->GetValue();
513 nFrameHigh = pArgFrameHigh->GetValue() + 1;
514 } else if (pArgFrameLow->GetFound() || pArgFrameHigh->GetFound()) {
515 // Only low-frame or high-frame was specified but both are required
517 CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_THREAD_FRAME_RANGE_INVALID),
518 m_cmdData.strMiCmd.c_str()));
519 return MIstatus::failure;
522 CMICmnLLDBDebugSessionInfo &rSessionInfo(
523 CMICmnLLDBDebugSessionInfo::Instance());
524 lldb::SBProcess sbProcess = rSessionInfo.GetProcess();
525 lldb::SBThread thread = (nThreadId != UINT64_MAX)
526 ? sbProcess.GetThreadByIndexID(nThreadId)
527 : sbProcess.GetSelectedThread();
528 m_bThreadInvalid = !thread.IsValid();
529 if (m_bThreadInvalid)
530 return MIstatus::success;
532 const lldb::StopReason eStopReason = thread.GetStopReason();
533 if ((eStopReason == lldb::eStopReasonNone) ||
534 (eStopReason == lldb::eStopReasonInvalid)) {
535 m_bThreadInvalid = true;
536 return MIstatus::success;
539 const MIuint nFrames = thread.GetNumFrames();
540 if (nFrameLow >= nFrames) {
541 // The low-frame is larger than the actual number of frames
543 CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_THREAD_FRAME_RANGE_INVALID),
544 m_cmdData.strMiCmd.c_str()));
545 return MIstatus::failure;
548 nFrameHigh = std::min(nFrameHigh, nFrames);
549 for (MIuint i = nFrameLow; i < nFrameHigh; i++) {
550 lldb::SBFrame frame = thread.GetFrameAtIndex(i);
551 CMICmnMIValueList miValueList(true);
552 const MIuint maskVarTypes =
553 CMICmnLLDBDebugSessionInfo::eVariableType_Arguments;
554 if (!rSessionInfo.MIResponseFormVariableInfo(frame, maskVarTypes,
555 eVarInfoFormat, miValueList))
556 return MIstatus::failure;
557 const CMICmnMIValueConst miValueConst(CMIUtilString::Format("%d", i));
558 const CMICmnMIValueResult miValueResult("level", miValueConst);
559 CMICmnMIValueTuple miValueTuple(miValueResult);
560 const CMICmnMIValueResult miValueResult2("args", miValueList);
561 miValueTuple.Add(miValueResult2);
562 const CMICmnMIValueResult miValueResult3("frame", miValueTuple);
563 m_miValueList.Add(miValueResult3);
566 return MIstatus::success;
570 // Details: The invoker requires this function. The command prepares a MI Record
572 // for the work carried out in the Execute().
575 // Return: MIstatus::success - Functional succeeded.
576 // MIstatus::failure - Functional failed.
579 bool CMICmdCmdStackListArguments::Acknowledge() {
580 if (m_bThreadInvalid) {
581 // MI print "%s^done,stack-args=[]"
582 const CMICmnMIValueList miValueList(true);
583 const CMICmnMIValueResult miValueResult("stack-args", miValueList);
584 const CMICmnMIResultRecord miRecordResult(
585 m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done,
587 m_miResultRecord = miRecordResult;
588 return MIstatus::success;
592 // "%s^done,stack-args=[frame={level=\"0\",args=[%s]},frame={level=\"1\",args=[%s]}]"
593 const CMICmnMIValueResult miValueResult4("stack-args", m_miValueList);
594 const CMICmnMIResultRecord miRecordResult(
595 m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done,
597 m_miResultRecord = miRecordResult;
599 return MIstatus::success;
603 // Details: Required by the CMICmdFactory when registering *this command. The
605 // calls this function to create an instance of *this command.
606 // Type: Static method.
608 // Return: CMICmdBase * - Pointer to a new command.
611 CMICmdBase *CMICmdCmdStackListArguments::CreateSelf() {
612 return new CMICmdCmdStackListArguments();
617 // Details: CMICmdCmdStackListLocals constructor.
623 CMICmdCmdStackListLocals::CMICmdCmdStackListLocals()
624 : m_bThreadInvalid(false), m_miValueList(true),
625 m_constStrArgPrintValues("print-values") {
626 // Command factory matches this name with that received from the stdin stream
627 m_strMiCmd = "stack-list-locals";
629 // Required by the CMICmdFactory when registering *this command
630 m_pSelfCreatorFn = &CMICmdCmdStackListLocals::CreateSelf;
634 // Details: CMICmdCmdStackListLocals destructor.
635 // Type: Overrideable.
640 CMICmdCmdStackListLocals::~CMICmdCmdStackListLocals() {}
643 // Details: The invoker requires this function. The parses the command line
645 // arguments to extract values for each of those arguments.
648 // Return: MIstatus::success - Functional succeeded.
649 // MIstatus::failure - Functional failed.
652 bool CMICmdCmdStackListLocals::ParseArgs() {
654 new CMICmdArgValPrintValues(m_constStrArgPrintValues, true, true));
655 return ParseValidateCmdOptions();
659 // Details: The invoker requires this function. The command does work in this
661 // The command is likely to communicate with the LLDB SBDebugger in
665 // Return: MIstatus::success - Functional succeeded.
666 // MIstatus::failure - Functional failed.
669 bool CMICmdCmdStackListLocals::Execute() {
670 CMICMDBASE_GETOPTION(pArgThread, OptionLong, m_constStrArgThread);
671 CMICMDBASE_GETOPTION(pArgFrame, OptionLong, m_constStrArgFrame);
672 CMICMDBASE_GETOPTION(pArgPrintValues, PrintValues, m_constStrArgPrintValues);
674 // Retrieve the --thread option's thread ID (only 1)
675 MIuint64 nThreadId = UINT64_MAX;
676 if (pArgThread->GetFound()) {
677 if (!pArgThread->GetExpectedOption<CMICmdArgValNumber, MIuint64>(
679 SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_OPTION_NOT_FOUND),
680 m_cmdData.strMiCmd.c_str(),
681 m_constStrArgThread.c_str()));
682 return MIstatus::failure;
686 MIuint64 nFrame = UINT64_MAX;
687 if (pArgFrame->GetFound()) {
688 if (!pArgFrame->GetExpectedOption<CMICmdArgValNumber, MIuint64>(nFrame)) {
689 SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_OPTION_NOT_FOUND),
690 m_cmdData.strMiCmd.c_str(),
691 m_constStrArgFrame.c_str()));
692 return MIstatus::failure;
696 const CMICmnLLDBDebugSessionInfo::VariableInfoFormat_e eVarInfoFormat =
697 static_cast<CMICmnLLDBDebugSessionInfo::VariableInfoFormat_e>(
698 pArgPrintValues->GetValue());
700 CMICmnLLDBDebugSessionInfo &rSessionInfo(
701 CMICmnLLDBDebugSessionInfo::Instance());
702 lldb::SBProcess sbProcess = rSessionInfo.GetProcess();
703 lldb::SBThread thread = (nThreadId != UINT64_MAX)
704 ? sbProcess.GetThreadByIndexID(nThreadId)
705 : sbProcess.GetSelectedThread();
706 m_bThreadInvalid = !thread.IsValid();
707 if (m_bThreadInvalid)
708 return MIstatus::success;
710 const lldb::StopReason eStopReason = thread.GetStopReason();
711 if ((eStopReason == lldb::eStopReasonNone) ||
712 (eStopReason == lldb::eStopReasonInvalid)) {
713 m_bThreadInvalid = true;
714 return MIstatus::success;
717 lldb::SBFrame frame = (nFrame != UINT64_MAX) ? thread.GetFrameAtIndex(nFrame)
718 : thread.GetSelectedFrame();
720 CMICmnMIValueList miValueList(true);
721 const MIuint maskVarTypes = CMICmnLLDBDebugSessionInfo::eVariableType_Locals |
722 CMICmnLLDBDebugSessionInfo::eVariableType_InScope;
723 if (!rSessionInfo.MIResponseFormVariableInfo(frame, maskVarTypes,
724 eVarInfoFormat, miValueList))
725 return MIstatus::failure;
727 m_miValueList = miValueList;
729 return MIstatus::success;
733 // Details: The invoker requires this function. The command prepares a MI Record
735 // for the work carried out in the Execute().
738 // Return: MIstatus::success - Functional succeeded.
739 // MIstatus::failure - Functional failed.
742 bool CMICmdCmdStackListLocals::Acknowledge() {
743 if (m_bThreadInvalid) {
744 // MI print "%s^done,locals=[]"
745 const CMICmnMIValueList miValueList(true);
746 const CMICmnMIValueResult miValueResult("locals", miValueList);
747 const CMICmnMIResultRecord miRecordResult(
748 m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done,
750 m_miResultRecord = miRecordResult;
751 return MIstatus::success;
754 // MI print "%s^done,locals=[%s]"
755 const CMICmnMIValueResult miValueResult("locals", m_miValueList);
756 const CMICmnMIResultRecord miRecordResult(
757 m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done,
759 m_miResultRecord = miRecordResult;
761 return MIstatus::success;
765 // Details: Required by the CMICmdFactory when registering *this command. The
767 // calls this function to create an instance of *this command.
768 // Type: Static method.
770 // Return: CMICmdBase * - Pointer to a new command.
773 CMICmdBase *CMICmdCmdStackListLocals::CreateSelf() {
774 return new CMICmdCmdStackListLocals();
779 // Details: CMICmdCmdStackListVariables constructor.
785 CMICmdCmdStackListVariables::CMICmdCmdStackListVariables()
786 : m_bThreadInvalid(false), m_miValueList(true),
787 m_constStrArgPrintValues("print-values") {
788 // Command factory matches this name with that received from the stdin stream
789 m_strMiCmd = "stack-list-variables";
791 // Required by the CMICmdFactory when registering *this command
792 m_pSelfCreatorFn = &CMICmdCmdStackListVariables::CreateSelf;
796 // Details: CMICmdCmdStackListVariables destructor.
797 // Type: Overrideable.
802 CMICmdCmdStackListVariables::~CMICmdCmdStackListVariables() {}
805 // Details: The invoker requires this function. The parses the command line
807 // arguments to extract values for each of those arguments.
810 // Return: MIstatus::success - Functional succeeded.
811 // MIstatus::failure - Functional failed.
814 bool CMICmdCmdStackListVariables::ParseArgs() {
816 new CMICmdArgValPrintValues(m_constStrArgPrintValues, true, true));
817 return ParseValidateCmdOptions();
821 // Details: The invoker requires this function. The command does work in this
823 // The command is likely to communicate with the LLDB SBDebugger in
827 // Return: MIstatus::success - Functional succeeded.
828 // MIstatus::failure - Functional failed.
831 bool CMICmdCmdStackListVariables::Execute() {
832 CMICMDBASE_GETOPTION(pArgThread, OptionLong, m_constStrArgThread);
833 CMICMDBASE_GETOPTION(pArgFrame, OptionLong, m_constStrArgFrame);
834 CMICMDBASE_GETOPTION(pArgPrintValues, PrintValues, m_constStrArgPrintValues);
836 // Retrieve the --thread option's thread ID (only 1)
837 MIuint64 nThreadId = UINT64_MAX;
838 if (pArgThread->GetFound()) {
839 if (!pArgThread->GetExpectedOption<CMICmdArgValNumber, MIuint64>(
841 SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_OPTION_NOT_FOUND),
842 m_cmdData.strMiCmd.c_str(),
843 m_constStrArgThread.c_str()));
844 return MIstatus::failure;
848 MIuint64 nFrame = UINT64_MAX;
849 if (pArgFrame->GetFound()) {
850 if (!pArgFrame->GetExpectedOption<CMICmdArgValNumber, MIuint64>(nFrame)) {
851 SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_OPTION_NOT_FOUND),
852 m_cmdData.strMiCmd.c_str(),
853 m_constStrArgFrame.c_str()));
854 return MIstatus::failure;
858 const CMICmnLLDBDebugSessionInfo::VariableInfoFormat_e eVarInfoFormat =
859 static_cast<CMICmnLLDBDebugSessionInfo::VariableInfoFormat_e>(
860 pArgPrintValues->GetValue());
862 CMICmnLLDBDebugSessionInfo &rSessionInfo(
863 CMICmnLLDBDebugSessionInfo::Instance());
864 lldb::SBProcess sbProcess = rSessionInfo.GetProcess();
865 lldb::SBThread thread = (nThreadId != UINT64_MAX)
866 ? sbProcess.GetThreadByIndexID(nThreadId)
867 : sbProcess.GetSelectedThread();
868 m_bThreadInvalid = !thread.IsValid();
869 if (m_bThreadInvalid)
870 return MIstatus::success;
872 const lldb::StopReason eStopReason = thread.GetStopReason();
873 if ((eStopReason == lldb::eStopReasonNone) ||
874 (eStopReason == lldb::eStopReasonInvalid)) {
875 m_bThreadInvalid = true;
876 return MIstatus::success;
879 lldb::SBFrame frame = (nFrame != UINT64_MAX) ? thread.GetFrameAtIndex(nFrame)
880 : thread.GetSelectedFrame();
882 CMICmnMIValueList miValueList(true);
883 const MIuint maskVarTypes =
884 CMICmnLLDBDebugSessionInfo::eVariableType_Arguments |
885 CMICmnLLDBDebugSessionInfo::eVariableType_Locals |
886 CMICmnLLDBDebugSessionInfo::eVariableType_InScope;
887 if (!rSessionInfo.MIResponseFormVariableInfo(
888 frame, maskVarTypes, eVarInfoFormat, miValueList, 10, true))
889 return MIstatus::failure;
890 m_miValueList = miValueList;
892 return MIstatus::success;
896 // Details: The invoker requires this function. The command prepares a MI Record
898 // for the work carried out in the Execute().
901 // Return: MIstatus::success - Functional succeeded.
902 // MIstatus::failure - Functional failed.
905 bool CMICmdCmdStackListVariables::Acknowledge() {
906 if (m_bThreadInvalid) {
907 // MI print "%s^done,variables=[]"
908 const CMICmnMIValueList miValueList(true);
909 const CMICmnMIValueResult miValueResult("variables", miValueList);
910 const CMICmnMIResultRecord miRecordResult(
911 m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done,
913 m_miResultRecord = miRecordResult;
914 return MIstatus::success;
917 // MI print "%s^done,variables=[%s]"
918 const CMICmnMIValueResult miValueResult("variables", m_miValueList);
919 const CMICmnMIResultRecord miRecordResult(
920 m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done,
922 m_miResultRecord = miRecordResult;
924 return MIstatus::success;
928 // Details: Required by the CMICmdFactory when registering *this command. The
930 // calls this function to create an instance of *this command.
931 // Type: Static method.
933 // Return: CMICmdBase * - Pointer to a new command.
936 CMICmdBase *CMICmdCmdStackListVariables::CreateSelf() {
937 return new CMICmdCmdStackListVariables();
942 // Details: CMICmdCmdStackSelectFrame constructor.
948 CMICmdCmdStackSelectFrame::CMICmdCmdStackSelectFrame()
949 : m_bFrameInvalid(false), m_constStrArgFrameId("frame_id") {
950 // Command factory matches this name with that received from the stdin stream
951 m_strMiCmd = "stack-select-frame";
953 // Required by the CMICmdFactory when registering *this command
954 m_pSelfCreatorFn = &CMICmdCmdStackSelectFrame::CreateSelf;
958 // Details: CMICmdCmdStackSelectFrame destructor.
959 // Type: Overrideable.
964 CMICmdCmdStackSelectFrame::~CMICmdCmdStackSelectFrame() {}
967 // Details: The invoker requires this function. The parses the command line
969 // arguments to extract values for each of those arguments.
972 // Return: MIstatus::success - Function succeeded.
973 // MIstatus::failure - Function failed.
976 bool CMICmdCmdStackSelectFrame::ParseArgs() {
977 m_setCmdArgs.Add(new CMICmdArgValNumber(m_constStrArgFrameId, true, false));
978 return ParseValidateCmdOptions();
982 // Details: The invoker requires this function. The command does work in this
984 // The command is likely to communicate with the LLDB SBDebugger in
988 // Return: MIstatus::success - Function succeeded.
989 // MIstatus::failure - Function failed.
992 bool CMICmdCmdStackSelectFrame::Execute() {
993 CMICMDBASE_GETOPTION(pArgFrame, Number, m_constStrArgFrameId);
995 CMICmnLLDBDebugSessionInfo &rSessionInfo(
996 CMICmnLLDBDebugSessionInfo::Instance());
997 lldb::SBThread sbThread = rSessionInfo.GetProcess().GetSelectedThread();
999 const MIuint nFrameId = pArgFrame->GetValue();
1000 m_bFrameInvalid = (nFrameId >= sbThread.GetNumFrames());
1001 if (m_bFrameInvalid)
1002 return MIstatus::success;
1004 lldb::SBFrame sbFrame = sbThread.SetSelectedFrame(nFrameId);
1005 m_bFrameInvalid = !sbFrame.IsValid();
1007 return MIstatus::success;
1011 // Details: The invoker requires this function. The command prepares a MI Record
1013 // for the work carried out in the Execute().
1014 // Type: Overridden.
1016 // Return: MIstatus::success - Function succeeded.
1017 // MIstatus::failure - Function failed.
1020 bool CMICmdCmdStackSelectFrame::Acknowledge() {
1021 if (m_bFrameInvalid) {
1022 // MI print "%s^error,msg=\"Command '-stack-select-frame'. Frame ID
1024 const CMICmnMIValueConst miValueConst(CMIUtilString::Format(
1025 MIRSRC(IDS_CMD_ERR_FRAME_INVALID), m_cmdData.strMiCmd.c_str()));
1026 const CMICmnMIValueResult miValueResult("msg", miValueConst);
1027 const CMICmnMIResultRecord miRecordResult(
1028 m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error,
1030 m_miResultRecord = miRecordResult;
1032 return MIstatus::success;
1035 const CMICmnMIResultRecord miRecordResult(
1036 m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done);
1037 m_miResultRecord = miRecordResult;
1039 return MIstatus::success;
1043 // Details: Required by the CMICmdFactory when registering *this command. The
1045 // calls this function to create an instance of *this command.
1046 // Type: Static method.
1048 // Return: CMICmdBase * - Pointer to a new command.
1051 CMICmdBase *CMICmdCmdStackSelectFrame::CreateSelf() {
1052 return new CMICmdCmdStackSelectFrame();