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 lldbutil.check_breakpoint(self, bpno = 1, location_id = 1, expected_location_hit_count = 1) 54 55 # Try some variables that should be visible 56 frame = self.dbg.GetSelectedTarget().GetProcess( 57 ).GetSelectedThread().GetSelectedFrame() 58 if self.is_variable_in_register(frame, 'a'): 59 register_variables_count += 1 60 self.expect("expr a", VARIABLES_DISPLAYED_CORRECTLY, 61 patterns=[re_expr_equals('int', 2)]) 62 63 if self.is_struct_pointer_in_register(frame, 'b', self.TraceOn()): 64 register_variables_count += 1 65 self.expect("expr b->m1", VARIABLES_DISPLAYED_CORRECTLY, 66 patterns=[re_expr_equals('int', 3)]) 67 68 ##################### 69 # Second breakpoint 70 71 self.runCmd("continue") 72 73 # The stop reason of the thread should be breakpoint. 74 self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, 75 substrs=['stopped', 76 'stop reason = breakpoint']) 77 78 # The breakpoint should have a hit count of 1. 79 lldbutil.check_breakpoint(self, bpno = 1, location_id = 2, expected_location_hit_count = 1) 80 81 # Try some variables that should be visible 82 frame = self.dbg.GetSelectedTarget().GetProcess( 83 ).GetSelectedThread().GetSelectedFrame() 84 if self.is_struct_pointer_in_register(frame, 'b', self.TraceOn()): 85 register_variables_count += 1 86 self.expect("expr b->m2", VARIABLES_DISPLAYED_CORRECTLY, 87 patterns=[re_expr_equals('int', 5)]) 88 89 if self.is_variable_in_register(frame, 'c'): 90 register_variables_count += 1 91 self.expect("expr c", VARIABLES_DISPLAYED_CORRECTLY, 92 patterns=[re_expr_equals('int', 5)]) 93 94 ##################### 95 # Third breakpoint 96 97 self.runCmd("continue") 98 99 # The stop reason of the thread should be breakpoint. 100 self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, 101 substrs=['stopped', 102 'stop reason = breakpoint']) 103 104 # The breakpoint should have a hit count of 1. 105 lldbutil.check_breakpoint(self, bpno = 1, location_id = 3, expected_location_hit_count = 1) 106 107 # Try some variables that should be visible 108 frame = self.dbg.GetSelectedTarget().GetProcess( 109 ).GetSelectedThread().GetSelectedFrame() 110 if self.is_variable_in_register(frame, 'f'): 111 register_variables_count += 1 112 self.expect("expr f", VARIABLES_DISPLAYED_CORRECTLY, 113 patterns=[re_expr_equals('float', '3.1')]) 114 115 # Validate that we verified at least one register variable 116 self.assertTrue( 117 register_variables_count > 0, 118 "expected to verify at least one variable in a register") 119 self.trace("executed {} expressions with values in registers".format(register_variables_count)) 120 121 self.runCmd("kill") 122 123 124 def is_variable_in_register(self, frame, var_name): 125 # Ensure we can lookup the variable. 126 var = frame.FindVariable(var_name) 127 self.trace("\nchecking {}...".format(var_name)) 128 if var is None or not var.IsValid(): 129 self.trace("{} cannot be found".format(var_name)) 130 return False 131 132 # Check that we can get its value. If not, this 133 # may be a variable that is just out of scope at this point. 134 value = var.GetValue() 135 self.trace("checking value...") 136 if value is None: 137 self.trace("value is invalid") 138 return False 139 else: 140 self.trace("value is {}".format(value)) 141 142 # We have a variable and we can get its value. The variable is in a 143 # register if we cannot get an address for it, assuming it is not a 144 # struct pointer. (This is an approximation - compilers can do other 145 # things with spitting up a value into multiple parts of multiple 146 # registers, but what we're verifying here is much more than it was 147 # doing before). 148 var_addr = var.GetAddress() 149 self.trace("checking address...") 150 if var_addr.IsValid(): 151 # We have an address, it must not be in a register. 152 self.trace("var {} is not in a register: has a valid address {}".format(var_name, var_addr)) 153 return False 154 else: 155 # We don't have an address but we can read the value. 156 # It is likely stored in a register. 157 self.trace("var {} is in a register (we don't have an address for it)".format(var_name)) 158 return True 159 160 161 def is_struct_pointer_in_register(self, frame, var_name, trace): 162 # Ensure we can lookup the variable. 163 var = frame.FindVariable(var_name) 164 if trace: 165 print("\nchecking {}...".format(var_name)) 166 167 if var is None or not var.IsValid(): 168 self.trace("{} cannot be found".format(var_name)) 169 return False 170 171 # Check that we can get its value. If not, this 172 # may be a variable that is just out of scope at this point. 173 value = var.GetValue() 174 self.trace("checking value...") 175 if value is None: 176 if trace: 177 print("value is invalid") 178 return False 179 else: 180 if trace: 181 print("value is {}".format(value)) 182 183 var_loc = var.GetLocation() 184 if trace: 185 print("checking location: {}".format(var_loc)) 186 if var_loc is None or var_loc.startswith("0x"): 187 # The frame var is not in a register but rather a memory location. 188 self.trace("frame var {} is not in a register".format(var_name)) 189 return False 190 else: 191 self.trace("frame var {} is in a register".format(var_name)) 192 return True 193 194