]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - packages/Python/lldbsuite/test/functionalities/conditional_break/TestConditionalBreak.py
Vendor import of lldb trunk r290819:
[FreeBSD/FreeBSD.git] / packages / Python / lldbsuite / test / functionalities / conditional_break / TestConditionalBreak.py
1 """
2 Test conditionally break on a function and inspect its variables.
3 """
4
5 from __future__ import print_function
6
7
8 import os
9 import time
10 import re
11 import lldb
12 from lldbsuite.test.decorators import *
13 from lldbsuite.test.lldbtest import *
14 from lldbsuite.test import lldbutil
15
16 # rdar://problem/8532131
17 # lldb not able to digest the clang-generated debug info correctly with respect to function name
18 #
19 # This class currently fails for clang as well as llvm-gcc.
20
21
22 class ConditionalBreakTestCase(TestBase):
23
24     mydir = TestBase.compute_mydir(__file__)
25
26     @add_test_categories(['pyapi'])
27     def test_with_python(self):
28         """Exercise some thread and frame APIs to break if c() is called by a()."""
29         self.build()
30         self.do_conditional_break()
31
32     def test_with_command(self):
33         """Simulate a user using lldb commands to break on c() if called from a()."""
34         self.build()
35         self.simulate_conditional_break_by_user()
36
37     @expectedFailureAll(
38         oslist=["windows"],
39         bugnumber="llvm.org/pr26265: args in frames other than #0 are not evaluated correctly")
40     def do_conditional_break(self):
41         """Exercise some thread and frame APIs to break if c() is called by a()."""
42         exe = os.path.join(os.getcwd(), "a.out")
43
44         target = self.dbg.CreateTarget(exe)
45         self.assertTrue(target, VALID_TARGET)
46
47         breakpoint = target.BreakpointCreateByName("c", exe)
48         self.assertTrue(breakpoint, VALID_BREAKPOINT)
49
50         # Now launch the process, and do not stop at entry point.
51         process = target.LaunchSimple(
52             None, None, self.get_process_working_directory())
53
54         self.assertTrue(process, PROCESS_IS_VALID)
55
56         # The stop reason of the thread should be breakpoint.
57         self.assertTrue(process.GetState() == lldb.eStateStopped,
58                         STOPPED_DUE_TO_BREAKPOINT)
59
60         # Find the line number where a's parent frame function is c.
61         line = line_number(
62             'main.c',
63             "// Find the line number where c's parent frame is a here.")
64
65         # Suppose we are only interested in the call scenario where c()'s
66         # immediate caller is a() and we want to find out the value passed from
67         # a().
68         #
69         # The 10 in range(10) is just an arbitrary number, which means we would
70         # like to try for at most 10 times.
71         for j in range(10):
72             if self.TraceOn():
73                 print("j is: ", j)
74             thread = lldbutil.get_one_thread_stopped_at_breakpoint(
75                 process, breakpoint)
76             self.assertIsNotNone(
77                 thread, "Expected one thread to be stopped at the breakpoint")
78
79             if thread.GetNumFrames() >= 2:
80                 frame0 = thread.GetFrameAtIndex(0)
81                 name0 = frame0.GetFunction().GetName()
82                 frame1 = thread.GetFrameAtIndex(1)
83                 name1 = frame1.GetFunction().GetName()
84                 # lldbutil.print_stacktrace(thread)
85                 self.assertTrue(name0 == "c", "Break on function c()")
86                 if (name1 == "a"):
87                     # By design, we know that a() calls c() only from main.c:27.
88                     # In reality, similar logic can be used to find out the call
89                     # site.
90                     self.assertTrue(frame1.GetLineEntry().GetLine() == line,
91                                     "Immediate caller a() at main.c:%d" % line)
92
93                     # And the local variable 'val' should have a value of (int)
94                     # 3.
95                     val = frame1.FindVariable("val")
96                     self.assertEqual("int", val.GetTypeName())
97                     self.assertEqual("3", val.GetValue())
98                     break
99
100             process.Continue()
101
102     def simulate_conditional_break_by_user(self):
103         """Simulate a user using lldb commands to break on c() if called from a()."""
104
105         # Sourcing .lldb in the current working directory, which sets the main
106         # executable, sets the breakpoint on c(), and adds the callback for the
107         # breakpoint such that lldb only stops when the caller of c() is a().
108         # the "my" package that defines the date() function.
109         if self.TraceOn():
110             print("About to source .lldb")
111
112         if not self.TraceOn():
113             self.HideStdout()
114
115         # Separate out the "file a.out" command from .lldb file, for the sake of
116         # remote testsuite.
117         self.runCmd("file a.out")
118         self.runCmd("command source .lldb")
119
120         self.runCmd("break list")
121
122         if self.TraceOn():
123             print("About to run.")
124         self.runCmd("run", RUN_SUCCEEDED)
125
126         self.runCmd("break list")
127
128         if self.TraceOn():
129             print("Done running")
130
131         # The stop reason of the thread should be breakpoint.
132         self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT,
133                     substrs=['stopped', 'stop reason = breakpoint'])
134
135         # The frame info for frame #0 points to a.out`c and its immediate caller
136         # (frame #1) points to a.out`a.
137
138         self.expect("frame info", "We should stop at c()",
139                     substrs=["a.out`c"])
140
141         # Select our parent frame as the current frame.
142         self.runCmd("frame select 1")
143         self.expect("frame info", "The immediate caller should be a()",
144                     substrs=["a.out`a"])