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