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