summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lldb/test/lldbtest.py6
-rw-r--r--lldb/test/python_api/frame/Makefile5
-rw-r--r--lldb/test/python_api/frame/TestFrames.py118
-rw-r--r--lldb/test/python_api/frame/main.c58
4 files changed, 185 insertions, 2 deletions
diff --git a/lldb/test/lldbtest.py b/lldb/test/lldbtest.py
index 764b6ca78aa..72bdfe9d8e2 100644
--- a/lldb/test/lldbtest.py
+++ b/lldb/test/lldbtest.py
@@ -133,6 +133,10 @@ PROCESS_IS_VALID = "Process is valid"
PROCESS_KILLED = "Process is killed successfully"
+PROCESS_EXITED = "Process exited successfully"
+
+PROCESS_STOPPED = "Process status should be stopped"
+
RUN_SUCCEEDED = "Process is launched successfully"
RUN_COMPLETED = "Process exited successfully"
@@ -155,8 +159,6 @@ SOURCE_DISPLAYED_CORRECTLY = "Source code displayed correctly"
STEP_OUT_SUCCEEDED = "Thread step-out succeeded"
-PROCESS_STOPPED = "Process status should be stopped"
-
STOPPED_DUE_TO_BREAKPOINT = "Process should be stopped due to breakpoint"
STOPPED_DUE_TO_BREAKPOINT_WITH_STOP_REASON_AS = "%s, %s" % (
diff --git a/lldb/test/python_api/frame/Makefile b/lldb/test/python_api/frame/Makefile
new file mode 100644
index 00000000000..0d70f259501
--- /dev/null
+++ b/lldb/test/python_api/frame/Makefile
@@ -0,0 +1,5 @@
+LEVEL = ../../make
+
+C_SOURCES := main.c
+
+include $(LEVEL)/Makefile.rules
diff --git a/lldb/test/python_api/frame/TestFrames.py b/lldb/test/python_api/frame/TestFrames.py
new file mode 100644
index 00000000000..f8b80e629d9
--- /dev/null
+++ b/lldb/test/python_api/frame/TestFrames.py
@@ -0,0 +1,118 @@
+"""
+Use lldb Python SBFrame API to get the argument values of the call stacks.
+"""
+
+import os, time
+import re
+import unittest2
+import lldb, lldbutil
+from lldbtest import *
+
+class FrameAPITestCase(TestBase):
+
+ mydir = os.path.join("python_api", "frame")
+
+ @unittest2.expectedFailure
+ @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin")
+ @python_api_test
+ def test_get_arg_vals_for_call_stack_with_dsym(self):
+ """Exercise SBFrame.GetVariables() API to get argument vals."""
+ self.buildDsym()
+ self.do_get_arg_vals()
+
+ @unittest2.expectedFailure
+ @python_api_test
+ def test_get_arg_vals_for_call_stack_with_dwarf(self):
+ """Exercise SBFrame.GetVariables() API to get argument vals."""
+ self.buildDwarf()
+ self.do_get_arg_vals()
+
+ def do_get_arg_vals(self):
+ """Get argument vals for the call stack when stopped on a breakpoint."""
+ exe = os.path.join(os.getcwd(), "a.out")
+
+ # Create a target by the debugger.
+ target = self.dbg.CreateTarget(exe)
+ self.assertTrue(target.IsValid(), VALID_TARGET)
+
+ # Now create a breakpoint on main.c by name 'c'.
+ breakpoint = target.BreakpointCreateByName('c', 'a.out')
+ #print "breakpoint:", breakpoint
+ self.assertTrue(breakpoint.IsValid() and
+ breakpoint.GetNumLocations() == 1,
+ VALID_BREAKPOINT)
+
+ # Now launch the process, and do not stop at the entry point.
+ # Note that we don't assign the process to self.process as in other test
+ # cases. We want the inferior to run till it exits and there's no need
+ # for the testing framework to kill the inferior upon tearDown().
+ process = target.LaunchProcess([], [], os.ctermid(), 0, False)
+
+ process = target.GetProcess()
+ self.assertTrue(process.GetState() == lldb.eStateStopped,
+ PROCESS_STOPPED)
+
+ # Keeps track of the number of times 'a' is called where it is within a
+ # depth of 3 of the 'c' leaf function.
+ callsOfA = 0
+
+ import StringIO
+ session = StringIO.StringIO()
+ while process.GetState() == lldb.eStateStopped:
+ thread = process.GetThreadAtIndex(0)
+ # Inspect at most 3 frames.
+ numFrames = min(3, thread.GetNumFrames())
+ for i in range(numFrames):
+ frame = thread.GetFrameAtIndex(i)
+ print "frame:", frame
+ #print "frame.FindValue('val', lldb.eValueTypeVariableArgument)", frame.FindValue('val', lldb.eValueTypeVariableArgument).GetValue(frame)
+ #print "frame.FindValue('ch', lldb.eValueTypeVariableArgument)", frame.FindValue('ch', lldb.eValueTypeVariableArgument).GetValue(frame)
+ #print "frame.EvaluateExpression('val'):", frame.EvaluateExpression('val').GetValue(frame)
+ #print "frame.EvaluateExpression('ch'):", frame.EvaluateExpression('ch').GetValue(frame)
+ name = frame.GetFunction().GetName()
+ if name == 'a':
+ callsOfA = callsOfA + 1
+
+ # We'll inspect only the arguments for the current frame:
+ #
+ # arguments => True
+ # locals => False
+ # statics => False
+ # in_scope_only => True
+ valList = frame.GetVariables(True, False, False, True)
+ argList = []
+ from lldbutil import lldb_iter
+ for val in lldb_iter(valList, 'GetSize', 'GetValueAtIndex'):
+ #self.DebugSBValue(frame, val)
+ argList.append("(%s)%s=%s" % (val.GetTypeName(),
+ val.GetName(),
+ val.GetValue(frame)))
+ print >> session, "%s(%s)" % (name, ", ".join(argList))
+
+ print >> session, "---"
+ process.Continue()
+
+ # At this point, the inferior process should have exited.
+ self.assertTrue(process.GetState() == lldb.eStateExited, PROCESS_EXITED)
+
+ # Expect to find 'a' on the call stacks two times.
+ self.assertTrue(callsOfA == 2,
+ "Expect to find 'a' on the call stacks two times")
+ # By design, the 'a' call frame has the following arg vals:
+ # o a((int)val=1, (char)ch='A')
+ # o a((int)val=3, (char)ch='A')
+ print "Full stack traces when stopped on the breakpoint 'c':"
+ print session.getvalue()
+ # rdar://problem/8801262
+ # test failure: ./dotest.py -v -w -t -p TestFrames (argument values are wrong)
+ self.expect(session.getvalue(), "Argugment values displayed correctly",
+ exe=False,
+ substrs = ["a((int)val=1, (char)ch='A')",
+ "a((int)val=3, (char)ch='A')"])
+
+
+if __name__ == '__main__':
+ import atexit
+ lldb.SBDebugger.Initialize()
+ atexit.register(lambda: lldb.SBDebugger.Terminate())
+ unittest2.main()
diff --git a/lldb/test/python_api/frame/main.c b/lldb/test/python_api/frame/main.c
new file mode 100644
index 00000000000..749bd615bb9
--- /dev/null
+++ b/lldb/test/python_api/frame/main.c
@@ -0,0 +1,58 @@
+//===-- main.c --------------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include <stdio.h>
+
+// This simple program is to test the lldb Python API related to frames.
+
+int a(int, char);
+int b(int, char);
+int c(int, char);
+
+int a(int val, char ch)
+{
+ int my_val = val;
+ char my_ch = ch;
+ printf("a(val=%d, ch='%c')\n", val, ch);
+ if (val <= 1)
+ return b(++val, ++ch);
+ else if (val >= 3)
+ return c(++val, ++ch);
+
+ return val;
+}
+
+int b(int val, char ch)
+{
+ int my_val = val;
+ char my_ch = ch;
+ printf("b(val=%d, ch='%c')\n", val, ch);
+ return c(++val, ++ch);
+}
+
+int c(int val, char ch)
+{
+ int my_val = val;
+ char my_ch = ch;
+ printf("c(val=%d, ch='%c')\n", val, ch);
+ return val + 3 + ch;
+}
+
+int main (int argc, char const *argv[])
+{
+ int A1 = a(1, 'A'); // a(1, 'A') -> b(2, 'B') -> c(3, 'C')
+ printf("a(1, 'A') returns %d\n", A1);
+
+ int B2 = b(2, 'B'); // b(2, 'B') -> c(3, 'C')
+ printf("b(2, 'B') returns %d\n", B2);
+
+ int A3 = a(3, 'A'); // a(3, 'A') -> c(4, 'B')
+ printf("a(3, 'A') returns %d\n", A3);
+
+ return 0;
+}
OpenPOWER on IntegriCloud