2 Test the 'register' command.
5 from __future__ import print_function
11 from lldbsuite.test.decorators import *
12 from lldbsuite.test.lldbtest import *
13 from lldbsuite.test import lldbutil
16 class RegisterCommandsTestCase(TestBase):
18 mydir = TestBase.compute_mydir(__file__)
19 NO_DEBUG_INFO_TESTCASE = True
23 self.has_teardown = False
26 self.dbg.GetSelectedTarget().GetProcess().Destroy()
27 TestBase.tearDown(self)
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."""
37 # verify that logging does not assert
38 self.log_enable("registers")
40 self.expect("register read -a", MISSING_EXPECTED_REGISTERS,
41 substrs=['registers were unavailable'], matching=False)
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
53 substrs=['invalid register set index: 4'],
57 # Writing of mxcsr register fails, presumably due to a kernel/hardware
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."""
65 self.fp_register_write()
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."""
78 self.fp_special_purpose_register_read()
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."""
88 if self.getArchitecture() in ['amd64', 'i386', 'x86_64']:
91 elif self.getArchitecture() in ['arm64', 'aarch64', 'arm64e', 'arm64_32']:
94 elif self.getArchitecture() in ['arm', 'armv7', 'armv7k']:
98 self.expect("expr/x $%s" % gpr, substrs=['unsigned int', ' = 0x'])
99 self.expect("expr $%s" % vector, substrs=['vector_type'])
101 "expr (unsigned int)$%s[0]" %
102 vector, substrs=['unsigned int'])
104 if self.getArchitecture() in ['amd64', 'x86_64']:
106 "expr -- ($rax & 0xffffffff) == $eax",
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."""
115 self.convenience_registers()
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'."""
124 self.convenience_registers_with_process_attach(test_16bit_regs=False)
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'."""
133 self.convenience_registers_with_process_attach(test_16bit_regs=True)
135 def common_setup(self):
136 exe = self.getBuildArtifact("a.out")
138 self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET)
141 lldbutil.run_break_set_by_symbol(
142 self, "main", num_expected_locations=-1)
144 self.runCmd("run", RUN_SUCCEEDED)
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'])
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.
155 if (sys.platform.startswith("freebsd") or
156 sys.platform.startswith("linux") or
157 sys.platform.startswith("netbsd")):
158 self.platform = "posix"
160 if self.platform != "":
161 self.log_file = self.getBuildArtifact('TestRegisters.log')
167 " registers -v -f " +
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)
177 def write_and_read(self, frame, register, new_value, must_exist=True):
178 value = frame.FindValue(register, lldb.eValueTypeRegister)
182 "finding a value for register " +
184 elif not value.IsValid():
185 return # If register doesn't exist, skip this test
187 # Also test the 're' alias.
188 self.runCmd("re write " + register + " \'" + new_value + "\'")
197 def fp_special_purpose_register_read(self):
198 exe = self.getBuildArtifact("a.out")
200 # Create a target by the debugger.
201 target = self.dbg.CreateTarget(exe)
202 self.assertTrue(target, VALID_TARGET)
204 # Launch the process and stop.
205 self.expect("run", PROCESS_STOPPED, substrs=['stopped'])
207 # Check stop reason; Should be either signal SIGTRAP or EXC_BREAKPOINT
208 output = self.res.GetOutput()
211 'stop reason = EXC_BREAKPOINT',
212 'stop reason = signal SIGTRAP']
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)
220 self.assertTrue(matched, STOPPED_DUE_TO_SIGNAL)
222 process = target.GetProcess()
223 self.assertTrue(process.GetState() == lldb.eStateStopped,
226 thread = process.GetThreadAtIndex(0)
227 self.assertTrue(thread.IsValid(), "current thread is valid")
229 currentFrame = thread.GetFrameAtIndex(0)
230 self.assertTrue(currentFrame.IsValid(), "current frame is valid")
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)
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)
243 self.assertTrue(error.Success(), "reading a value for ftag")
244 fstat_top_pointer_initial = (reg_value_fstat_initial & 0x3800) >> 11
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
251 self.runCmd("si", RUN_SUCCEEDED)
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
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
267 # Verify ftag and save it to be used for verification in next
268 # execution of 'si' command
270 "register read ftag", substrs=[
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)
278 def fp_register_write(self):
279 exe = self.getBuildArtifact("a.out")
281 # Create a target by the debugger.
282 target = self.dbg.CreateTarget(exe)
283 self.assertTrue(target, VALID_TARGET)
285 # Launch the process, stop at the entry point.
286 error = lldb.SBError()
287 process = target.Launch(
289 None, None, # argv, envp
290 None, None, None, # stdin/out/err
291 self.get_process_working_directory(),
293 True, # stop at entry
295 self.assertTrue(error.Success(), "Launch succeeds. Error is :" + str(error))
298 process.GetState() == lldb.eStateStopped,
301 thread = process.GetThreadAtIndex(0)
302 self.assertTrue(thread.IsValid(), "current thread is valid")
304 currentFrame = thread.GetFrameAtIndex(0)
305 self.assertTrue(currentFrame.IsValid(), "current frame is valid")
307 if self.getArchitecture() in ['amd64', 'i386', 'x86_64']:
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),
320 if currentFrame.FindRegister("st0").IsValid():
322 elif currentFrame.FindRegister("stmm0").IsValid():
324 if st0regname is not None:
328 (st0regname, "{0x01 0x02 0x03 0x00 0x00 0x00 0x00 0x00 0x00 0x00}", True))
331 "{0x01 0x02 0x03 0x00 0x00 0x00 0x00 0x00 0x09 0x0a 0x2f 0x2f 0x2f 0x2f 0x2f 0x2f}",
335 "{0x01 0x02 0x03 0x00 0x00 0x00 0x00 0x00 0x09 0x0a 0x2f 0x2f 0x2f 0x2f 0x0e 0x0f}",
337 elif self.getArchitecture() in ['arm64', 'aarch64', 'arm64e', 'arm64_32']:
341 ("fpsr", "0xfbf79f9f", True),
342 ("s0", "1.25", True),
343 ("s31", "0.75", True),
345 ("d17", "987", False),
346 ("v1", "{0x01 0x02 0x03 0x00 0x00 0x00 0x00 0x00 0x09 0x0a 0x2f 0x2f 0x2f 0x2f 0x2f 0x2f}", True),
348 "{0x01 0x02 0x03 0x00 0x00 0x00 0x00 0x00 0x09 0x0a 0x2f 0x2f 0x2f 0x2f 0x0e 0x0f}",
351 elif self.getArchitecture() in ['armv7'] and self.platformIsDarwin():
355 ("fpsr", "0xfbf79f9f", True),
356 ("s0", "1.25", True),
357 ("s31", "0.75", True),
359 ("d17", "987", False),
360 ("q1", "{0x01 0x02 0x03 0x00 0x00 0x00 0x00 0x00 0x09 0x0a 0x2f 0x2f 0x2f 0x2f 0x2f 0x2f}", True),
362 "{0x01 0x02 0x03 0x00 0x00 0x00 0x00 0x00 0x09 0x0a 0x2f 0x2f 0x2f 0x2f 0x0e 0x0f}",
365 elif self.getArchitecture() in ['arm', 'armv7k']:
369 ("fpscr", "0xfbf79f9f", True),
370 ("s0", "1.25", True),
371 ("s31", "0.75", True),
373 ("d17", "987", False),
374 ("q1", "{0x01 0x02 0x03 0x00 0x00 0x00 0x00 0x00 0x09 0x0a 0x2f 0x2f 0x2f 0x2f 0x2f 0x2f}", True),
376 "{0x01 0x02 0x03 0x00 0x00 0x00 0x00 0x00 0x09 0x0a 0x2f 0x2f 0x2f 0x2f 0x0e 0x0f}",
380 for (reg, val, must) in reg_list:
381 self.write_and_read(currentFrame, reg, val, must)
383 if self.getArchitecture() in ['amd64', 'i386', 'x86_64']:
384 if st0regname is None:
385 self.fail("st0regname could not be determined")
389 " \"{0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00}\"")
400 # Returns an SBValueList.
401 registerSets = currentFrame.GetRegisters()
402 for registerSet in registerSets:
403 if 'advanced vector extensions' in registerSet.GetName().lower():
405 if 'memory protection extension' in registerSet.GetName().lower():
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'])
414 self.runCmd("register read ymm0")
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'])
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'])
429 self.runCmd("register read bnd0")
431 def convenience_registers(self):
432 """Test convenience registers."""
435 # The command "register read -a" does output a derived register like
437 self.expect("register read -a", matching=True,
440 # ...however, the vanilla "register read" command should not output derived registers like eax.
441 self.expect("register read", matching=False,
444 # Test reading of rax and eax.
445 self.expect("register read rax eax",
446 substrs=['rax = 0x', 'eax = 0x'])
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'])
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")
458 # Spawn a new process
459 pid = self.spawnSubprocess(exe, ['wait_for_attach']).pid
460 self.addTearDownHook(self.cleanupSubprocesses)
463 print("pid of spawned process: %d" % pid)
465 self.runCmd("process attach -p %d" % pid)
467 # Check that "register read eax" works.
468 self.runCmd("register read eax")
470 if self.getArchitecture() in ['amd64', 'x86_64']:
471 self.expect("expr -- ($rax & 0xffffffff) == $eax",
475 self.expect("expr -- $ax == (($ah << 8) | $al)",
479 @skipIf(archs=no_match(['amd64', 'arm', 'i386', 'x86_64']))
480 def test_invalid_invocation(self):
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"])
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"])
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>"])
496 @skipIf(archs=no_match(['amd64', 'arm', 'i386', 'x86_64']))
497 def test_write_unknown_register(self):
501 self.expect("register write blub 1", error=True,
502 substrs=["error: Register not found for 'blub'."])