1""" 2Test the 'register' command. 3""" 4 5from __future__ import print_function 6 7 8import os 9import sys 10import lldb 11from lldbsuite.test.decorators import * 12from lldbsuite.test.lldbtest import * 13from lldbsuite.test import lldbutil 14 15 16class RegisterCommandsTestCase(TestBase): 17 18 mydir = TestBase.compute_mydir(__file__) 19 NO_DEBUG_INFO_TESTCASE = True 20 21 def setUp(self): 22 TestBase.setUp(self) 23 self.has_teardown = False 24 25 def tearDown(self): 26 self.dbg.GetSelectedTarget().GetProcess().Destroy() 27 TestBase.tearDown(self) 28 29 @skipIfiOSSimulator 30 @skipIf(archs=no_match(['amd64', 'arm', 'i386', 'x86_64'])) 31 @expectedFailureNetBSD 32 def test_register_commands(self): 33 """Test commands related to registers, in particular vector registers.""" 34 self.build() 35 self.common_setup() 36 37 # verify that logging does not assert 38 self.log_enable("registers") 39 40 self.expect("register read -a", MISSING_EXPECTED_REGISTERS, 41 substrs=['registers were unavailable'], matching=False) 42 43 if self.getArchitecture() in ['amd64', 'i386', 'x86_64']: 44 self.runCmd("register read xmm0") 45 self.runCmd("register read ymm15") # may be available 46 self.runCmd("register read bnd0") # may be available 47 elif self.getArchitecture() in ['arm', 'armv7', 'armv7k', 'arm64', 'arm64e', 'arm64_32']: 48 self.runCmd("register read s0") 49 self.runCmd("register read q15") # may be available 50 51 self.expect( 52 "register read -s 4", 53 substrs=['invalid register set index: 4'], 54 error=True) 55 56 @skipIfiOSSimulator 57 # Writing of mxcsr register fails, presumably due to a kernel/hardware 58 # problem 59 @skipIfTargetAndroid(archs=["i386"]) 60 @skipIf(archs=no_match(['amd64', 'arm', 'i386', 'x86_64'])) 61 @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr37995") 62 def test_fp_register_write(self): 63 """Test commands that write to registers, in particular floating-point registers.""" 64 self.build() 65 self.fp_register_write() 66 67 @skipIfiOSSimulator 68 # "register read fstat" always return 0xffff 69 @expectedFailureAndroid(archs=["i386"]) 70 @skipIfFreeBSD # llvm.org/pr25057 71 @skipIf(archs=no_match(['amd64', 'i386', 'x86_64'])) 72 @skipIfOutOfTreeDebugserver 73 @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr37995") 74 @expectedFailureNetBSD 75 def test_fp_special_purpose_register_read(self): 76 """Test commands that read fpu special purpose registers.""" 77 self.build() 78 self.fp_special_purpose_register_read() 79 80 @skipIfiOSSimulator 81 @skipIf(archs=no_match(['amd64', 'arm', 'i386', 'x86_64'])) 82 @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr37683") 83 def test_register_expressions(self): 84 """Test expression evaluation with commands related to registers.""" 85 self.build() 86 self.common_setup() 87 88 if self.getArchitecture() in ['amd64', 'i386', 'x86_64']: 89 gpr = "eax" 90 vector = "xmm0" 91 elif self.getArchitecture() in ['arm64', 'aarch64', 'arm64e', 'arm64_32']: 92 gpr = "w0" 93 vector = "v0" 94 elif self.getArchitecture() in ['arm', 'armv7', 'armv7k']: 95 gpr = "r0" 96 vector = "q0" 97 98 self.expect("expr/x $%s" % gpr, substrs=['unsigned int', ' = 0x']) 99 self.expect("expr $%s" % vector, substrs=['vector_type']) 100 self.expect( 101 "expr (unsigned int)$%s[0]" % 102 vector, substrs=['unsigned int']) 103 104 if self.getArchitecture() in ['amd64', 'x86_64']: 105 self.expect( 106 "expr -- ($rax & 0xffffffff) == $eax", 107 substrs=['true']) 108 109 @skipIfiOSSimulator 110 @skipIf(archs=no_match(['amd64', 'x86_64'])) 111 @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr37683") 112 def test_convenience_registers(self): 113 """Test convenience registers.""" 114 self.build() 115 self.convenience_registers() 116 117 @skipIfiOSSimulator 118 @skipIf(archs=no_match(['amd64', 'x86_64'])) 119 @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr37683") 120 @expectedFailureNetBSD 121 def test_convenience_registers_with_process_attach(self): 122 """Test convenience registers after a 'process attach'.""" 123 self.build() 124 self.convenience_registers_with_process_attach(test_16bit_regs=False) 125 126 @skipIfiOSSimulator 127 @skipIf(archs=no_match(['amd64', 'x86_64'])) 128 @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr37683") 129 @expectedFailureNetBSD 130 def test_convenience_registers_16bit_with_process_attach(self): 131 """Test convenience registers after a 'process attach'.""" 132 self.build() 133 self.convenience_registers_with_process_attach(test_16bit_regs=True) 134 135 def common_setup(self): 136 exe = self.getBuildArtifact("a.out") 137 138 self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) 139 140 # Break in main(). 141 lldbutil.run_break_set_by_symbol( 142 self, "main", num_expected_locations=-1) 143 144 self.runCmd("run", RUN_SUCCEEDED) 145 146 # The stop reason of the thread should be breakpoint. 147 self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, 148 substrs=['stopped', 'stop reason = breakpoint']) 149 150 # platform specific logging of the specified category 151 def log_enable(self, category): 152 # This intentionally checks the host platform rather than the target 153 # platform as logging is host side. 154 self.platform = "" 155 if (sys.platform.startswith("freebsd") or 156 sys.platform.startswith("linux") or 157 sys.platform.startswith("netbsd")): 158 self.platform = "posix" 159 160 if self.platform != "": 161 self.log_file = self.getBuildArtifact('TestRegisters.log') 162 self.runCmd( 163 "log enable " + 164 self.platform + 165 " " + 166 str(category) + 167 " registers -v -f " + 168 self.log_file, 169 RUN_SUCCEEDED) 170 if not self.has_teardown: 171 def remove_log(self): 172 if os.path.exists(self.log_file): 173 os.remove(self.log_file) 174 self.has_teardown = True 175 self.addTearDownHook(remove_log) 176 177 def write_and_read(self, frame, register, new_value, must_exist=True): 178 value = frame.FindValue(register, lldb.eValueTypeRegister) 179 if must_exist: 180 self.assertTrue( 181 value.IsValid(), 182 "finding a value for register " + 183 register) 184 elif not value.IsValid(): 185 return # If register doesn't exist, skip this test 186 187 # Also test the 're' alias. 188 self.runCmd("re write " + register + " \'" + new_value + "\'") 189 self.expect( 190 "register read " + 191 register, 192 substrs=[ 193 register + 194 ' = ', 195 new_value]) 196 197 def fp_special_purpose_register_read(self): 198 exe = self.getBuildArtifact("a.out") 199 200 # Create a target by the debugger. 201 target = self.dbg.CreateTarget(exe) 202 self.assertTrue(target, VALID_TARGET) 203 204 # Launch the process and stop. 205 self.expect("run", PROCESS_STOPPED, substrs=['stopped']) 206 207 # Check stop reason; Should be either signal SIGTRAP or EXC_BREAKPOINT 208 output = self.res.GetOutput() 209 matched = False 210 substrs = [ 211 'stop reason = EXC_BREAKPOINT', 212 'stop reason = signal SIGTRAP'] 213 for str1 in substrs: 214 matched = output.find(str1) != -1 215 with recording(self, False) as sbuf: 216 print("%s sub string: %s" % ('Expecting', str1), file=sbuf) 217 print("Matched" if matched else "Not Matched", file=sbuf) 218 if matched: 219 break 220 self.assertTrue(matched, STOPPED_DUE_TO_SIGNAL) 221 222 process = target.GetProcess() 223 self.assertTrue(process.GetState() == lldb.eStateStopped, 224 PROCESS_STOPPED) 225 226 thread = process.GetThreadAtIndex(0) 227 self.assertTrue(thread.IsValid(), "current thread is valid") 228 229 currentFrame = thread.GetFrameAtIndex(0) 230 self.assertTrue(currentFrame.IsValid(), "current frame is valid") 231 232 # Extract the value of fstat and ftag flag at the point just before 233 # we start pushing floating point values on st% register stack 234 value = currentFrame.FindValue("fstat", lldb.eValueTypeRegister) 235 error = lldb.SBError() 236 reg_value_fstat_initial = value.GetValueAsUnsigned(error, 0) 237 238 self.assertTrue(error.Success(), "reading a value for fstat") 239 value = currentFrame.FindValue("ftag", lldb.eValueTypeRegister) 240 error = lldb.SBError() 241 reg_value_ftag_initial = value.GetValueAsUnsigned(error, 0) 242 243 self.assertTrue(error.Success(), "reading a value for ftag") 244 fstat_top_pointer_initial = (reg_value_fstat_initial & 0x3800) >> 11 245 246 # Execute 'si' aka 'thread step-inst' instruction 5 times and with 247 # every execution verify the value of fstat and ftag registers 248 for x in range(0, 5): 249 # step into the next instruction to push a value on 'st' register 250 # stack 251 self.runCmd("si", RUN_SUCCEEDED) 252 253 # Verify fstat and save it to be used for verification in next 254 # execution of 'si' command 255 if not (reg_value_fstat_initial & 0x3800): 256 self.expect("register read fstat", substrs=[ 257 'fstat' + ' = ', str("0x%0.4x" % ((reg_value_fstat_initial & ~(0x3800)) | 0x3800))]) 258 reg_value_fstat_initial = ( 259 (reg_value_fstat_initial & ~(0x3800)) | 0x3800) 260 fstat_top_pointer_initial = 7 261 else: 262 self.expect("register read fstat", substrs=[ 263 'fstat' + ' = ', str("0x%0.4x" % (reg_value_fstat_initial - 0x0800))]) 264 reg_value_fstat_initial = (reg_value_fstat_initial - 0x0800) 265 fstat_top_pointer_initial -= 1 266 267 # Verify ftag and save it to be used for verification in next 268 # execution of 'si' command 269 self.expect( 270 "register read ftag", substrs=[ 271 'ftag' + ' = ', str( 272 "0x%0.4x" % 273 (reg_value_ftag_initial | ( 274 1 << fstat_top_pointer_initial)))]) 275 reg_value_ftag_initial = reg_value_ftag_initial | ( 276 1 << fstat_top_pointer_initial) 277 278 def fp_register_write(self): 279 exe = self.getBuildArtifact("a.out") 280 281 # Create a target by the debugger. 282 target = self.dbg.CreateTarget(exe) 283 self.assertTrue(target, VALID_TARGET) 284 285 # Launch the process, stop at the entry point. 286 error = lldb.SBError() 287 process = target.Launch( 288 lldb.SBListener(), 289 None, None, # argv, envp 290 None, None, None, # stdin/out/err 291 self.get_process_working_directory(), 292 0, # launch flags 293 True, # stop at entry 294 error) 295 self.assertTrue(error.Success(), "Launch succeeds. Error is :" + str(error)) 296 297 self.assertTrue( 298 process.GetState() == lldb.eStateStopped, 299 PROCESS_STOPPED) 300 301 thread = process.GetThreadAtIndex(0) 302 self.assertTrue(thread.IsValid(), "current thread is valid") 303 304 currentFrame = thread.GetFrameAtIndex(0) 305 self.assertTrue(currentFrame.IsValid(), "current frame is valid") 306 307 if self.getArchitecture() in ['amd64', 'i386', 'x86_64']: 308 reg_list = [ 309 # reg value must-have 310 ("fcw", "0x0000ff0e", False), 311 ("fsw", "0x0000ff0e", False), 312 ("ftw", "0x0000ff0e", False), 313 ("ip", "0x0000ff0e", False), 314 ("dp", "0x0000ff0e", False), 315 ("mxcsr", "0x0000ff0e", False), 316 ("mxcsrmask", "0x0000ff0e", False), 317 ] 318 319 st0regname = None 320 if currentFrame.FindRegister("st0").IsValid(): 321 st0regname = "st0" 322 elif currentFrame.FindRegister("stmm0").IsValid(): 323 st0regname = "stmm0" 324 if st0regname is not None: 325 # reg value 326 # must-have 327 reg_list.append( 328 (st0regname, "{0x01 0x02 0x03 0x00 0x00 0x00 0x00 0x00 0x00 0x00}", True)) 329 reg_list.append( 330 ("xmm0", 331 "{0x01 0x02 0x03 0x00 0x00 0x00 0x00 0x00 0x09 0x0a 0x2f 0x2f 0x2f 0x2f 0x2f 0x2f}", 332 True)) 333 reg_list.append( 334 ("xmm15", 335 "{0x01 0x02 0x03 0x00 0x00 0x00 0x00 0x00 0x09 0x0a 0x2f 0x2f 0x2f 0x2f 0x0e 0x0f}", 336 False)) 337 elif self.getArchitecture() in ['arm64', 'aarch64', 'arm64e', 'arm64_32']: 338 reg_list = [ 339 # reg value 340 # must-have 341 ("fpsr", "0xfbf79f9f", True), 342 ("s0", "1.25", True), 343 ("s31", "0.75", True), 344 ("d1", "123", True), 345 ("d17", "987", False), 346 ("v1", "{0x01 0x02 0x03 0x00 0x00 0x00 0x00 0x00 0x09 0x0a 0x2f 0x2f 0x2f 0x2f 0x2f 0x2f}", True), 347 ("v14", 348 "{0x01 0x02 0x03 0x00 0x00 0x00 0x00 0x00 0x09 0x0a 0x2f 0x2f 0x2f 0x2f 0x0e 0x0f}", 349 False), 350 ] 351 elif self.getArchitecture() in ['armv7'] and self.platformIsDarwin(): 352 reg_list = [ 353 # reg value 354 # must-have 355 ("fpsr", "0xfbf79f9f", True), 356 ("s0", "1.25", True), 357 ("s31", "0.75", True), 358 ("d1", "123", True), 359 ("d17", "987", False), 360 ("q1", "{0x01 0x02 0x03 0x00 0x00 0x00 0x00 0x00 0x09 0x0a 0x2f 0x2f 0x2f 0x2f 0x2f 0x2f}", True), 361 ("q14", 362 "{0x01 0x02 0x03 0x00 0x00 0x00 0x00 0x00 0x09 0x0a 0x2f 0x2f 0x2f 0x2f 0x0e 0x0f}", 363 False), 364 ] 365 elif self.getArchitecture() in ['arm', 'armv7k']: 366 reg_list = [ 367 # reg value 368 # must-have 369 ("fpscr", "0xfbf79f9f", True), 370 ("s0", "1.25", True), 371 ("s31", "0.75", True), 372 ("d1", "123", True), 373 ("d17", "987", False), 374 ("q1", "{0x01 0x02 0x03 0x00 0x00 0x00 0x00 0x00 0x09 0x0a 0x2f 0x2f 0x2f 0x2f 0x2f 0x2f}", True), 375 ("q14", 376 "{0x01 0x02 0x03 0x00 0x00 0x00 0x00 0x00 0x09 0x0a 0x2f 0x2f 0x2f 0x2f 0x0e 0x0f}", 377 False), 378 ] 379 380 for (reg, val, must) in reg_list: 381 self.write_and_read(currentFrame, reg, val, must) 382 383 if self.getArchitecture() in ['amd64', 'i386', 'x86_64']: 384 if st0regname is None: 385 self.fail("st0regname could not be determined") 386 self.runCmd( 387 "register write " + 388 st0regname + 389 " \"{0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00}\"") 390 self.expect( 391 "register read " + 392 st0regname + 393 " --format f", 394 substrs=[ 395 st0regname + 396 ' = 0']) 397 398 has_avx = False 399 has_mpx = False 400 # Returns an SBValueList. 401 registerSets = currentFrame.GetRegisters() 402 for registerSet in registerSets: 403 if 'advanced vector extensions' in registerSet.GetName().lower(): 404 has_avx = True 405 if 'memory protection extension' in registerSet.GetName().lower(): 406 has_mpx = True 407 408 if has_avx: 409 new_value = "{0x01 0x02 0x03 0x00 0x00 0x00 0x00 0x00 0x09 0x0a 0x2f 0x2f 0x2f 0x2f 0x0e 0x0f 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x0c 0x0d 0x0e 0x0f}" 410 self.write_and_read(currentFrame, "ymm0", new_value) 411 self.write_and_read(currentFrame, "ymm7", new_value) 412 self.expect("expr $ymm0", substrs=['vector_type']) 413 else: 414 self.runCmd("register read ymm0") 415 416 if has_mpx: 417 # Test write and read for bnd0. 418 new_value_w = "{0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09 0x0a 0x0b 0x0c 0x0d 0x0e 0x0f 0x10}" 419 self.runCmd("register write bnd0 \'" + new_value_w + "\'") 420 new_value_r = "{0x0807060504030201 0x100f0e0d0c0b0a09}" 421 self.expect("register read bnd0", substrs = ['bnd0 = ', new_value_r]) 422 self.expect("expr $bnd0", substrs = ['vector_type']) 423 424 # Test write and for bndstatus. 425 new_value = "{0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08}" 426 self.write_and_read(currentFrame, "bndstatus", new_value) 427 self.expect("expr $bndstatus", substrs = ['vector_type']) 428 else: 429 self.runCmd("register read bnd0") 430 431 def convenience_registers(self): 432 """Test convenience registers.""" 433 self.common_setup() 434 435 # The command "register read -a" does output a derived register like 436 # eax... 437 self.expect("register read -a", matching=True, 438 substrs=['eax']) 439 440 # ...however, the vanilla "register read" command should not output derived registers like eax. 441 self.expect("register read", matching=False, 442 substrs=['eax']) 443 444 # Test reading of rax and eax. 445 self.expect("register read rax eax", 446 substrs=['rax = 0x', 'eax = 0x']) 447 448 # Now write rax with a unique bit pattern and test that eax indeed 449 # represents the lower half of rax. 450 self.runCmd("register write rax 0x1234567887654321") 451 self.expect("register read rax 0x1234567887654321", 452 substrs=['0x1234567887654321']) 453 454 def convenience_registers_with_process_attach(self, test_16bit_regs): 455 """Test convenience registers after a 'process attach'.""" 456 exe = self.getBuildArtifact("a.out") 457 458 # Spawn a new process 459 pid = self.spawnSubprocess(exe, ['wait_for_attach']).pid 460 self.addTearDownHook(self.cleanupSubprocesses) 461 462 if self.TraceOn(): 463 print("pid of spawned process: %d" % pid) 464 465 self.runCmd("process attach -p %d" % pid) 466 467 # Check that "register read eax" works. 468 self.runCmd("register read eax") 469 470 if self.getArchitecture() in ['amd64', 'x86_64']: 471 self.expect("expr -- ($rax & 0xffffffff) == $eax", 472 substrs=['true']) 473 474 if test_16bit_regs: 475 self.expect("expr -- $ax == (($ah << 8) | $al)", 476 substrs=['true']) 477 478 @skipIfiOSSimulator 479 @skipIf(archs=no_match(['amd64', 'arm', 'i386', 'x86_64'])) 480 def test_invalid_invocation(self): 481 self.build() 482 self.common_setup() 483 484 self.expect("register read -a arg", error=True, 485 substrs=["the --all option can't be used when registers names are supplied as arguments"]) 486 487 self.expect("register read --set 0 r", error=True, 488 substrs=["the --set <set> option can't be used when registers names are supplied as arguments"]) 489 490 self.expect("register write a", error=True, 491 substrs=["register write takes exactly 2 arguments: <reg-name> <value>"]) 492 self.expect("register write a b c", error=True, 493 substrs=["register write takes exactly 2 arguments: <reg-name> <value>"]) 494 495 @skipIfiOSSimulator 496 @skipIf(archs=no_match(['amd64', 'arm', 'i386', 'x86_64'])) 497 def test_write_unknown_register(self): 498 self.build() 499 self.common_setup() 500 501 self.expect("register write blub 1", error=True, 502 substrs=["error: Register not found for 'blub'."]) 503