summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lldb/test/tools/lldb-mi/TestMiStack.py56
-rw-r--r--lldb/tools/lldb-mi/MICmdCmdStack.cpp122
-rw-r--r--lldb/tools/lldb-mi/MICmdCmdStack.h31
-rw-r--r--lldb/tools/lldb-mi/MICmdCommands.cpp1
4 files changed, 210 insertions, 0 deletions
diff --git a/lldb/test/tools/lldb-mi/TestMiStack.py b/lldb/test/tools/lldb-mi/TestMiStack.py
index fa974c6d6dc..3caf8f45ada 100644
--- a/lldb/test/tools/lldb-mi/TestMiStack.py
+++ b/lldb/test/tools/lldb-mi/TestMiStack.py
@@ -242,5 +242,61 @@ class MiStackTestCase(lldbmi_testcase.MiTestCaseBase):
self.runCmd("-stack-list-frames 0 0")
self.expect("\^done,stack=\[frame=\{level=\"0\",addr=\".+\",func=\"main\",file=\"main\.c\",fullname=\".*main\.c\",line=\".+\"\}\]")
+ @lldbmi_test
+ @expectedFailureWindows("llvm.org/pr22274: need a pexpect replacement for windows")
+ @skipIfFreeBSD # llvm.org/pr22411: Failure presumably due to known thread races
+ @skipIfLinux # llvm.org/pr22411: Failure presumably due to known thread races
+ def test_lldbmi_stack_select_frame(self):
+ """Test that 'lldb-mi --interpreter' can choose current frame."""
+
+ self.spawnLldbMi(args = None)
+
+ # Load executable
+ self.runCmd("-file-exec-and-symbols %s" % self.myexe)
+ self.expect("\^done")
+
+ # Run to main
+ self.runCmd("-break-insert -f main")
+ self.expect("\^done,bkpt={number=\"1\"")
+ self.runCmd("-exec-run")
+ self.expect("\^running")
+ self.expect("\*stopped,reason=\"breakpoint-hit\"")
+
+ # Test that -stack-select-frame requires 1 mandatory argument
+ self.runCmd("-stack-select-frame")
+ self.expect("\^error,msg=\"Command 'stack-select-frame'. Command Args. Missing options, 1 or more required\"")
+
+ # Test that -stack-select-frame fails on invalid frame number
+ self.runCmd("-stack-select-frame 99")
+ self.expect("\^error,msg=\"Command 'stack-select-frame'. Frame ID invalid\"")
+
+ # Test that current frame is #0
+ self.runCmd("-stack-info-frame")
+ self.expect("\^done,frame=\{level=\"0\",addr=\".+\",func=\"main\",file=\"main\.c\",fullname=\".*main\.c\",line=\"\d+\"\}")
+
+ # Test that -stack-select-frame can select the selected frame
+ self.runCmd("-stack-select-frame 0")
+ self.expect("\^done")
+
+ # Test that current frame is still #0
+ self.runCmd("-stack-info-frame")
+ self.expect("\^done,frame=\{level=\"0\",addr=\".+\",func=\"main\",file=\"main\.c\",fullname=\".*main\.c\",line=\"\d+\"\}")
+
+ # Test that -stack-select-frame can select frame #1 (parent frame)
+ self.runCmd("-stack-select-frame 1")
+ self.expect("\^done")
+
+ # Test that current frame is #1
+ self.runCmd("-stack-info-frame")
+ self.expect("\^done,frame=\{level=\"1\",addr=\".+\",func=\".+\",file=\"\?\?\",fullname=\"\?\?\",line=\"-1\"\}")
+
+ # Test that -stack-select-frame can select frame #0 (child frame)
+ self.runCmd("-stack-select-frame 0")
+ self.expect("\^done")
+
+ # Test that current frame is #0 and it has the same information
+ self.runCmd("-stack-info-frame")
+ self.expect("\^done,frame=\{level=\"0\",addr=\".+\",func=\"main\",file=\"main\.c\",fullname=\".*main\.c\",line=\"\d+\"\}")
+
if __name__ == '__main__':
unittest2.main()
diff --git a/lldb/tools/lldb-mi/MICmdCmdStack.cpp b/lldb/tools/lldb-mi/MICmdCmdStack.cpp
index b23a57fd46c..6e1b6078fb4 100644
--- a/lldb/tools/lldb-mi/MICmdCmdStack.cpp
+++ b/lldb/tools/lldb-mi/MICmdCmdStack.cpp
@@ -15,6 +15,7 @@
// CMICmdCmdStackListFrames implementation.
// CMICmdCmdStackListArguments implementation.
// CMICmdCmdStackListLocals implementation.
+// CMICmdCmdStackSelectFrame implementation.
//
// Environment: Compilers: Visual C++ 12.
// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1
@@ -825,3 +826,124 @@ CMICmdCmdStackListLocals::CreateSelf(void)
{
return new CMICmdCmdStackListLocals();
}
+
+//---------------------------------------------------------------------------------------
+//---------------------------------------------------------------------------------------
+//---------------------------------------------------------------------------------------
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmdCmdStackSelectFrame constructor.
+// Type: Method.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMICmdCmdStackSelectFrame::CMICmdCmdStackSelectFrame(void)
+ : m_bFrameInvalid(false)
+ , m_constStrArgFrame("frame")
+{
+ // Command factory matches this name with that received from the stdin stream
+ m_strMiCmd = "stack-select-frame";
+
+ // Required by the CMICmdFactory when registering *this command
+ m_pSelfCreatorFn = &CMICmdCmdStackSelectFrame::CreateSelf;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: CMICmdCmdStackSelectFrame destructor.
+// Type: Overrideable.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+CMICmdCmdStackSelectFrame::~CMICmdCmdStackSelectFrame(void)
+{
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: The invoker requires this function. The parses the command line options
+// arguments to extract values for each of those arguments.
+// Type: Overridden.
+// Args: None.
+// Return: MIstatus::success - Function succeeded.
+// MIstatus::failure - Function failed.
+// Throws: None.
+//--
+bool
+CMICmdCmdStackSelectFrame::ParseArgs(void)
+{
+ bool bOk = m_setCmdArgs.Add(*(new CMICmdArgValNumber(m_constStrArgFrame, true, false)));
+ return (bOk && ParseValidateCmdOptions());
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: The invoker requires this function. The command does work in this function.
+// The command is likely to communicate with the LLDB SBDebugger in here.
+// Type: Overridden.
+// Args: None.
+// Return: MIstatus::success - Function succeeded.
+// MIstatus::failure - Function failed.
+// Throws: None.
+//--
+bool
+CMICmdCmdStackSelectFrame::Execute(void)
+{
+ CMICMDBASE_GETOPTION(pArgFrame, Number, m_constStrArgFrame);
+
+ CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance());
+ lldb::SBThread sbThread = rSessionInfo.GetProcess().GetSelectedThread();
+
+ const MIuint nFrameId = pArgFrame->GetValue();
+ m_bFrameInvalid = (nFrameId >= sbThread.GetNumFrames());
+ if (m_bFrameInvalid)
+ return MIstatus::success;
+
+ lldb::SBFrame sbFrame = sbThread.SetSelectedFrame(nFrameId);
+ m_bFrameInvalid = !sbFrame.IsValid();
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: The invoker requires this function. The command prepares a MI Record Result
+// for the work carried out in the Execute().
+// Type: Overridden.
+// Args: None.
+// Return: MIstatus::success - Function succeeded.
+// MIstatus::failure - Function failed.
+// Throws: None.
+//--
+bool
+CMICmdCmdStackSelectFrame::Acknowledge(void)
+{
+ if (m_bFrameInvalid)
+ {
+ // MI print "%s^error,msg=\"Command '-stack-select-frame'. Frame ID invalid\""
+ const CMICmnMIValueConst miValueConst(
+ CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_FRAME_INVALID), m_cmdData.strMiCmd.c_str()));
+ const CMICmnMIValueResult miValueResult("msg", miValueConst);
+ const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, miValueResult);
+ m_miResultRecord = miRecordResult;
+
+ return MIstatus::success;
+ }
+
+ const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done);
+ m_miResultRecord = miRecordResult;
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Required by the CMICmdFactory when registering *this command. The factory
+// calls this function to create an instance of *this command.
+// Type: Static method.
+// Args: None.
+// Return: CMICmdBase * - Pointer to a new command.
+// Throws: None.
+//--
+CMICmdBase *
+CMICmdCmdStackSelectFrame::CreateSelf(void)
+{
+ return new CMICmdCmdStackSelectFrame();
+}
diff --git a/lldb/tools/lldb-mi/MICmdCmdStack.h b/lldb/tools/lldb-mi/MICmdCmdStack.h
index ec90481300e..affe9a53977 100644
--- a/lldb/tools/lldb-mi/MICmdCmdStack.h
+++ b/lldb/tools/lldb-mi/MICmdCmdStack.h
@@ -15,6 +15,7 @@
// CMICmdCmdStackListFrames interface.
// CMICmdCmdStackListArguments interface.
// CMICmdCmdStackListLocals interface.
+// CMICmdCmdStackSelectFrame interface.
//
// To implement new MI commands derive a new command class from the command base
// class. To enable the new command for interpretation add the new command class
@@ -182,6 +183,36 @@ class CMICmdCmdStackListArguments : public CMICmdBase
//++ ============================================================================
// Details: MI command class. MI commands derived from the command base class.
+// *this class implements MI command "stack-select-frame".
+//--
+class CMICmdCmdStackSelectFrame : public CMICmdBase
+{
+ // Statics:
+ public:
+ // Required by the CMICmdFactory when registering *this command
+ static CMICmdBase *CreateSelf(void);
+
+ // Methods:
+ public:
+ /* ctor */ CMICmdCmdStackSelectFrame(void);
+
+ // Overridden:
+ public:
+ // From CMICmdInvoker::ICmd
+ virtual bool Execute(void);
+ virtual bool Acknowledge(void);
+ virtual bool ParseArgs(void);
+ // From CMICmnBase
+ /* dtor */ virtual ~CMICmdCmdStackSelectFrame(void);
+
+ // Attributes:
+ private:
+ bool m_bFrameInvalid; // True = yes invalid frame, false = ok
+ const CMIUtilString m_constStrArgFrame;
+};
+
+//++ ============================================================================
+// Details: MI command class. MI commands derived from the command base class.
// *this class implements MI command "stack-list-locals".
// Gotchas: None.
// Authors: Illya Rudkin 24/03/2014.
diff --git a/lldb/tools/lldb-mi/MICmdCommands.cpp b/lldb/tools/lldb-mi/MICmdCommands.cpp
index e13aa4f8416..b9abfd5068b 100644
--- a/lldb/tools/lldb-mi/MICmdCommands.cpp
+++ b/lldb/tools/lldb-mi/MICmdCommands.cpp
@@ -121,6 +121,7 @@ MICmnCommands::RegisterAll(void)
bOk &= Register<CMICmdCmdStackListFrames>();
bOk &= Register<CMICmdCmdStackListArguments>();
bOk &= Register<CMICmdCmdStackListLocals>();
+ bOk &= Register<CMICmdCmdStackSelectFrame>();
bOk &= Register<CMICmdCmdSupportListFeatures>();
bOk &= Register<CMICmdCmdTargetSelect>();
bOk &= Register<CMICmdCmdThreadInfo>();
OpenPOWER on IntegriCloud