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 if currentFrame.FindRegister("st0").IsValid(): 324 st0regname = "st0" 325 elif currentFrame.FindRegister("stmm0").IsValid(): 326 st0regname = "stmm0" 327 if st0regname is not None: 328 # reg value 329 # must-have 330 reg_list.append( 331 (st0regname, "{0x01 0x02 0x03 0x00 0x00 0x00 0x00 0x00 0x00 0x00}", True)) 332 reg_list.append( 333 ("xmm0", 334 "{0x01 0x02 0x03 0x00 0x00 0x00 0x00 0x00 0x09 0x0a 0x2f 0x2f 0x2f 0x2f 0x2f 0x2f}", 335 True)) 336 reg_list.append( 337 ("xmm15", 338 "{0x01 0x02 0x03 0x00 0x00 0x00 0x00 0x00 0x09 0x0a 0x2f 0x2f 0x2f 0x2f 0x0e 0x0f}", 339 False)) 340 elif self.getArchitecture() in ['arm64', 'aarch64', 'arm64e', 'arm64_32']: 341 reg_list = [ 342 # reg value 343 # must-have 344 ("fpsr", "0xfbf79f9f", True), 345 ("s0", "1.25", True), 346 ("s31", "0.75", True), 347 ("d1", "123", True), 348 ("d17", "987", False), 349 ("v1", "{0x01 0x02 0x03 0x00 0x00 0x00 0x00 0x00 0x09 0x0a 0x2f 0x2f 0x2f 0x2f 0x2f 0x2f}", True), 350 ("v14", 351 "{0x01 0x02 0x03 0x00 0x00 0x00 0x00 0x00 0x09 0x0a 0x2f 0x2f 0x2f 0x2f 0x0e 0x0f}", 352 False), 353 ] 354 elif self.getArchitecture() in ['armv7'] and self.platformIsDarwin(): 355 reg_list = [ 356 # reg value 357 # must-have 358 ("fpsr", "0xfbf79f9f", True), 359 ("s0", "1.25", True), 360 ("s31", "0.75", True), 361 ("d1", "123", True), 362 ("d17", "987", False), 363 ("q1", "{0x01 0x02 0x03 0x00 0x00 0x00 0x00 0x00 0x09 0x0a 0x2f 0x2f 0x2f 0x2f 0x2f 0x2f}", True), 364 ("q14", 365 "{0x01 0x02 0x03 0x00 0x00 0x00 0x00 0x00 0x09 0x0a 0x2f 0x2f 0x2f 0x2f 0x0e 0x0f}", 366 False), 367 ] 368 elif self.getArchitecture() in ['arm', 'armv7k']: 369 reg_list = [ 370 # reg value 371 # must-have 372 ("fpscr", "0xfbf79f9f", True), 373 ("s0", "1.25", True), 374 ("s31", "0.75", True), 375 ("d1", "123", True), 376 ("d17", "987", False), 377 ("q1", "{0x01 0x02 0x03 0x00 0x00 0x00 0x00 0x00 0x09 0x0a 0x2f 0x2f 0x2f 0x2f 0x2f 0x2f}", True), 378 ("q14", 379 "{0x01 0x02 0x03 0x00 0x00 0x00 0x00 0x00 0x09 0x0a 0x2f 0x2f 0x2f 0x2f 0x0e 0x0f}", 380 False), 381 ] 382 383 for (reg, val, must) in reg_list: 384 self.write_and_read(currentFrame, reg, val, must) 385 386 if self.getArchitecture() in ['amd64', 'i386', 'x86_64']: 387 if st0regname is None: 388 self.fail("st0regname could not be determined") 389 self.runCmd( 390 "register write " + 391 st0regname + 392 " \"{0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00}\"") 393 self.expect( 394 "register read " + 395 st0regname + 396 " --format f", 397 substrs=[ 398 st0regname + 399 ' = 0']) 400 401 has_avx = False 402 has_mpx = False 403 # Returns an SBValueList. 404 registerSets = currentFrame.GetRegisters() 405 for registerSet in registerSets: 406 if 'advanced vector extensions' in registerSet.GetName().lower(): 407 has_avx = True 408 # FreeBSD/NetBSD reports missing register sets differently 409 # at the moment and triggers false positive here. 410 # TODO: remove FreeBSD/NetBSD exception when we make unsupported 411 # register groups correctly disappear. 412 if ('memory protection extension' in registerSet.GetName().lower() 413 and self.getPlatform() not in ["freebsd", "netbsd"]): 414 has_mpx = True 415 416 if has_avx: 417 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}" 418 self.write_and_read(currentFrame, "ymm0", new_value) 419 self.write_and_read(currentFrame, "ymm7", new_value) 420 self.expect("expr $ymm0", substrs=['vector_type']) 421 else: 422 self.runCmd("register read ymm0") 423 424 if has_mpx: 425 # Test write and read for bnd0. 426 new_value_w = "{0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09 0x0a 0x0b 0x0c 0x0d 0x0e 0x0f 0x10}" 427 self.runCmd("register write bnd0 \'" + new_value_w + "\'") 428 new_value_r = "{0x0807060504030201 0x100f0e0d0c0b0a09}" 429 self.expect("register read bnd0", substrs = ['bnd0 = ', new_value_r]) 430 self.expect("expr $bnd0", substrs = ['vector_type']) 431 432 # Test write and for bndstatus. 433 new_value = "{0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08}" 434 self.write_and_read(currentFrame, "bndstatus", new_value) 435 self.expect("expr $bndstatus", substrs = ['vector_type']) 436 else: 437 self.runCmd("register read bnd0") 438 439 def convenience_registers(self): 440 """Test convenience registers.""" 441 self.common_setup() 442 443 # The command "register read -a" does output a derived register like 444 # eax... 445 self.expect("register read -a", matching=True, 446 substrs=['eax']) 447 448 # ...however, the vanilla "register read" command should not output derived registers like eax. 449 self.expect("register read", matching=False, 450 substrs=['eax']) 451 452 # Test reading of rax and eax. 453 self.expect("register read rax eax", 454 substrs=['rax = 0x', 'eax = 0x']) 455 456 # Now write rax with a unique bit pattern and test that eax indeed 457 # represents the lower half of rax. 458 self.runCmd("register write rax 0x1234567887654321") 459 self.expect("register read rax 0x1234567887654321", 460 substrs=['0x1234567887654321']) 461 462 def convenience_registers_with_process_attach(self, test_16bit_regs): 463 """Test convenience registers after a 'process attach'.""" 464 exe = self.getBuildArtifact("a.out") 465 466 # Spawn a new process 467 pid = self.spawnSubprocess(exe, ['wait_for_attach']).pid 468 469 if self.TraceOn(): 470 print("pid of spawned process: %d" % pid) 471 472 self.runCmd("process attach -p %d" % pid) 473 474 # Check that "register read eax" works. 475 self.runCmd("register read eax") 476 477 if self.getArchitecture() in ['amd64', 'x86_64']: 478 self.expect("expr -- ($rax & 0xffffffff) == $eax", 479 substrs=['true']) 480 481 if test_16bit_regs: 482 self.expect("expr -- $ax == (($ah << 8) | $al)", 483 substrs=['true']) 484 485 @skipIfiOSSimulator 486 @skipIf(archs=no_match(['amd64', 'arm', 'i386', 'x86_64'])) 487 def test_invalid_invocation(self): 488 self.build() 489 self.common_setup() 490 491 self.expect("register read -a arg", error=True, 492 substrs=["the --all option can't be used when registers names are supplied as arguments"]) 493 494 self.expect("register read --set 0 r", error=True, 495 substrs=["the --set <set> option can't be used when registers names are supplied as arguments"]) 496 497 self.expect("register write a", error=True, 498 substrs=["register write takes exactly 2 arguments: <reg-name> <value>"]) 499 self.expect("register write a b c", error=True, 500 substrs=["register write takes exactly 2 arguments: <reg-name> <value>"]) 501 502 @skipIfiOSSimulator 503 @skipIf(archs=no_match(['amd64', 'arm', 'i386', 'x86_64'])) 504 def test_write_unknown_register(self): 505 self.build() 506 self.common_setup() 507 508 self.expect("register write blub 1", error=True, 509 substrs=["error: Register not found for 'blub'."]) 510