1 //===-- MICmdCmdStack.cpp ---------------------------------------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // Overview: CMICmdCmdStackInfoDepth implementation.
11 // CMICmdCmdStackInfoFrame implementation.
12 // CMICmdCmdStackListFrames implementation.
13 // CMICmdCmdStackListArguments implementation.
14 // CMICmdCmdStackListLocals implementation.
15 // CMICmdCmdStackSelectFrame implementation.
17 // Third Party Headers:
18 #include "lldb/API/SBThread.h"
21 #include "MICmdArgValListOfN.h"
22 #include "MICmdArgValNumber.h"
23 #include "MICmdArgValOptionLong.h"
24 #include "MICmdArgValOptionShort.h"
25 #include "MICmdArgValPrintValues.h"
26 #include "MICmdArgValString.h"
27 #include "MICmdArgValThreadGrp.h"
28 #include "MICmdCmdStack.h"
29 #include "MICmnLLDBDebugSessionInfo.h"
30 #include "MICmnLLDBDebugger.h"
31 #include "MICmnMIOutOfBandRecord.h"
32 #include "MICmnMIResultRecord.h"
33 #include "MICmnMIValueConst.h"
38 //------------------------------------------------------------------------------------
39 // Details: CMICmdCmdStackInfoDepth constructor.
45 CMICmdCmdStackInfoDepth::CMICmdCmdStackInfoDepth()
46 : m_nThreadFrames(0), m_constStrArgMaxDepth("max-depth") {
47 // Command factory matches this name with that received from the stdin stream
48 m_strMiCmd = "stack-info-depth";
50 // Required by the CMICmdFactory when registering *this command
51 m_pSelfCreatorFn = &CMICmdCmdStackInfoDepth::CreateSelf;
55 //------------------------------------------------------------------------------------
56 // Details: CMICmdCmdStackInfoDepth destructor.
57 // Type: Overrideable.
62 CMICmdCmdStackInfoDepth::~CMICmdCmdStackInfoDepth() {}
65 //------------------------------------------------------------------------------------
66 // Details: The invoker requires this function. The parses the command line
68 // arguments to extract values for each of those arguments.
71 // Return: MIstatus::success - Functional succeeded.
72 // MIstatus::failure - Functional failed.
75 bool CMICmdCmdStackInfoDepth::ParseArgs() {
76 m_setCmdArgs.Add(new CMICmdArgValNumber(m_constStrArgMaxDepth, false, false));
77 return ParseValidateCmdOptions();
81 //------------------------------------------------------------------------------------
82 // Details: The invoker requires this function. The command does work in this
84 // The command is likely to communicate with the LLDB SBDebugger in
88 // Return: MIstatus::success - Functional succeeded.
89 // MIstatus::failure - Functional failed.
92 bool CMICmdCmdStackInfoDepth::Execute() {
93 CMICMDBASE_GETOPTION(pArgThread, OptionLong, m_constStrArgThread);
94 CMICMDBASE_GETOPTION(pArgMaxDepth, Number, m_constStrArgMaxDepth);
96 // Retrieve the --thread option's thread ID (only 1)
97 MIuint64 nThreadId = UINT64_MAX;
98 if (pArgThread->GetFound() &&
99 !pArgThread->GetExpectedOption<CMICmdArgValNumber, MIuint64>(nThreadId)) {
100 SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_OPTION_NOT_FOUND),
101 m_cmdData.strMiCmd.c_str(),
102 m_constStrArgThread.c_str()));
103 return MIstatus::failure;
106 CMICmnLLDBDebugSessionInfo &rSessionInfo(
107 CMICmnLLDBDebugSessionInfo::Instance());
108 lldb::SBProcess sbProcess = rSessionInfo.GetProcess();
109 lldb::SBThread thread = (nThreadId != UINT64_MAX)
110 ? sbProcess.GetThreadByIndexID(nThreadId)
111 : sbProcess.GetSelectedThread();
112 m_nThreadFrames = thread.GetNumFrames();
114 return MIstatus::success;
118 //------------------------------------------------------------------------------------
119 // Details: The invoker requires this function. The command prepares a MI Record
121 // for the work carried out in the Execute().
124 // Return: MIstatus::success - Functional succeeded.
125 // MIstatus::failure - Functional failed.
128 bool CMICmdCmdStackInfoDepth::Acknowledge() {
129 const CMIUtilString strDepth(CMIUtilString::Format("%d", m_nThreadFrames));
130 const CMICmnMIValueConst miValueConst(strDepth);
131 const CMICmnMIValueResult miValueResult("depth", miValueConst);
132 const CMICmnMIResultRecord miRecordResult(
133 m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done,
135 m_miResultRecord = miRecordResult;
137 return MIstatus::success;
141 //------------------------------------------------------------------------------------
142 // Details: Required by the CMICmdFactory when registering *this command. The
144 // calls this function to create an instance of *this command.
145 // Type: Static method.
147 // Return: CMICmdBase * - Pointer to a new command.
150 CMICmdBase *CMICmdCmdStackInfoDepth::CreateSelf() {
151 return new CMICmdCmdStackInfoDepth();
154 //---------------------------------------------------------------------------------------
155 //---------------------------------------------------------------------------------------
156 //---------------------------------------------------------------------------------------
159 //------------------------------------------------------------------------------------
160 // Details: CMICmdCmdStackInfoFrame constructor.
166 CMICmdCmdStackInfoFrame::CMICmdCmdStackInfoFrame() {
167 // Command factory matches this name with that received from the stdin stream
168 m_strMiCmd = "stack-info-frame";
170 // Required by the CMICmdFactory when registering *this command
171 m_pSelfCreatorFn = &CMICmdCmdStackInfoFrame::CreateSelf;
175 //------------------------------------------------------------------------------------
176 // Details: CMICmdCmdStackInfoFrame destructor.
177 // Type: Overrideable.
182 CMICmdCmdStackInfoFrame::~CMICmdCmdStackInfoFrame() {}
185 //------------------------------------------------------------------------------------
186 // Details: The invoker requires this function. The parses the command line
188 // arguments to extract values for each of those arguments.
191 // Return: MIstatus::success - Function succeeded.
192 // MIstatus::failure - Function failed.
195 bool CMICmdCmdStackInfoFrame::ParseArgs() { return ParseValidateCmdOptions(); }
198 //------------------------------------------------------------------------------------
199 // Details: The invoker requires this function. The command does work in this
201 // The command is likely to communicate with the LLDB SBDebugger in
205 // Return: MIstatus::success - Function succeeded.
206 // MIstatus::failure - Function failed.
209 bool CMICmdCmdStackInfoFrame::Execute() {
210 CMICmnLLDBDebugSessionInfo &rSessionInfo(
211 CMICmnLLDBDebugSessionInfo::Instance());
212 lldb::SBProcess sbProcess = rSessionInfo.GetProcess();
213 if (!sbProcess.IsValid()) {
214 SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_INVALID_PROCESS),
215 m_cmdData.strMiCmd.c_str()));
216 return MIstatus::failure;
219 lldb::SBThread sbThread = sbProcess.GetSelectedThread();
220 MIuint nFrameId = sbThread.GetSelectedFrame().GetFrameID();
221 if (!rSessionInfo.MIResponseFormFrameInfo(
223 CMICmnLLDBDebugSessionInfo::eFrameInfoFormat_NoArguments,
225 return MIstatus::failure;
227 return MIstatus::success;
231 //------------------------------------------------------------------------------------
232 // Details: The invoker requires this function. The command prepares a MI Record
234 // for the work carried out in the Execute().
237 // Return: MIstatus::success - Function succeeded.
238 // MIstatus::failure - Function failed.
241 bool CMICmdCmdStackInfoFrame::Acknowledge() {
242 const CMICmnMIValueResult miValueResult("frame", m_miValueTuple);
243 const CMICmnMIResultRecord miRecordResult(
244 m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done,
246 m_miResultRecord = miRecordResult;
248 return MIstatus::success;
252 //------------------------------------------------------------------------------------
253 // Details: Required by the CMICmdFactory when registering *this command. The
255 // calls this function to create an instance of *this command.
256 // Type: Static method.
258 // Return: CMICmdBase * - Pointer to a new command.
261 CMICmdBase *CMICmdCmdStackInfoFrame::CreateSelf() {
262 return new CMICmdCmdStackInfoFrame();
265 //---------------------------------------------------------------------------------------
266 //---------------------------------------------------------------------------------------
267 //---------------------------------------------------------------------------------------
270 //------------------------------------------------------------------------------------
271 // Details: CMICmdCmdStackListFrames constructor.
277 CMICmdCmdStackListFrames::CMICmdCmdStackListFrames()
278 : m_nThreadFrames(0), m_constStrArgFrameLow("low-frame"),
279 m_constStrArgFrameHigh("high-frame") {
280 // Command factory matches this name with that received from the stdin stream
281 m_strMiCmd = "stack-list-frames";
283 // Required by the CMICmdFactory when registering *this command
284 m_pSelfCreatorFn = &CMICmdCmdStackListFrames::CreateSelf;
288 //------------------------------------------------------------------------------------
289 // Details: CMICmdCmdStackListFrames destructor.
290 // Type: Overrideable.
295 CMICmdCmdStackListFrames::~CMICmdCmdStackListFrames() {
296 m_vecMIValueResult.clear();
300 //------------------------------------------------------------------------------------
301 // Details: The invoker requires this function. The parses the command line
303 // arguments to extract values for each of those arguments.
306 // Return: MIstatus::success - Functional succeeded.
307 // MIstatus::failure - Functional failed.
310 bool CMICmdCmdStackListFrames::ParseArgs() {
311 m_setCmdArgs.Add(new CMICmdArgValNumber(m_constStrArgFrameLow, false, true));
312 m_setCmdArgs.Add(new CMICmdArgValNumber(m_constStrArgFrameHigh, false, true));
313 return ParseValidateCmdOptions();
317 //------------------------------------------------------------------------------------
318 // Details: The invoker requires this function. The command does work in this
320 // The command is likely to communicate with the LLDB SBDebugger in
324 // Return: MIstatus::success - Functional succeeded.
325 // MIstatus::failure - Functional failed.
328 bool CMICmdCmdStackListFrames::Execute() {
329 CMICMDBASE_GETOPTION(pArgThread, OptionLong, m_constStrArgThread);
330 CMICMDBASE_GETOPTION(pArgFrameLow, Number, m_constStrArgFrameLow);
331 CMICMDBASE_GETOPTION(pArgFrameHigh, Number, m_constStrArgFrameHigh);
333 // Retrieve the --thread option's thread ID (only 1)
334 MIuint64 nThreadId = UINT64_MAX;
335 if (pArgThread->GetFound() &&
336 !pArgThread->GetExpectedOption<CMICmdArgValNumber, MIuint64>(nThreadId)) {
337 SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_OPTION_NOT_FOUND),
338 m_cmdData.strMiCmd.c_str(),
339 m_constStrArgThread.c_str()));
340 return MIstatus::failure;
343 // Frame low and high options are not mandatory
345 pArgFrameHigh->GetFound() ? pArgFrameHigh->GetValue() : UINT32_MAX;
346 const MIuint nFrameLow =
347 pArgFrameLow->GetFound() ? pArgFrameLow->GetValue() : 0;
349 CMICmnLLDBDebugSessionInfo &rSessionInfo(
350 CMICmnLLDBDebugSessionInfo::Instance());
351 lldb::SBProcess sbProcess = rSessionInfo.GetProcess();
352 lldb::SBThread thread = (nThreadId != UINT64_MAX)
353 ? sbProcess.GetThreadByIndexID(nThreadId)
354 : sbProcess.GetSelectedThread();
355 MIuint nThreadFrames = thread.GetNumFrames();
357 // Adjust nThreadFrames for the nFrameHigh argument as we use nFrameHigh+1 in
358 // the min calc as the arg
359 // is not an index, but a frame id value.
360 if (nFrameHigh < UINT32_MAX) {
362 nThreadFrames = (nFrameHigh < nThreadFrames) ? nFrameHigh : nThreadFrames;
365 m_nThreadFrames = nThreadFrames;
366 if (nThreadFrames == 0)
367 return MIstatus::success;
369 m_vecMIValueResult.clear();
370 for (MIuint nLevel = nFrameLow; nLevel < nThreadFrames; nLevel++) {
371 CMICmnMIValueTuple miValueTuple;
372 if (!rSessionInfo.MIResponseFormFrameInfo(
374 CMICmnLLDBDebugSessionInfo::eFrameInfoFormat_NoArguments,
376 return MIstatus::failure;
378 const CMICmnMIValueResult miValueResult8("frame", miValueTuple);
379 m_vecMIValueResult.push_back(miValueResult8);
382 return MIstatus::success;
386 //------------------------------------------------------------------------------------
387 // Details: The invoker requires this function. The command prepares a MI Record
389 // for the work carried out in the Execute().
392 // Return: MIstatus::success - Functional succeeded.
393 // MIstatus::failure - Functional failed.
396 bool CMICmdCmdStackListFrames::Acknowledge() {
397 if (m_nThreadFrames == 0) {
398 // MI print "3^done,stack=[{}]"
399 const CMICmnMIValueTuple miValueTuple;
400 const CMICmnMIValueList miValueList(miValueTuple);
401 const CMICmnMIValueResult miValueResult("stack", miValueList);
402 const CMICmnMIResultRecord miRecordResult(
403 m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done,
405 m_miResultRecord = miRecordResult;
407 return MIstatus::success;
410 // Build up a list of thread information from tuples
411 VecMIValueResult_t::const_iterator it = m_vecMIValueResult.begin();
412 if (it == m_vecMIValueResult.end()) {
413 // MI print "3^done,stack=[{}]"
414 const CMICmnMIValueTuple miValueTuple;
415 const CMICmnMIValueList miValueList(miValueTuple);
416 const CMICmnMIValueResult miValueResult("stack", miValueList);
417 const CMICmnMIResultRecord miRecordResult(
418 m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done,
420 m_miResultRecord = miRecordResult;
421 return MIstatus::success;
423 CMICmnMIValueList miValueList(*it);
425 while (it != m_vecMIValueResult.end()) {
426 const CMICmnMIValueResult &rTuple(*it);
427 miValueList.Add(rTuple);
432 const CMICmnMIValueResult miValueResult("stack", miValueList);
433 const CMICmnMIResultRecord miRecordResult(
434 m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done,
436 m_miResultRecord = miRecordResult;
438 return MIstatus::success;
442 //------------------------------------------------------------------------------------
443 // Details: Required by the CMICmdFactory when registering *this command. The
445 // calls this function to create an instance of *this command.
446 // Type: Static method.
448 // Return: CMICmdBase * - Pointer to a new command.
451 CMICmdBase *CMICmdCmdStackListFrames::CreateSelf() {
452 return new CMICmdCmdStackListFrames();
455 //---------------------------------------------------------------------------------------
456 //---------------------------------------------------------------------------------------
457 //---------------------------------------------------------------------------------------
460 //------------------------------------------------------------------------------------
461 // Details: CMICmdCmdStackListArguments constructor.
467 CMICmdCmdStackListArguments::CMICmdCmdStackListArguments()
468 : m_bThreadInvalid(false), m_miValueList(true),
469 m_constStrArgPrintValues("print-values"),
470 m_constStrArgFrameLow("low-frame"), m_constStrArgFrameHigh("high-frame") {
471 // Command factory matches this name with that received from the stdin stream
472 m_strMiCmd = "stack-list-arguments";
474 // Required by the CMICmdFactory when registering *this command
475 m_pSelfCreatorFn = &CMICmdCmdStackListArguments::CreateSelf;
479 //------------------------------------------------------------------------------------
480 // Details: CMICmdCmdStackListArguments destructor.
481 // Type: Overrideable.
486 CMICmdCmdStackListArguments::~CMICmdCmdStackListArguments() {}
489 //------------------------------------------------------------------------------------
490 // Details: The invoker requires this function. The parses the command line
492 // arguments to extract values for each of those arguments.
495 // Return: MIstatus::success - Functional succeeded.
496 // MIstatus::failure - Functional failed.
499 bool CMICmdCmdStackListArguments::ParseArgs() {
501 new CMICmdArgValPrintValues(m_constStrArgPrintValues, true, true));
502 m_setCmdArgs.Add(new CMICmdArgValNumber(m_constStrArgFrameLow, false, true));
503 m_setCmdArgs.Add(new CMICmdArgValNumber(m_constStrArgFrameHigh, false, true));
504 return ParseValidateCmdOptions();
508 //------------------------------------------------------------------------------------
509 // Details: The invoker requires this function. The command does work in this
511 // The command is likely to communicate with the LLDB SBDebugger in
515 // Return: MIstatus::success - Functional succeeded.
516 // MIstatus::failure - Functional failed.
519 bool CMICmdCmdStackListArguments::Execute() {
520 CMICMDBASE_GETOPTION(pArgThread, OptionLong, m_constStrArgThread);
521 CMICMDBASE_GETOPTION(pArgPrintValues, PrintValues, m_constStrArgPrintValues);
522 CMICMDBASE_GETOPTION(pArgFrameLow, Number, m_constStrArgFrameLow);
523 CMICMDBASE_GETOPTION(pArgFrameHigh, Number, m_constStrArgFrameHigh);
525 // Retrieve the --thread option's thread ID (only 1)
526 MIuint64 nThreadId = UINT64_MAX;
527 if (pArgThread->GetFound()) {
528 if (!pArgThread->GetExpectedOption<CMICmdArgValNumber, MIuint64>(
530 SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_OPTION_NOT_FOUND),
531 m_cmdData.strMiCmd.c_str(),
532 m_constStrArgThread.c_str()));
533 return MIstatus::failure;
537 const CMICmnLLDBDebugSessionInfo::VariableInfoFormat_e eVarInfoFormat =
538 static_cast<CMICmnLLDBDebugSessionInfo::VariableInfoFormat_e>(
539 pArgPrintValues->GetValue());
541 MIuint nFrameLow = 0;
542 MIuint nFrameHigh = UINT32_MAX;
543 if (pArgFrameLow->GetFound() && pArgFrameHigh->GetFound()) {
544 nFrameLow = pArgFrameLow->GetValue();
545 nFrameHigh = pArgFrameHigh->GetValue() + 1;
546 } else if (pArgFrameLow->GetFound() || pArgFrameHigh->GetFound()) {
547 // Only low-frame or high-frame was specified but both are required
549 CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_THREAD_FRAME_RANGE_INVALID),
550 m_cmdData.strMiCmd.c_str()));
551 return MIstatus::failure;
554 CMICmnLLDBDebugSessionInfo &rSessionInfo(
555 CMICmnLLDBDebugSessionInfo::Instance());
556 lldb::SBProcess sbProcess = rSessionInfo.GetProcess();
557 lldb::SBThread thread = (nThreadId != UINT64_MAX)
558 ? sbProcess.GetThreadByIndexID(nThreadId)
559 : sbProcess.GetSelectedThread();
560 m_bThreadInvalid = !thread.IsValid();
561 if (m_bThreadInvalid)
562 return MIstatus::success;
564 const lldb::StopReason eStopReason = thread.GetStopReason();
565 if ((eStopReason == lldb::eStopReasonNone) ||
566 (eStopReason == lldb::eStopReasonInvalid)) {
567 m_bThreadInvalid = true;
568 return MIstatus::success;
571 const MIuint nFrames = thread.GetNumFrames();
572 if (nFrameLow >= nFrames) {
573 // The low-frame is larger than the actual number of frames
575 CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_THREAD_FRAME_RANGE_INVALID),
576 m_cmdData.strMiCmd.c_str()));
577 return MIstatus::failure;
580 nFrameHigh = std::min(nFrameHigh, nFrames);
581 for (MIuint i = nFrameLow; i < nFrameHigh; i++) {
582 lldb::SBFrame frame = thread.GetFrameAtIndex(i);
583 CMICmnMIValueList miValueList(true);
584 const MIuint maskVarTypes =
585 CMICmnLLDBDebugSessionInfo::eVariableType_Arguments;
586 if (!rSessionInfo.MIResponseFormVariableInfo(frame, maskVarTypes,
587 eVarInfoFormat, miValueList))
588 return MIstatus::failure;
589 const CMICmnMIValueConst miValueConst(CMIUtilString::Format("%d", i));
590 const CMICmnMIValueResult miValueResult("level", miValueConst);
591 CMICmnMIValueTuple miValueTuple(miValueResult);
592 const CMICmnMIValueResult miValueResult2("args", miValueList);
593 miValueTuple.Add(miValueResult2);
594 const CMICmnMIValueResult miValueResult3("frame", miValueTuple);
595 m_miValueList.Add(miValueResult3);
598 return MIstatus::success;
602 //------------------------------------------------------------------------------------
603 // Details: The invoker requires this function. The command prepares a MI Record
605 // for the work carried out in the Execute().
608 // Return: MIstatus::success - Functional succeeded.
609 // MIstatus::failure - Functional failed.
612 bool CMICmdCmdStackListArguments::Acknowledge() {
613 if (m_bThreadInvalid) {
614 // MI print "%s^done,stack-args=[]"
615 const CMICmnMIValueList miValueList(true);
616 const CMICmnMIValueResult miValueResult("stack-args", miValueList);
617 const CMICmnMIResultRecord miRecordResult(
618 m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done,
620 m_miResultRecord = miRecordResult;
621 return MIstatus::success;
625 // "%s^done,stack-args=[frame={level=\"0\",args=[%s]},frame={level=\"1\",args=[%s]}]"
626 const CMICmnMIValueResult miValueResult4("stack-args", m_miValueList);
627 const CMICmnMIResultRecord miRecordResult(
628 m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done,
630 m_miResultRecord = miRecordResult;
632 return MIstatus::success;
636 //------------------------------------------------------------------------------------
637 // Details: Required by the CMICmdFactory when registering *this command. The
639 // calls this function to create an instance of *this command.
640 // Type: Static method.
642 // Return: CMICmdBase * - Pointer to a new command.
645 CMICmdBase *CMICmdCmdStackListArguments::CreateSelf() {
646 return new CMICmdCmdStackListArguments();
649 //---------------------------------------------------------------------------------------
650 //---------------------------------------------------------------------------------------
651 //---------------------------------------------------------------------------------------
654 //------------------------------------------------------------------------------------
655 // Details: CMICmdCmdStackListLocals constructor.
661 CMICmdCmdStackListLocals::CMICmdCmdStackListLocals()
662 : m_bThreadInvalid(false), m_miValueList(true),
663 m_constStrArgPrintValues("print-values") {
664 // Command factory matches this name with that received from the stdin stream
665 m_strMiCmd = "stack-list-locals";
667 // Required by the CMICmdFactory when registering *this command
668 m_pSelfCreatorFn = &CMICmdCmdStackListLocals::CreateSelf;
672 //------------------------------------------------------------------------------------
673 // Details: CMICmdCmdStackListLocals destructor.
674 // Type: Overrideable.
679 CMICmdCmdStackListLocals::~CMICmdCmdStackListLocals() {}
682 //------------------------------------------------------------------------------------
683 // Details: The invoker requires this function. The parses the command line
685 // arguments to extract values for each of those arguments.
688 // Return: MIstatus::success - Functional succeeded.
689 // MIstatus::failure - Functional failed.
692 bool CMICmdCmdStackListLocals::ParseArgs() {
694 new CMICmdArgValPrintValues(m_constStrArgPrintValues, true, true));
695 return ParseValidateCmdOptions();
699 //------------------------------------------------------------------------------------
700 // Details: The invoker requires this function. The command does work in this
702 // The command is likely to communicate with the LLDB SBDebugger in
706 // Return: MIstatus::success - Functional succeeded.
707 // MIstatus::failure - Functional failed.
710 bool CMICmdCmdStackListLocals::Execute() {
711 CMICMDBASE_GETOPTION(pArgThread, OptionLong, m_constStrArgThread);
712 CMICMDBASE_GETOPTION(pArgFrame, OptionLong, m_constStrArgFrame);
713 CMICMDBASE_GETOPTION(pArgPrintValues, PrintValues, m_constStrArgPrintValues);
715 // Retrieve the --thread option's thread ID (only 1)
716 MIuint64 nThreadId = UINT64_MAX;
717 if (pArgThread->GetFound()) {
718 if (!pArgThread->GetExpectedOption<CMICmdArgValNumber, MIuint64>(
720 SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_OPTION_NOT_FOUND),
721 m_cmdData.strMiCmd.c_str(),
722 m_constStrArgThread.c_str()));
723 return MIstatus::failure;
727 MIuint64 nFrame = UINT64_MAX;
728 if (pArgFrame->GetFound()) {
729 if (!pArgFrame->GetExpectedOption<CMICmdArgValNumber, MIuint64>(nFrame)) {
730 SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_OPTION_NOT_FOUND),
731 m_cmdData.strMiCmd.c_str(),
732 m_constStrArgFrame.c_str()));
733 return MIstatus::failure;
737 const CMICmnLLDBDebugSessionInfo::VariableInfoFormat_e eVarInfoFormat =
738 static_cast<CMICmnLLDBDebugSessionInfo::VariableInfoFormat_e>(
739 pArgPrintValues->GetValue());
741 CMICmnLLDBDebugSessionInfo &rSessionInfo(
742 CMICmnLLDBDebugSessionInfo::Instance());
743 lldb::SBProcess sbProcess = rSessionInfo.GetProcess();
744 lldb::SBThread thread = (nThreadId != UINT64_MAX)
745 ? sbProcess.GetThreadByIndexID(nThreadId)
746 : sbProcess.GetSelectedThread();
747 m_bThreadInvalid = !thread.IsValid();
748 if (m_bThreadInvalid)
749 return MIstatus::success;
751 const lldb::StopReason eStopReason = thread.GetStopReason();
752 if ((eStopReason == lldb::eStopReasonNone) ||
753 (eStopReason == lldb::eStopReasonInvalid)) {
754 m_bThreadInvalid = true;
755 return MIstatus::success;
758 lldb::SBFrame frame = (nFrame != UINT64_MAX) ? thread.GetFrameAtIndex(nFrame)
759 : thread.GetSelectedFrame();
761 CMICmnMIValueList miValueList(true);
762 const MIuint maskVarTypes = CMICmnLLDBDebugSessionInfo::eVariableType_Locals |
763 CMICmnLLDBDebugSessionInfo::eVariableType_InScope;
764 if (!rSessionInfo.MIResponseFormVariableInfo(frame, maskVarTypes,
765 eVarInfoFormat, miValueList))
766 return MIstatus::failure;
768 m_miValueList = miValueList;
770 return MIstatus::success;
774 //------------------------------------------------------------------------------------
775 // Details: The invoker requires this function. The command prepares a MI Record
777 // for the work carried out in the Execute().
780 // Return: MIstatus::success - Functional succeeded.
781 // MIstatus::failure - Functional failed.
784 bool CMICmdCmdStackListLocals::Acknowledge() {
785 if (m_bThreadInvalid) {
786 // MI print "%s^done,locals=[]"
787 const CMICmnMIValueList miValueList(true);
788 const CMICmnMIValueResult miValueResult("locals", miValueList);
789 const CMICmnMIResultRecord miRecordResult(
790 m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done,
792 m_miResultRecord = miRecordResult;
793 return MIstatus::success;
796 // MI print "%s^done,locals=[%s]"
797 const CMICmnMIValueResult miValueResult("locals", m_miValueList);
798 const CMICmnMIResultRecord miRecordResult(
799 m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done,
801 m_miResultRecord = miRecordResult;
803 return MIstatus::success;
807 //------------------------------------------------------------------------------------
808 // Details: Required by the CMICmdFactory when registering *this command. The
810 // calls this function to create an instance of *this command.
811 // Type: Static method.
813 // Return: CMICmdBase * - Pointer to a new command.
816 CMICmdBase *CMICmdCmdStackListLocals::CreateSelf() {
817 return new CMICmdCmdStackListLocals();
820 //---------------------------------------------------------------------------------------
821 //---------------------------------------------------------------------------------------
822 //---------------------------------------------------------------------------------------
825 //------------------------------------------------------------------------------------
826 // Details: CMICmdCmdStackListVariables constructor.
832 CMICmdCmdStackListVariables::CMICmdCmdStackListVariables()
833 : m_bThreadInvalid(false), m_miValueList(true),
834 m_constStrArgPrintValues("print-values") {
835 // Command factory matches this name with that received from the stdin stream
836 m_strMiCmd = "stack-list-variables";
838 // Required by the CMICmdFactory when registering *this command
839 m_pSelfCreatorFn = &CMICmdCmdStackListVariables::CreateSelf;
843 //------------------------------------------------------------------------------------
844 // Details: CMICmdCmdStackListVariables destructor.
845 // Type: Overrideable.
850 CMICmdCmdStackListVariables::~CMICmdCmdStackListVariables() {}
853 //------------------------------------------------------------------------------------
854 // Details: The invoker requires this function. The parses the command line
856 // arguments to extract values for each of those arguments.
859 // Return: MIstatus::success - Functional succeeded.
860 // MIstatus::failure - Functional failed.
863 bool CMICmdCmdStackListVariables::ParseArgs() {
865 new CMICmdArgValPrintValues(m_constStrArgPrintValues, true, true));
866 return ParseValidateCmdOptions();
870 //------------------------------------------------------------------------------------
871 // Details: The invoker requires this function. The command does work in this
873 // The command is likely to communicate with the LLDB SBDebugger in
877 // Return: MIstatus::success - Functional succeeded.
878 // MIstatus::failure - Functional failed.
881 bool CMICmdCmdStackListVariables::Execute() {
882 CMICMDBASE_GETOPTION(pArgThread, OptionLong, m_constStrArgThread);
883 CMICMDBASE_GETOPTION(pArgFrame, OptionLong, m_constStrArgFrame);
884 CMICMDBASE_GETOPTION(pArgPrintValues, PrintValues, m_constStrArgPrintValues);
886 // Retrieve the --thread option's thread ID (only 1)
887 MIuint64 nThreadId = UINT64_MAX;
888 if (pArgThread->GetFound()) {
889 if (!pArgThread->GetExpectedOption<CMICmdArgValNumber, MIuint64>(
891 SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_OPTION_NOT_FOUND),
892 m_cmdData.strMiCmd.c_str(),
893 m_constStrArgThread.c_str()));
894 return MIstatus::failure;
898 MIuint64 nFrame = UINT64_MAX;
899 if (pArgFrame->GetFound()) {
900 if (!pArgFrame->GetExpectedOption<CMICmdArgValNumber, MIuint64>(nFrame)) {
901 SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_OPTION_NOT_FOUND),
902 m_cmdData.strMiCmd.c_str(),
903 m_constStrArgFrame.c_str()));
904 return MIstatus::failure;
908 const CMICmnLLDBDebugSessionInfo::VariableInfoFormat_e eVarInfoFormat =
909 static_cast<CMICmnLLDBDebugSessionInfo::VariableInfoFormat_e>(
910 pArgPrintValues->GetValue());
912 CMICmnLLDBDebugSessionInfo &rSessionInfo(
913 CMICmnLLDBDebugSessionInfo::Instance());
914 lldb::SBProcess sbProcess = rSessionInfo.GetProcess();
915 lldb::SBThread thread = (nThreadId != UINT64_MAX)
916 ? sbProcess.GetThreadByIndexID(nThreadId)
917 : sbProcess.GetSelectedThread();
918 m_bThreadInvalid = !thread.IsValid();
919 if (m_bThreadInvalid)
920 return MIstatus::success;
922 const lldb::StopReason eStopReason = thread.GetStopReason();
923 if ((eStopReason == lldb::eStopReasonNone) ||
924 (eStopReason == lldb::eStopReasonInvalid)) {
925 m_bThreadInvalid = true;
926 return MIstatus::success;
929 lldb::SBFrame frame = (nFrame != UINT64_MAX) ? thread.GetFrameAtIndex(nFrame)
930 : thread.GetSelectedFrame();
932 CMICmnMIValueList miValueList(true);
933 const MIuint maskVarTypes =
934 CMICmnLLDBDebugSessionInfo::eVariableType_Arguments |
935 CMICmnLLDBDebugSessionInfo::eVariableType_Locals |
936 CMICmnLLDBDebugSessionInfo::eVariableType_InScope;
937 if (!rSessionInfo.MIResponseFormVariableInfo(
938 frame, maskVarTypes, eVarInfoFormat, miValueList, 10, true))
939 return MIstatus::failure;
940 m_miValueList = miValueList;
942 return MIstatus::success;
946 //------------------------------------------------------------------------------------
947 // Details: The invoker requires this function. The command prepares a MI Record
949 // for the work carried out in the Execute().
952 // Return: MIstatus::success - Functional succeeded.
953 // MIstatus::failure - Functional failed.
956 bool CMICmdCmdStackListVariables::Acknowledge() {
957 if (m_bThreadInvalid) {
958 // MI print "%s^done,variables=[]"
959 const CMICmnMIValueList miValueList(true);
960 const CMICmnMIValueResult miValueResult("variables", miValueList);
961 const CMICmnMIResultRecord miRecordResult(
962 m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done,
964 m_miResultRecord = miRecordResult;
965 return MIstatus::success;
968 // MI print "%s^done,variables=[%s]"
969 const CMICmnMIValueResult miValueResult("variables", m_miValueList);
970 const CMICmnMIResultRecord miRecordResult(
971 m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done,
973 m_miResultRecord = miRecordResult;
975 return MIstatus::success;
979 //------------------------------------------------------------------------------------
980 // Details: Required by the CMICmdFactory when registering *this command. The
982 // calls this function to create an instance of *this command.
983 // Type: Static method.
985 // Return: CMICmdBase * - Pointer to a new command.
988 CMICmdBase *CMICmdCmdStackListVariables::CreateSelf() {
989 return new CMICmdCmdStackListVariables();
992 //---------------------------------------------------------------------------------------
993 //---------------------------------------------------------------------------------------
994 //---------------------------------------------------------------------------------------
997 //------------------------------------------------------------------------------------
998 // Details: CMICmdCmdStackSelectFrame constructor.
1004 CMICmdCmdStackSelectFrame::CMICmdCmdStackSelectFrame()
1005 : m_bFrameInvalid(false), m_constStrArgFrameId("frame_id") {
1006 // Command factory matches this name with that received from the stdin stream
1007 m_strMiCmd = "stack-select-frame";
1009 // Required by the CMICmdFactory when registering *this command
1010 m_pSelfCreatorFn = &CMICmdCmdStackSelectFrame::CreateSelf;
1014 //------------------------------------------------------------------------------------
1015 // Details: CMICmdCmdStackSelectFrame destructor.
1016 // Type: Overrideable.
1021 CMICmdCmdStackSelectFrame::~CMICmdCmdStackSelectFrame() {}
1024 //------------------------------------------------------------------------------------
1025 // Details: The invoker requires this function. The parses the command line
1027 // arguments to extract values for each of those arguments.
1028 // Type: Overridden.
1030 // Return: MIstatus::success - Function succeeded.
1031 // MIstatus::failure - Function failed.
1034 bool CMICmdCmdStackSelectFrame::ParseArgs() {
1035 m_setCmdArgs.Add(new CMICmdArgValNumber(m_constStrArgFrameId, true, false));
1036 return ParseValidateCmdOptions();
1040 //------------------------------------------------------------------------------------
1041 // Details: The invoker requires this function. The command does work in this
1043 // The command is likely to communicate with the LLDB SBDebugger in
1045 // Type: Overridden.
1047 // Return: MIstatus::success - Function succeeded.
1048 // MIstatus::failure - Function failed.
1051 bool CMICmdCmdStackSelectFrame::Execute() {
1052 CMICMDBASE_GETOPTION(pArgFrame, Number, m_constStrArgFrameId);
1054 CMICmnLLDBDebugSessionInfo &rSessionInfo(
1055 CMICmnLLDBDebugSessionInfo::Instance());
1056 lldb::SBThread sbThread = rSessionInfo.GetProcess().GetSelectedThread();
1058 const MIuint nFrameId = pArgFrame->GetValue();
1059 m_bFrameInvalid = (nFrameId >= sbThread.GetNumFrames());
1060 if (m_bFrameInvalid)
1061 return MIstatus::success;
1063 lldb::SBFrame sbFrame = sbThread.SetSelectedFrame(nFrameId);
1064 m_bFrameInvalid = !sbFrame.IsValid();
1066 return MIstatus::success;
1070 //------------------------------------------------------------------------------------
1071 // Details: The invoker requires this function. The command prepares a MI Record
1073 // for the work carried out in the Execute().
1074 // Type: Overridden.
1076 // Return: MIstatus::success - Function succeeded.
1077 // MIstatus::failure - Function failed.
1080 bool CMICmdCmdStackSelectFrame::Acknowledge() {
1081 if (m_bFrameInvalid) {
1082 // MI print "%s^error,msg=\"Command '-stack-select-frame'. Frame ID
1084 const CMICmnMIValueConst miValueConst(CMIUtilString::Format(
1085 MIRSRC(IDS_CMD_ERR_FRAME_INVALID), m_cmdData.strMiCmd.c_str()));
1086 const CMICmnMIValueResult miValueResult("msg", miValueConst);
1087 const CMICmnMIResultRecord miRecordResult(
1088 m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error,
1090 m_miResultRecord = miRecordResult;
1092 return MIstatus::success;
1095 const CMICmnMIResultRecord miRecordResult(
1096 m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done);
1097 m_miResultRecord = miRecordResult;
1099 return MIstatus::success;
1103 //------------------------------------------------------------------------------------
1104 // Details: Required by the CMICmdFactory when registering *this command. The
1106 // calls this function to create an instance of *this command.
1107 // Type: Static method.
1109 // Return: CMICmdBase * - Pointer to a new command.
1112 CMICmdBase *CMICmdCmdStackSelectFrame::CreateSelf() {
1113 return new CMICmdCmdStackSelectFrame();