1""" 2Test the 'register' command. 3""" 4 5import os 6import sys 7import lldb 8from lldbsuite.test.decorators import * 9from lldbsuite.test.lldbtest import * 10from lldbsuite.test import lldbutil 11 12 13class RegisterCommandsTestCase(TestBase): 14 NO_DEBUG_INFO_TESTCASE = True 15 16 def setUp(self): 17 TestBase.setUp(self) 18 self.has_teardown = False 19 20 def tearDown(self): 21 self.dbg.GetSelectedTarget().GetProcess().Destroy() 22 TestBase.tearDown(self) 23 24 # on macOS, detect if the current machine is arm64 and supports SME 25 def get_sme_available(self): 26 if self.getArchitecture() != "arm64": 27 return None 28 try: 29 sysctl_output = subprocess.check_output( 30 ["sysctl", "hw.optional.arm.FEAT_SME"] 31 ).decode("utf-8") 32 except subprocess.CalledProcessError: 33 return None 34 m = re.match(r"hw\.optional\.arm\.FEAT_SME: (\w+)", sysctl_output) 35 if m: 36 if int(m.group(1)) == 1: 37 return True 38 else: 39 return False 40 return None 41 42 @skipIfiOSSimulator 43 @skipIf(archs=no_match(["amd64", "arm", "i386", "x86_64"])) 44 @expectedFailureAll(oslist=["freebsd", "netbsd"], bugnumber="llvm.org/pr48371") 45 def test_register_commands(self): 46 """Test commands related to registers, in particular vector registers.""" 47 self.build() 48 self.common_setup() 49 50 # verify that logging does not assert 51 self.log_enable("registers") 52 53 error_str_matched = False 54 if self.get_sme_available() and self.platformIsDarwin(): 55 # On Darwin AArch64 SME machines, we will have unavailable 56 # registers when not in Streaming SVE Mode/SME, so 57 # `register read -a` will report that some registers 58 # could not be read. This is expected. 59 error_str_matched = True 60 61 if self.getArchitecture() == "x86_64" and self.platformIsDarwin(): 62 # debugserver on x86 will provide ds/es/ss/gsbase when the 63 # kernel provides them, but most of the time they will be 64 # unavailable. So "register read -a" will report that 65 # 4 registers were unavailable, it is expected. 66 error_str_matched = True 67 68 self.expect( 69 "register read -a", 70 MISSING_EXPECTED_REGISTERS, 71 substrs=["registers were unavailable"], 72 matching=error_str_matched, 73 ) 74 75 all_registers = self.res.GetOutput() 76 77 if self.getArchitecture() in ["amd64", "i386", "x86_64"]: 78 self.runCmd("register read xmm0") 79 if "ymm15 = " in all_registers: 80 self.runCmd("register read ymm15") # may be available 81 if "bnd0 = " in all_registers: 82 self.runCmd("register read bnd0") # may be available 83 elif self.getArchitecture() in [ 84 "arm", 85 "armv7", 86 "armv7k", 87 "arm64", 88 "arm64e", 89 "arm64_32", 90 ]: 91 self.runCmd("register read s0") 92 if "q15 = " in all_registers: 93 self.runCmd("register read q15") # may be available 94 95 self.expect( 96 "register read -s 8", substrs=["invalid register set index: 8"], error=True 97 ) 98 99 @skipIfiOSSimulator 100 # Writing of mxcsr register fails, presumably due to a kernel/hardware 101 # problem 102 @skipIfTargetAndroid(archs=["i386"]) 103 @skipIf(archs=no_match(["amd64", "arm", "i386", "x86_64"])) 104 @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr37995") 105 def test_fp_register_write(self): 106 """Test commands that write to registers, in particular floating-point registers.""" 107 self.build() 108 self.fp_register_write() 109 110 @skipIfiOSSimulator 111 # "register read fstat" always return 0xffff 112 @expectedFailureAndroid(archs=["i386"]) 113 @skipIf(archs=no_match(["amd64", "i386", "x86_64"])) 114 @skipIfOutOfTreeDebugserver 115 @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr37995") 116 def test_fp_special_purpose_register_read(self): 117 """Test commands that read fpu special purpose registers.""" 118 self.build() 119 self.fp_special_purpose_register_read() 120 121 @skipIfiOSSimulator 122 @skipIf(archs=no_match(["amd64", "arm", "i386", "x86_64"])) 123 @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr37683") 124 def test_register_expressions(self): 125 """Test expression evaluation with commands related to registers.""" 126 self.build() 127 self.common_setup() 128 129 if self.getArchitecture() in ["amd64", "i386", "x86_64"]: 130 gpr = "eax" 131 vector = "xmm0" 132 elif self.getArchitecture() in ["arm64", "aarch64", "arm64e", "arm64_32"]: 133 gpr = "w0" 134 vector = "v0" 135 elif self.getArchitecture() in ["arm", "armv7", "armv7k"]: 136 gpr = "r0" 137 vector = "q0" 138 139 self.expect("expr/x $%s" % gpr, substrs=["unsigned int", " = 0x"]) 140 self.expect("expr $%s" % vector, substrs=["vector_type"]) 141 self.expect("expr (unsigned int)$%s[0]" % vector, substrs=["unsigned int"]) 142 143 if self.getArchitecture() in ["amd64", "x86_64"]: 144 self.expect("expr -- ($rax & 0xffffffff) == $eax", substrs=["true"]) 145 146 @skipIfiOSSimulator 147 @skipIf(archs=no_match(["amd64", "x86_64"])) 148 @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr37683") 149 def test_convenience_registers(self): 150 """Test convenience registers.""" 151 self.build() 152 self.convenience_registers() 153 154 @skipIfiOSSimulator 155 @skipIf(archs=no_match(["amd64", "x86_64"])) 156 def test_convenience_registers_with_process_attach(self): 157 """Test convenience registers after a 'process attach'.""" 158 self.build() 159 self.convenience_registers_with_process_attach(test_16bit_regs=False) 160 161 @skipIfiOSSimulator 162 @skipIf(archs=no_match(["amd64", "x86_64"])) 163 def test_convenience_registers_16bit_with_process_attach(self): 164 """Test convenience registers after a 'process attach'.""" 165 self.build() 166 self.convenience_registers_with_process_attach(test_16bit_regs=True) 167 168 def common_setup(self): 169 exe = self.getBuildArtifact("a.out") 170 171 self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) 172 173 # Break in main(). 174 lldbutil.run_break_set_by_symbol(self, "main", num_expected_locations=-1) 175 176 self.runCmd("run", RUN_SUCCEEDED) 177 178 # The stop reason of the thread should be breakpoint. 179 self.expect( 180 "thread list", 181 STOPPED_DUE_TO_BREAKPOINT, 182 substrs=["stopped", "stop reason = breakpoint"], 183 ) 184 185 # platform specific logging of the specified category 186 def log_enable(self, category): 187 # This intentionally checks the host platform rather than the target 188 # platform as logging is host side. 189 self.platform = "" 190 if ( 191 sys.platform.startswith("freebsd") 192 or sys.platform.startswith("linux") 193 or sys.platform.startswith("netbsd") 194 ): 195 self.platform = "posix" 196 197 if self.platform != "": 198 self.log_file = self.getBuildArtifact("TestRegisters.log") 199 self.runCmd( 200 "log enable " 201 + self.platform 202 + " " 203 + str(category) 204 + " registers -v -f " 205 + self.log_file, 206 RUN_SUCCEEDED, 207 ) 208 if not self.has_teardown: 209 210 def remove_log(self): 211 if os.path.exists(self.log_file): 212 os.remove(self.log_file) 213 214 self.has_teardown = True 215 self.addTearDownHook(remove_log) 216 217 def write_and_read(self, frame, register, new_value, must_exist=True): 218 value = frame.FindValue(register, lldb.eValueTypeRegister) 219 if must_exist: 220 self.assertTrue(value.IsValid(), "finding a value for register " + register) 221 elif not value.IsValid(): 222 return # If register doesn't exist, skip this test 223 224 # Also test the 're' alias. 225 self.runCmd("re write " + register + " '" + new_value + "'") 226 self.expect("register read " + register, substrs=[register + " = ", new_value]) 227 228 # This test relies on ftag containing the 'abridged' value. Linux 229 # and *BSD targets have been ported to report the full value instead 230 # consistently with GDB. They are covered by the new-style 231 # lldb/test/Shell/Register/x86*-fp-read.test. 232 @skipUnlessDarwin 233 def fp_special_purpose_register_read(self): 234 target = self.createTestTarget() 235 236 # Launch the process and stop. 237 self.expect("run", PROCESS_STOPPED, substrs=["stopped"]) 238 239 # Check stop reason; Should be either signal SIGTRAP or EXC_BREAKPOINT 240 output = self.res.GetOutput() 241 matched = False 242 substrs = ["stop reason = EXC_BREAKPOINT", "stop reason = signal SIGTRAP"] 243 for str1 in substrs: 244 matched = output.find(str1) != -1 245 with recording(self, False) as sbuf: 246 print("%s sub string: %s" % ("Expecting", str1), file=sbuf) 247 print("Matched" if matched else "Not Matched", file=sbuf) 248 if matched: 249 break 250 self.assertTrue(matched, STOPPED_DUE_TO_SIGNAL) 251 252 process = target.GetProcess() 253 self.assertState(process.GetState(), lldb.eStateStopped, PROCESS_STOPPED) 254 255 thread = process.GetThreadAtIndex(0) 256 self.assertTrue(thread.IsValid(), "current thread is valid") 257 258 currentFrame = thread.GetFrameAtIndex(0) 259 self.assertTrue(currentFrame.IsValid(), "current frame is valid") 260 261 # Extract the value of fstat and ftag flag at the point just before 262 # we start pushing floating point values on st% register stack 263 value = currentFrame.FindValue("fstat", lldb.eValueTypeRegister) 264 error = lldb.SBError() 265 reg_value_fstat_initial = value.GetValueAsUnsigned(error, 0) 266 267 self.assertSuccess(error, "reading a value for fstat") 268 value = currentFrame.FindValue("ftag", lldb.eValueTypeRegister) 269 error = lldb.SBError() 270 reg_value_ftag_initial = value.GetValueAsUnsigned(error, 0) 271 272 self.assertSuccess(error, "reading a value for ftag") 273 fstat_top_pointer_initial = (reg_value_fstat_initial & 0x3800) >> 11 274 275 # Execute 'si' aka 'thread step-inst' instruction 5 times and with 276 # every execution verify the value of fstat and ftag registers 277 for x in range(0, 5): 278 # step into the next instruction to push a value on 'st' register 279 # stack 280 self.runCmd("si", RUN_SUCCEEDED) 281 282 # Verify fstat and save it to be used for verification in next 283 # execution of 'si' command 284 if not (reg_value_fstat_initial & 0x3800): 285 self.expect( 286 "register read fstat", 287 substrs=[ 288 "fstat" + " = ", 289 str( 290 "0x%0.4x" % ((reg_value_fstat_initial & ~(0x3800)) | 0x3800) 291 ), 292 ], 293 ) 294 reg_value_fstat_initial = (reg_value_fstat_initial & ~(0x3800)) | 0x3800 295 fstat_top_pointer_initial = 7 296 else: 297 self.expect( 298 "register read fstat", 299 substrs=[ 300 "fstat" + " = ", 301 str("0x%0.4x" % (reg_value_fstat_initial - 0x0800)), 302 ], 303 ) 304 reg_value_fstat_initial = reg_value_fstat_initial - 0x0800 305 fstat_top_pointer_initial -= 1 306 307 # Verify ftag and save it to be used for verification in next 308 # execution of 'si' command 309 self.expect( 310 "register read ftag", 311 substrs=[ 312 "ftag" + " = ", 313 str( 314 "0x%0.4x" 315 % (reg_value_ftag_initial | (1 << fstat_top_pointer_initial)) 316 ), 317 ], 318 ) 319 reg_value_ftag_initial = reg_value_ftag_initial | ( 320 1 << fstat_top_pointer_initial 321 ) 322 323 def fp_register_write(self): 324 target = self.createTestTarget() 325 326 # Launch the process, stop at the entry point. 327 error = lldb.SBError() 328 flags = target.GetLaunchInfo().GetLaunchFlags() 329 process = target.Launch( 330 lldb.SBListener(), 331 None, 332 None, # argv, envp 333 None, 334 None, 335 None, # stdin/out/err 336 self.get_process_working_directory(), 337 flags, # launch flags 338 True, # stop at entry 339 error, 340 ) 341 self.assertSuccess(error, "Launch succeeds") 342 343 self.assertEqual(process.GetState(), lldb.eStateStopped, PROCESS_STOPPED) 344 345 thread = process.GetThreadAtIndex(0) 346 self.assertTrue(thread.IsValid(), "current thread is valid") 347 348 currentFrame = thread.GetFrameAtIndex(0) 349 self.assertTrue(currentFrame.IsValid(), "current frame is valid") 350 351 if self.getArchitecture() in ["amd64", "i386", "x86_64"]: 352 reg_list = [ 353 # reg value must-have 354 ("fcw", "0x0000ff0e", False), 355 ("fsw", "0x0000ff0e", False), 356 ("ftw", "0x0000ff0e", False), 357 ("ip", "0x0000ff0e", False), 358 ("dp", "0x0000ff0e", False), 359 ("mxcsr", "0x0000ff0e", False), 360 ("mxcsrmask", "0x0000ff0e", False), 361 ] 362 363 st0regname = None 364 # Darwin is using stmmN by default but support stN as an alias. 365 # Therefore, we need to check for stmmN first. 366 if currentFrame.FindRegister("stmm0").IsValid(): 367 st0regname = "stmm0" 368 elif currentFrame.FindRegister("st0").IsValid(): 369 st0regname = "st0" 370 if st0regname is not None: 371 # reg value 372 # must-have 373 reg_list.append( 374 ( 375 st0regname, 376 "{0x01 0x02 0x03 0x00 0x00 0x00 0x00 0x00 0x00 0x00}", 377 True, 378 ) 379 ) 380 reg_list.append( 381 ( 382 "xmm0", 383 "{0x01 0x02 0x03 0x00 0x00 0x00 0x00 0x00 0x09 0x0a 0x2f 0x2f 0x2f 0x2f 0x2f 0x2f}", 384 True, 385 ) 386 ) 387 reg_list.append( 388 ( 389 "xmm15", 390 "{0x01 0x02 0x03 0x00 0x00 0x00 0x00 0x00 0x09 0x0a 0x2f 0x2f 0x2f 0x2f 0x0e 0x0f}", 391 False, 392 ) 393 ) 394 elif self.getArchitecture() in ["arm64", "aarch64", "arm64e", "arm64_32"]: 395 reg_list = [ 396 # reg value 397 # must-have 398 ("fpsr", "0xfbf79f9f", True), 399 ("s0", "1.25", True), 400 ("s31", "0.75", True), 401 ("d1", "123", True), 402 ("d17", "987", False), 403 ( 404 "v1", 405 "{0x01 0x02 0x03 0x00 0x00 0x00 0x00 0x00 0x09 0x0a 0x2f 0x2f 0x2f 0x2f 0x2f 0x2f}", 406 True, 407 ), 408 ( 409 "v14", 410 "{0x01 0x02 0x03 0x00 0x00 0x00 0x00 0x00 0x09 0x0a 0x2f 0x2f 0x2f 0x2f 0x0e 0x0f}", 411 False, 412 ), 413 ] 414 elif self.getArchitecture() in ["armv7"] and self.platformIsDarwin(): 415 reg_list = [ 416 # reg value 417 # must-have 418 ("fpsr", "0xfbf79f9f", True), 419 ("s0", "1.25", True), 420 ("s31", "0.75", True), 421 ("d1", "123", True), 422 ("d17", "987", False), 423 ( 424 "q1", 425 "{0x01 0x02 0x03 0x00 0x00 0x00 0x00 0x00 0x09 0x0a 0x2f 0x2f 0x2f 0x2f 0x2f 0x2f}", 426 True, 427 ), 428 ( 429 "q14", 430 "{0x01 0x02 0x03 0x00 0x00 0x00 0x00 0x00 0x09 0x0a 0x2f 0x2f 0x2f 0x2f 0x0e 0x0f}", 431 False, 432 ), 433 ] 434 elif self.getArchitecture() in ["arm", "armv7k"]: 435 reg_list = [ 436 # reg value 437 # must-have 438 ("fpscr", "0xfbf79f9f", True), 439 ("s0", "1.25", True), 440 ("s31", "0.75", True), 441 ("d1", "123", True), 442 ("d17", "987", False), 443 ( 444 "q1", 445 "{0x01 0x02 0x03 0x00 0x00 0x00 0x00 0x00 0x09 0x0a 0x2f 0x2f 0x2f 0x2f 0x2f 0x2f}", 446 True, 447 ), 448 ( 449 "q14", 450 "{0x01 0x02 0x03 0x00 0x00 0x00 0x00 0x00 0x09 0x0a 0x2f 0x2f 0x2f 0x2f 0x0e 0x0f}", 451 False, 452 ), 453 ] 454 455 for reg, val, must in reg_list: 456 self.write_and_read(currentFrame, reg, val, must) 457 458 if self.getArchitecture() in ["amd64", "i386", "x86_64"]: 459 if st0regname is None: 460 self.fail("st0regname could not be determined") 461 self.runCmd( 462 "register write " 463 + st0regname 464 + ' "{0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00}"' 465 ) 466 self.expect( 467 "register read " + st0regname + " --format f", 468 substrs=[st0regname + " = 0"], 469 ) 470 471 # Check if AVX/MPX registers are defined at all. 472 registerSets = currentFrame.GetRegisters() 473 registers = frozenset( 474 reg.GetName() for registerSet in registerSets for reg in registerSet 475 ) 476 has_avx_regs = "ymm0" in registers 477 has_mpx_regs = "bnd0" in registers 478 # Check if they are actually present. 479 self.runCmd("register read -a") 480 output = self.res.GetOutput() 481 has_avx = "ymm0 =" in output 482 has_mpx = "bnd0 =" in output 483 484 if has_avx: 485 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}" 486 self.write_and_read(currentFrame, "ymm0", new_value) 487 self.write_and_read(currentFrame, "ymm7", new_value) 488 self.expect("expr $ymm0", substrs=["vector_type"]) 489 elif has_avx_regs: 490 self.expect("register read ymm0", substrs=["error: unavailable"]) 491 else: 492 self.expect( 493 "register read ymm0", 494 substrs=["Invalid register name 'ymm0'"], 495 error=True, 496 ) 497 498 if has_mpx: 499 # Test write and read for bnd0. 500 new_value_w = "{0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09 0x0a 0x0b 0x0c 0x0d 0x0e 0x0f 0x10}" 501 self.runCmd("register write bnd0 '" + new_value_w + "'") 502 new_value_r = "{0x0807060504030201 0x100f0e0d0c0b0a09}" 503 self.expect("register read bnd0", substrs=["bnd0 = ", new_value_r]) 504 self.expect("expr $bnd0", substrs=["vector_type"]) 505 506 # Test write and for bndstatus. 507 new_value = "{0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08}" 508 self.write_and_read(currentFrame, "bndstatus", new_value) 509 self.expect("expr $bndstatus", substrs=["vector_type"]) 510 elif has_mpx_regs: 511 self.expect("register read bnd0", substrs=["error: unavailable"]) 512 else: 513 self.expect( 514 "register read bnd0", 515 substrs=["Invalid register name 'bnd0'"], 516 error=True, 517 ) 518 519 def convenience_registers(self): 520 """Test convenience registers.""" 521 self.common_setup() 522 523 # The command "register read -a" does output a derived register like 524 # eax... 525 self.expect("register read -a", matching=True, substrs=["eax"]) 526 527 # ...however, the vanilla "register read" command should not output derived registers like eax. 528 self.expect("register read", matching=False, substrs=["eax"]) 529 530 # Test reading of rax and eax. 531 self.expect("register read rax eax", substrs=["rax = 0x", "eax = 0x"]) 532 533 # Now write rax with a unique bit pattern and test that eax indeed 534 # represents the lower half of rax. 535 self.runCmd("register write rax 0x1234567887654321") 536 self.expect("register read rax", substrs=["0x1234567887654321"]) 537 538 def convenience_registers_with_process_attach(self, test_16bit_regs): 539 """Test convenience registers after a 'process attach'.""" 540 exe = self.getBuildArtifact("a.out") 541 542 # Spawn a new process 543 pid = self.spawnSubprocess(exe, ["wait_for_attach"]).pid 544 545 if self.TraceOn(): 546 print("pid of spawned process: %d" % pid) 547 548 self.runCmd("process attach -p %d" % pid) 549 550 # Check that "register read eax" works. 551 self.runCmd("register read eax") 552 553 if self.getArchitecture() in ["amd64", "x86_64"]: 554 self.expect("expr -- ($rax & 0xffffffff) == $eax", substrs=["true"]) 555 556 if test_16bit_regs: 557 self.expect("expr -- $ax == (($ah << 8) | $al)", substrs=["true"]) 558 559 @skipIfiOSSimulator 560 @skipIf(archs=no_match(["amd64", "arm", "i386", "x86_64"])) 561 def test_invalid_invocation(self): 562 self.build() 563 self.common_setup() 564 565 self.expect( 566 "register read -a arg", 567 error=True, 568 substrs=[ 569 "the --all option can't be used when registers names are supplied as arguments" 570 ], 571 ) 572 573 self.expect( 574 "register read --set 0 r", 575 error=True, 576 substrs=[ 577 "the --set <set> option can't be used when registers names are supplied as arguments" 578 ], 579 ) 580 581 self.expect( 582 "register write a", 583 error=True, 584 substrs=["register write takes exactly 2 arguments: <reg-name> <value>"], 585 ) 586 self.expect( 587 "register write a b c", 588 error=True, 589 substrs=["register write takes exactly 2 arguments: <reg-name> <value>"], 590 ) 591 592 @skipIfiOSSimulator 593 @skipIf(archs=no_match(["amd64", "arm", "i386", "x86_64"])) 594 def test_write_unknown_register(self): 595 self.build() 596 self.common_setup() 597 598 self.expect( 599 "register write blub 1", 600 error=True, 601 substrs=["error: Register not found for 'blub'."], 602 ) 603 604 def test_info_unknown_register(self): 605 self.build() 606 self.common_setup() 607 608 self.expect( 609 "register info blub", 610 error=True, 611 substrs=["error: No register found with name 'blub'."], 612 ) 613 614 def test_info_many_registers(self): 615 self.build() 616 self.common_setup() 617 618 # Only 1 register allowed at this time. 619 self.expect( 620 "register info abc def", 621 error=True, 622 substrs=["error: register info takes exactly 1 argument"], 623 ) 624 625 @skipIf(archs=no_match(["aarch64"])) 626 def test_info_register(self): 627 # The behaviour of this command is generic but the specific registers 628 # are not, so this is written for AArch64 only. 629 # Text alignment and ordering are checked in the DumpRegisterInfo and 630 # RegisterFlags unit tests. 631 self.build() 632 self.common_setup() 633 634 # Standard register. Doesn't invalidate anything, doesn't have an alias. 635 self.expect( 636 "register info x1", 637 substrs=[ 638 "Name: x1", 639 "Size: 8 bytes (64 bits)", 640 "In sets: General Purpose Registers", 641 ], 642 ) 643 self.expect( 644 "register info x1", substrs=["Invalidates:", "Name: x1 ("], matching=False 645 ) 646 647 # These registers invalidate others as they are subsets of those registers. 648 self.expect("register info w1", substrs=["Invalidates: x1"]) 649 self.expect("register info s0", substrs=["Invalidates: v0, d0"]) 650 651 # This has an alternative name according to the ABI. 652 self.expect("register info x30", substrs=["Name: lr (x30)"]) 653 654 @skipIfXmlSupportMissing 655 @skipUnlessPlatform(["linux", "freebsd"]) 656 @skipIf(archs=no_match(["aarch64"])) 657 def test_register_read_fields(self): 658 """Test that when debugging a live process, we see the fields of certain 659 registers.""" 660 self.build() 661 self.common_setup() 662 663 # N/Z/C/V bits will always be present, so check only for those. 664 self.expect( 665 "register read cpsr", 666 patterns=["= \(N = [0|1], Z = [0|1], C = [0|1], V = [0|1]"], 667 ) 668 self.expect( 669 "register read fpsr", patterns=["= \(QC = [0|1], IDC = [0|1], IXC = [0|1]"] 670 ) 671 # AHP/DN/FZ always present, others may vary. 672 self.expect( 673 "register read fpcr", patterns=["= \(AHP = [0|1], DN = [0|1], FZ = [0|1]"] 674 ) 675 676 # Should get enumerator descriptions for RMode. 677 self.expect( 678 "register info fpcr", 679 substrs=["RMode: 0 = RN, 1 = RP, 2 = RM, 3 = RZ"], 680 ) 681 682 @skipUnlessPlatform(["linux"]) 683 @skipIf(archs=no_match(["x86_64"])) 684 def test_fs_gs_base(self): 685 """ 686 Tests fs_base register can be read and equals to pthread_self() return value 687 and gs_base register equals zero. 688 """ 689 self.build() 690 target = self.createTestTarget() 691 # Launch the process and stop. 692 self.expect("run", PROCESS_STOPPED, substrs=["stopped"]) 693 694 process = target.GetProcess() 695 696 thread = process.GetThreadAtIndex(0) 697 self.assertTrue(thread.IsValid(), "current thread is valid") 698 699 current_frame = thread.GetFrameAtIndex(0) 700 self.assertTrue(current_frame.IsValid(), "current frame is valid") 701 702 reg_fs_base = current_frame.FindRegister("fs_base") 703 self.assertTrue(reg_fs_base.IsValid(), "fs_base is not available") 704 reg_gs_base = current_frame.FindRegister("gs_base") 705 self.assertTrue(reg_gs_base.IsValid(), "gs_base is not available") 706 self.assertEqual(reg_gs_base.GetValueAsSigned(-1), 0, f"gs_base should be zero") 707 708 # Evaluate pthread_self() and compare against fs_base register read. 709 pthread_self_code = "(uint64_t)pthread_self()" 710 pthread_self_val = current_frame.EvaluateExpression(pthread_self_code) 711 self.assertTrue( 712 pthread_self_val.IsValid(), f"{pthread_self_code} evaluation has failed" 713 ) 714 self.assertNotEqual( 715 reg_fs_base.GetValueAsSigned(-1), -1, f"fs_base returned -1 which is wrong" 716 ) 717 718 self.assertEqual( 719 reg_fs_base.GetValueAsUnsigned(0), 720 pthread_self_val.GetValueAsUnsigned(0), 721 "fs_base does not equal to pthread_self() value.", 722 ) 723 724 def test_process_must_be_stopped(self): 725 """Check that all register commands error when the process is not stopped.""" 726 self.build() 727 exe = self.getBuildArtifact("a.out") 728 pid = self.spawnSubprocess(exe, ["wait_for_attach"]).pid 729 # Async so we can enter commands while the process is running. 730 self.setAsync(True) 731 self.runCmd("process attach --continue -p %d" % pid) 732 733 err_msg = "Command requires a process which is currently stopped." 734 self.expect("register read pc", substrs=[err_msg], error=True) 735 self.expect("register write pc 0", substrs=[err_msg], error=True) 736 self.expect("register info pc", substrs=[err_msg], error=True) 737