]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - packages/Python/lldbsuite/test/lang/c/register_variables/TestRegisterVariables.py
Vendor import of lldb release_39 branch r276489:
[FreeBSD/FreeBSD.git] / packages / Python / lldbsuite / test / lang / c / register_variables / TestRegisterVariables.py
1 """Check that compiler-generated register values work correctly"""
2
3 from __future__ import print_function
4
5 import os, time
6 import re
7 import lldb
8 from lldbsuite.test.decorators import *
9 from lldbsuite.test.lldbtest import *
10 from lldbsuite.test import lldbutil
11
12 # This method attempts to figure out if a given variable
13 # is in a register.
14 #
15 # Return:
16 #   True if the value has a readable value and is in a register
17 #   False otherwise
18 def is_variable_in_register(frame, var_name):
19     # Ensure we can lookup the variable.
20     var = frame.FindVariable(var_name)
21     # print("\nchecking {}...".format(var_name))
22     if var is None or not var.IsValid():
23         # print("{} cannot be found".format(var_name))
24         return False
25
26     # Check that we can get its value.  If not, this
27     # may be a variable that is just out of scope at this point.
28     value = var.GetValue()
29     # print("checking value...")
30     if value is None:
31         # print("value is invalid")
32         return False
33     # else:
34         # print("value is {}".format(value))
35
36     # We have a variable and we can get its value.  The variable is in
37     # a register if we cannot get an address for it, assuming it is
38     # not a struct pointer.  (This is an approximation - compilers can
39     # do other things with spitting up a value into multiple parts of
40     # multiple registers, but what we're verifying here is much more
41     # than it was doing before).
42     var_addr = var.GetAddress()
43     # print("checking address...")
44     if var_addr.IsValid():
45         # We have an address, it must not be in a register.
46         # print("var {} is not in a register: has a valid address {}".format(var_name, var_addr))
47         return False
48     else:
49         # We don't have an address but we can read the value.
50         # It is likely stored in a register.
51         # print("var {} is in a register (we don't have an address for it)".format(var_name))
52         return True
53
54
55 def is_struct_pointer_in_register(frame, var_name):
56     # Ensure we can lookup the variable.
57     var = frame.FindVariable(var_name)
58     # print("\nchecking {}...".format(var_name))
59     if var is None or not var.IsValid():
60         # print("{} cannot be found".format(var_name))
61         return False
62
63     # Check that we can get its value.  If not, this
64     # may be a variable that is just out of scope at this point.
65     value = var.GetValue()
66     # print("checking value...")
67     if value is None:
68         # print("value is invalid")
69         return False
70     # else:
71     #     print("value is {}".format(value))
72
73     var_loc = var.GetLocation()
74     # print("checking location: {}".format(var_loc))
75     if var_loc is None or var_loc.startswith("0x"):
76         # The frame var is not in a register but rather a memory location.
77         # print("frame var {} is not in a register".format(var_name))
78         return False
79     else:
80         # print("frame var {} is in a register".format(var_name))
81         return True
82
83
84 def re_expr_equals(val_type, val):
85     # Match ({val_type}) ${sum_digits} = {val}
86     return re.compile(r'\(' + val_type + '\) \$\d+ = ' + str(val))
87
88
89 class RegisterVariableTestCase(TestBase):
90
91     mydir = TestBase.compute_mydir(__file__)
92
93
94     @expectedFailureAll(compiler="clang", compiler_version=['<', '3.5'])
95     @expectedFailureAll(compiler="gcc", compiler_version=['>=', '4.8.2'], archs=["i386", "x86_64"])
96     def test_and_run_command(self):
97         """Test expressions on register values."""
98
99         # This test now ensures that each probable
100         # register variable location is actually a register, and
101         # if so, whether we can print out the variable there.
102         # It only requires one of them to be handled in a non-error
103         # way.
104         register_variables_count = 0
105
106         self.build()
107         exe = os.path.join(os.getcwd(), "a.out")
108         self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET)
109
110         # Break inside the main.
111         lldbutil.run_break_set_by_source_regexp(self, "break", num_expected_locations=3)
112
113         ####################
114         # First breakpoint
115
116         self.runCmd("run", RUN_SUCCEEDED)
117
118         # The stop reason of the thread should be breakpoint.
119         self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT,
120             substrs = ['stopped',
121                        'stop reason = breakpoint'])
122
123         # The breakpoint should have a hit count of 1.
124         self.expect("breakpoint list -f", BREAKPOINT_HIT_ONCE,
125             substrs = [' resolved, hit count = 1'])
126
127         # Try some variables that should be visible
128         frame = self.dbg.GetSelectedTarget().GetProcess().GetSelectedThread().GetSelectedFrame()
129         if is_variable_in_register(frame, 'a'):
130             register_variables_count += 1
131             self.expect("expr a", VARIABLES_DISPLAYED_CORRECTLY,
132                 patterns = [re_expr_equals('int', 2)])
133
134         if is_struct_pointer_in_register(frame, 'b'):
135             register_variables_count += 1
136             self.expect("expr b->m1", VARIABLES_DISPLAYED_CORRECTLY,
137                 patterns = [re_expr_equals('int', 3)])
138
139         #####################
140         # Second breakpoint
141
142         self.runCmd("continue")
143
144         # The stop reason of the thread should be breakpoint.
145         self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT,
146             substrs = ['stopped',
147                        'stop reason = breakpoint'])
148
149         # The breakpoint should have a hit count of 1.
150         self.expect("breakpoint list -f", BREAKPOINT_HIT_ONCE,
151             substrs = [' resolved, hit count = 1'])
152
153         # Try some variables that should be visible
154         frame = self.dbg.GetSelectedTarget().GetProcess().GetSelectedThread().GetSelectedFrame()
155         if is_struct_pointer_in_register(frame, 'b'):
156             register_variables_count += 1
157             self.expect("expr b->m2", VARIABLES_DISPLAYED_CORRECTLY,
158                 patterns = [re_expr_equals('int', 5)])
159
160         if is_variable_in_register(frame, 'c'):
161             register_variables_count += 1
162             self.expect("expr c", VARIABLES_DISPLAYED_CORRECTLY,
163                 patterns = [re_expr_equals('int', 5)])
164
165         #####################
166         # Third breakpoint
167
168         self.runCmd("continue")
169
170         # The stop reason of the thread should be breakpoint.
171         self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT,
172             substrs = ['stopped',
173                        'stop reason = breakpoint'])
174
175         # The breakpoint should have a hit count of 1.
176         self.expect("breakpoint list -f", BREAKPOINT_HIT_ONCE,
177             substrs = [' resolved, hit count = 1'])
178
179         # Try some variables that should be visible
180         frame = self.dbg.GetSelectedTarget().GetProcess().GetSelectedThread().GetSelectedFrame()
181         if is_variable_in_register(frame, 'f'):
182             register_variables_count += 1
183             self.expect("expr f", VARIABLES_DISPLAYED_CORRECTLY,
184                 patterns = [re_expr_equals('float', '3.1')])
185
186         # Validate that we verified at least one register variable
187         self.assertTrue(register_variables_count > 0, "expected to verify at least one variable in a register")
188         # print("executed {} expressions with values in registers".format(register_variables_count))
189
190         self.runCmd("kill")