There was an error in ORing mask which is used for getting a list of variables.
Previously, these constants were unnamed, and possible it become the reason of this
bug. Also added test case for -stack-list-local and -stack-list_arguments.
Patch from Ilia K <ki.stfu@gmail.com>.
llvm-svn: 223674
--- /dev/null
+"""
+Test that the lldb-mi driver works with -stack-xxx commands
+"""
+
+import os
+import unittest2
+import lldb
+from lldbtest import *
+
+class MiStackTestCase(TestBase):
+
+ mydir = TestBase.compute_mydir(__file__)
+ myexe = "a.out"
+
+ @classmethod
+ def classCleanup(cls):
+ """Cleanup the test byproducts."""
+ try:
+ os.remove("child_send.txt")
+ os.remove("child_read.txt")
+ os.remove(cls.myexe)
+ except:
+ pass
+
+ @lldbmi_test
+ def test_lldbmi_stackargs(self):
+ """Test that 'lldb-mi --interpreter' can shows arguments."""
+ import pexpect
+ self.buildDefault()
+
+ # So that the child gets torn down after the test.
+ self.child = pexpect.spawn('%s --interpreter' % (self.lldbMiExec))
+ child = self.child
+ child.setecho(True)
+ # Turn on logging for input/output to/from the child.
+ with open('child_send.txt', 'w') as f_send:
+ with open('child_read.txt', 'w') as f_read:
+ child.logfile_send = f_send
+ child.logfile_read = f_read
+
+ # Load executable
+ child.sendline("-file-exec-and-symbols %s" % (self.myexe))
+ child.expect("\^done")
+
+ # Run to main
+ child.sendline("-break-insert -f main")
+ child.expect("\^done,bkpt={number=\"1\"")
+ child.sendline("-exec-run")
+ child.expect("\^running")
+ child.expect("\*stopped,reason=\"breakpoint-hit\"")
+
+ # Test arguments
+ child.sendline("-stack-list-arguments 0")
+ child.expect("\^done,stack-args=\[frame={level=\"0\",args=\[{name=\"argc\",value=\"1\"},{name=\"argv\",value=\".*\"}\]}")
+
+ # Now that the necessary logging is done, restore logfile to None to
+ # stop further logging.
+ child.logfile_send = None
+ child.logfile_read = None
+
+ with open('child_send.txt', 'r') as fs:
+ if self.TraceOn():
+ print "\n\nContents of child_send.txt:"
+ print fs.read()
+ with open('child_read.txt', 'r') as fr:
+ from_child = fr.read()
+ if self.TraceOn():
+ print "\n\nContents of child_read.txt:"
+ print from_child
+
+ @lldbmi_test
+ def test_lldbmi_locals(self):
+ """Test that 'lldb-mi --interpreter' can shows local variables."""
+ import pexpect
+ self.buildDefault()
+
+ # So that the child gets torn down after the test.
+ self.child = pexpect.spawn('%s --interpreter' % (self.lldbMiExec))
+ child = self.child
+ child.setecho(True)
+ # Turn on logging for input/output to/from the child.
+ with open('child_send.txt', 'w') as f_send:
+ with open('child_read.txt', 'w') as f_read:
+ child.logfile_send = f_send
+ child.logfile_read = f_read
+
+ # Load executable
+ child.sendline("-file-exec-and-symbols %s" % (self.myexe))
+ child.expect("\^done")
+
+ # Run to main
+ self.line = line_number('main.c', '//BP_localstest')
+ child.sendline("-break-insert --file main.c:%d" % (self.line))
+ child.expect("\^done,bkpt={number=\"1\"")
+ child.sendline("-exec-run")
+ child.expect("\^running")
+ child.expect("\*stopped,reason=\"breakpoint-hit\"")
+
+ # Test locals
+ child.sendline("-stack-list-locals 0")
+ child.expect("\^done,locals=\[{name=\"a\",value=\"10\"},{name=\"b\",value=\"20\"}\]")
+
+ # Now that the necessary logging is done, restore logfile to None to
+ # stop further logging.
+ child.logfile_send = None
+ child.logfile_read = None
+
+ with open('child_send.txt', 'r') as fs:
+ if self.TraceOn():
+ print "\n\nContents of child_send.txt:"
+ print fs.read()
+ with open('child_read.txt', 'r') as fr:
+ from_child = fr.read()
+ if self.TraceOn():
+ print "\n\nContents of child_read.txt:"
+ print from_child
+
+if __name__ == '__main__':
+ import atexit
+ lldb.SBDebugger.Initialize()
+ atexit.register(lambda: lldb.SBDebugger.Terminate())
+ unittest2.main()
printf("argc=%d\n", argc);
a = a_MyFunction();
b = b_MyFunction();
+ //BP_localstest
if (doloop)
infloop();
if (argc > 1 && *argv[1] == 'l') {
{
lldb::SBFrame frame = thread.GetFrameAtIndex(i);
CMICmnMIValueList miValueList(true);
- const MIuint maskVarTypes = 0x1000;
+ const MIuint maskVarTypes = CMICmnLLDBDebugSessionInfo::eVariableType_Arguments;
if (!rSessionInfo.MIResponseFormVariableInfo3(frame, maskVarTypes, miValueList))
return MIstatus::failure;
const CMICmnMIValueConst miValueConst(CMIUtilString::Format("%d", i));
MIunused(nFrames);
lldb::SBFrame frame = (nFrame != UINT64_MAX) ? thread.GetFrameAtIndex(nFrame) : thread.GetSelectedFrame();
CMICmnMIValueList miValueList(true);
- const MIuint maskVarTypes = 0x0110;
+ const MIuint maskVarTypes = CMICmnLLDBDebugSessionInfo::eVariableType_Locals;
if (!rSessionInfo.MIResponseFormVariableInfo(frame, maskVarTypes, miValueList))
return MIstatus::failure;
// Function args
CMICmnMIValueList miValueList(true);
- const MIuint maskVarTypes = 0x1000;
+ const MIuint maskVarTypes = eVariableType_Arguments;
if (!MIResponseFormVariableInfo(frame, maskVarTypes, miValueList))
return MIstatus::failure;
// Function args
CMICmnMIValueList miValueList(true);
- const MIuint maskVarTypes = 0x1000;
+ const MIuint maskVarTypes = eVariableType_Arguments;
if (!MIResponseFormVariableInfo2(frame, maskVarTypes, miValueList))
return MIstatus::failure;
// tuple type object past in.
// Type: Method.
// Args: vrFrame - (R) LLDB thread object.
-// vMaskVarTypes - (R) 0x1000 = arguments,
-// 0x0100 = locals,
-// 0x0010 = statics,
-// 0x0001 = in scope only.
+// vMaskVarTypes - (R) Construed according to VariableType_e.
// vwrMIValueList - (W) MI value list object.
// Return: MIstatus::success - Functional succeeded.
// MIstatus::failure - Functional failed.
bool bOk = MIstatus::success;
lldb::SBFrame &rFrame = const_cast<lldb::SBFrame &>(vrFrame);
- const bool bArg = (vMaskVarTypes & 0x1000);
- const bool bLocals = (vMaskVarTypes & 0x0100);
- const bool bStatics = (vMaskVarTypes & 0x0010);
- const bool bInScopeOnly = (vMaskVarTypes & 0x0001);
+ const bool bArg = (vMaskVarTypes & eVariableType_Arguments);
+ const bool bLocals = (vMaskVarTypes & eVariableType_Locals);
+ const bool bStatics = (vMaskVarTypes & eVariableType_Statics);
+ const bool bInScopeOnly = (vMaskVarTypes & eVariableType_InScope);
lldb::SBValueList listArg = rFrame.GetVariables(bArg, bLocals, bStatics, bInScopeOnly);
const MIuint nArgs = listArg.GetSize();
for (MIuint i = 0; bOk && (i < nArgs); i++)
// tuple type object past in.
// Type: Method.
// Args: vrFrame - (R) LLDB thread object.
-// vMaskVarTypes - (R) 0x1000 = arguments,
-// 0x0100 = locals,
-// 0x0010 = statics,
-// 0x0001 = in scope only.
+// vMaskVarTypes - (R) Construed according to VariableType_e.
// vwrMIValueList - (W) MI value list object.
// Return: MIstatus::success - Functional succeeded.
// MIstatus::failure - Functional failed.
bool bOk = MIstatus::success;
lldb::SBFrame &rFrame = const_cast<lldb::SBFrame &>(vrFrame);
- const bool bArg = (vMaskVarTypes & 0x1000);
- const bool bLocals = (vMaskVarTypes & 0x0100);
- const bool bStatics = (vMaskVarTypes & 0x0010);
- const bool bInScopeOnly = (vMaskVarTypes & 0x0001);
+ const bool bArg = (vMaskVarTypes & eVariableType_Arguments);
+ const bool bLocals = (vMaskVarTypes & eVariableType_Locals);
+ const bool bStatics = (vMaskVarTypes & eVariableType_Statics);
+ const bool bInScopeOnly = (vMaskVarTypes & eVariableType_InScope);
const MIuint nMaxRecusiveDepth = 10;
MIuint nCurrentRecursiveDepth = 0;
lldb::SBValueList listArg = rFrame.GetVariables(bArg, bLocals, bStatics, bInScopeOnly);
// tuple type object past in.
// Type: Method.
// Args: vrFrame - (R) LLDB thread object.
-// vMaskVarTypes - (R) 0x1000 = arguments,
-// 0x0100 = locals,
-// 0x0010 = statics,
-// 0x0001 = in scope only.
+// vMaskVarTypes - (R) Construed according to VariableType_e.
// vwrMIValueList - (W) MI value list object.
// Return: MIstatus::success - Functional succeeded.
// MIstatus::failure - Functional failed.
bool bOk = MIstatus::success;
lldb::SBFrame &rFrame = const_cast<lldb::SBFrame &>(vrFrame);
- const bool bArg = (vMaskVarTypes & 0x1000);
- const bool bLocals = (vMaskVarTypes & 0x0100);
- const bool bStatics = (vMaskVarTypes & 0x0010);
- const bool bInScopeOnly = (vMaskVarTypes & 0x0001);
+ const bool bArg = (vMaskVarTypes & eVariableType_Arguments);
+ const bool bLocals = (vMaskVarTypes & eVariableType_Locals);
+ const bool bStatics = (vMaskVarTypes & eVariableType_Statics);
+ const bool bInScopeOnly = (vMaskVarTypes & eVariableType_InScope);
const MIuint nMaxRecusiveDepth = 10;
MIuint nCurrentRecursiveDepth = 0;
lldb::SBValueList listArg = rFrame.GetVariables(bArg, bLocals, bStatics, bInScopeOnly);
MIuint m_nBrkPtThreadId; // Restrict the breakpoint to the specified thread-id
};
+ // Enumerations:
+ public:
+ //++ ===================================================================
+ // Details: The type of variable used by MIResponseFormVariableInfo family functions.
+ //--
+ enum VariableType_e
+ {
+ eVariableType_InScope = (1u << 0), // In scope only.
+ eVariableType_Statics = (1u << 1), // Statics.
+ eVariableType_Locals = (1u << 2), // Locals.
+ eVariableType_Arguments = (1u << 3) // Arguments.
+ };
+
// Typedefs:
public:
typedef std::vector<uint32_t> VecActiveThreadId_t;
if (bOk)
{
CMICmnMIValueList miValueList(true);
- const MIuint maskVarTypes = 0x1000;
+ const MIuint maskVarTypes = CMICmnLLDBDebugSessionInfo::eVariableType_Arguments;
bOk = rSession.MIResponseFormVariableInfo2(frame, maskVarTypes, miValueList);
CMICmnMIValueTuple miValueTuple;
// Function args
CMICmnMIValueList miValueList(true);
- const MIuint maskVarTypes = 0x1000;
+ const MIuint maskVarTypes = CMICmnLLDBDebugSessionInfo::eVariableType_Arguments;
if (!rSession.MIResponseFormVariableInfo2(frame, maskVarTypes, miValueList))
return MIstatus::failure;
CMICmnMIValueTuple miValueTuple;