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