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