1 """Check that compiler-generated register values work correctly"""
3 from __future__ import print_function
8 from lldbsuite.test.decorators import *
9 from lldbsuite.test.lldbtest import *
10 from lldbsuite.test import lldbutil
12 # This method attempts to figure out if a given variable
16 # True if the value has a readable value and is in a register
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))
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...")
31 # print("value is invalid")
34 # print("value is {}".format(value))
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))
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))
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))
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...")
68 # print("value is invalid")
71 # print("value is {}".format(value))
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))
80 # print("frame var {} is in a register".format(var_name))
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))
89 class RegisterVariableTestCase(TestBase):
91 mydir = TestBase.compute_mydir(__file__)
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."""
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
104 register_variables_count = 0
107 exe = os.path.join(os.getcwd(), "a.out")
108 self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET)
110 # Break inside the main.
111 lldbutil.run_break_set_by_source_regexp(self, "break", num_expected_locations=3)
116 self.runCmd("run", RUN_SUCCEEDED)
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'])
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'])
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)])
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)])
139 #####################
142 self.runCmd("continue")
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'])
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'])
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)])
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)])
165 #####################
168 self.runCmd("continue")
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'])
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'])
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')])
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))