2 Test the 'register' command.
5 from __future__ import print_function
13 from lldbsuite.test.decorators import *
14 from lldbsuite.test.lldbtest import *
15 from lldbsuite.test import lldbutil
18 class RegisterCommandsTestCase(TestBase):
20 mydir = TestBase.compute_mydir(__file__)
24 self.has_teardown = False
27 self.dbg.GetSelectedTarget().GetProcess().Destroy()
28 TestBase.tearDown(self)
31 @skipIf(archs=no_match(['amd64', 'arm', 'i386', 'x86_64']))
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']:
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 def test_fp_register_write(self):
62 """Test commands that write to registers, in particular floating-point registers."""
64 self.fp_register_write()
67 # "register read fstat" always return 0xffff
68 @expectedFailureAndroid(archs=["i386"])
69 @skipIfFreeBSD # llvm.org/pr25057
70 @skipIf(archs=no_match(['amd64', 'i386', 'x86_64']))
71 def test_fp_special_purpose_register_read(self):
72 """Test commands that read fpu special purpose registers."""
74 self.fp_special_purpose_register_read()
77 @skipIf(archs=no_match(['amd64', 'arm', 'i386', 'x86_64']))
78 def test_register_expressions(self):
79 """Test expression evaluation with commands related to registers."""
83 if self.getArchitecture() in ['amd64', 'i386', 'x86_64']:
86 elif self.getArchitecture() in ['arm']:
90 self.expect("expr/x $%s" % gpr, substrs=['unsigned int', ' = 0x'])
91 self.expect("expr $%s" % vector, substrs=['vector_type'])
93 "expr (unsigned int)$%s[0]" %
94 vector, substrs=['unsigned int'])
96 if self.getArchitecture() in ['amd64', 'x86_64']:
98 "expr -- ($rax & 0xffffffff) == $eax",
102 @skipIf(archs=no_match(['amd64', 'x86_64']))
103 def test_convenience_registers(self):
104 """Test convenience registers."""
106 self.convenience_registers()
109 @skipIf(archs=no_match(['amd64', 'x86_64']))
110 def test_convenience_registers_with_process_attach(self):
111 """Test convenience registers after a 'process attach'."""
113 self.convenience_registers_with_process_attach(test_16bit_regs=False)
116 @skipIf(archs=no_match(['amd64', 'x86_64']))
117 def test_convenience_registers_16bit_with_process_attach(self):
118 """Test convenience registers after a 'process attach'."""
120 self.convenience_registers_with_process_attach(test_16bit_regs=True)
122 def common_setup(self):
123 exe = os.path.join(os.getcwd(), "a.out")
125 self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET)
128 lldbutil.run_break_set_by_symbol(
129 self, "main", num_expected_locations=-1)
131 self.runCmd("run", RUN_SUCCEEDED)
133 # The stop reason of the thread should be breakpoint.
134 self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT,
135 substrs=['stopped', 'stop reason = breakpoint'])
137 # platform specific logging of the specified category
138 def log_enable(self, category):
139 # This intentionally checks the host platform rather than the target
140 # platform as logging is host side.
142 if sys.platform.startswith("darwin"):
143 self.platform = "" # TODO: add support for "log enable darwin registers"
145 if sys.platform.startswith("freebsd"):
146 self.platform = "freebsd"
148 if sys.platform.startswith("linux"):
149 self.platform = "linux"
151 if sys.platform.startswith("netbsd"):
152 self.platform = "netbsd"
154 if self.platform != "":
155 self.log_file = os.path.join(os.getcwd(), 'TestRegisters.log')
161 " registers -v -f " +
164 if not self.has_teardown:
165 def remove_log(self):
166 if os.path.exists(self.log_file):
167 os.remove(self.log_file)
168 self.has_teardown = True
169 self.addTearDownHook(remove_log)
171 def write_and_read(self, frame, register, new_value, must_exist=True):
172 value = frame.FindValue(register, lldb.eValueTypeRegister)
176 "finding a value for register " +
178 elif not value.IsValid():
179 return # If register doesn't exist, skip this test
181 self.runCmd("register write " + register + " \'" + new_value + "\'")
190 def fp_special_purpose_register_read(self):
191 exe = os.path.join(os.getcwd(), "a.out")
193 # Create a target by the debugger.
194 target = self.dbg.CreateTarget(exe)
195 self.assertTrue(target, VALID_TARGET)
197 # Launch the process and stop.
198 self.expect("run", PROCESS_STOPPED, substrs=['stopped'])
200 # Check stop reason; Should be either signal SIGTRAP or EXC_BREAKPOINT
201 output = self.res.GetOutput()
204 'stop reason = EXC_BREAKPOINT',
205 'stop reason = signal SIGTRAP']
207 matched = output.find(str1) != -1
208 with recording(self, False) as sbuf:
209 print("%s sub string: %s" % ('Expecting', str1), file=sbuf)
210 print("Matched" if matched else "Not Matched", file=sbuf)
213 self.assertTrue(matched, STOPPED_DUE_TO_SIGNAL)
215 process = target.GetProcess()
216 self.assertTrue(process.GetState() == lldb.eStateStopped,
219 thread = process.GetThreadAtIndex(0)
220 self.assertTrue(thread.IsValid(), "current thread is valid")
222 currentFrame = thread.GetFrameAtIndex(0)
223 self.assertTrue(currentFrame.IsValid(), "current frame is valid")
225 # Extract the value of fstat and ftag flag at the point just before
226 # we start pushing floating point values on st% register stack
227 value = currentFrame.FindValue("fstat", lldb.eValueTypeRegister)
228 error = lldb.SBError()
229 reg_value_fstat_initial = value.GetValueAsUnsigned(error, 0)
231 self.assertTrue(error.Success(), "reading a value for fstat")
232 value = currentFrame.FindValue("ftag", lldb.eValueTypeRegister)
233 error = lldb.SBError()
234 reg_value_ftag_initial = value.GetValueAsUnsigned(error, 0)
236 self.assertTrue(error.Success(), "reading a value for ftag")
237 fstat_top_pointer_initial = (reg_value_fstat_initial & 0x3800) >> 11
239 # Execute 'si' aka 'thread step-inst' instruction 5 times and with
240 # every execution verify the value of fstat and ftag registers
241 for x in range(0, 5):
242 # step into the next instruction to push a value on 'st' register
244 self.runCmd("si", RUN_SUCCEEDED)
246 # Verify fstat and save it to be used for verification in next
247 # execution of 'si' command
248 if not (reg_value_fstat_initial & 0x3800):
249 self.expect("register read fstat", substrs=[
250 'fstat' + ' = ', str("0x%0.4x" % ((reg_value_fstat_initial & ~(0x3800)) | 0x3800))])
251 reg_value_fstat_initial = (
252 (reg_value_fstat_initial & ~(0x3800)) | 0x3800)
253 fstat_top_pointer_initial = 7
255 self.expect("register read fstat", substrs=[
256 'fstat' + ' = ', str("0x%0.4x" % (reg_value_fstat_initial - 0x0800))])
257 reg_value_fstat_initial = (reg_value_fstat_initial - 0x0800)
258 fstat_top_pointer_initial -= 1
260 # Verify ftag and save it to be used for verification in next
261 # execution of 'si' command
263 "register read ftag", substrs=[
266 (reg_value_ftag_initial | (
267 1 << fstat_top_pointer_initial)))])
268 reg_value_ftag_initial = reg_value_ftag_initial | (
269 1 << fstat_top_pointer_initial)
271 def fp_register_write(self):
272 exe = os.path.join(os.getcwd(), "a.out")
274 # Create a target by the debugger.
275 target = self.dbg.CreateTarget(exe)
276 self.assertTrue(target, VALID_TARGET)
278 lldbutil.run_break_set_by_symbol(
279 self, "main", num_expected_locations=-1)
281 # Launch the process, and do not stop at the entry point.
282 process = target.LaunchSimple(
283 None, None, self.get_process_working_directory())
285 process = target.GetProcess()
287 process.GetState() == lldb.eStateStopped,
290 thread = process.GetThreadAtIndex(0)
291 self.assertTrue(thread.IsValid(), "current thread is valid")
293 currentFrame = thread.GetFrameAtIndex(0)
294 self.assertTrue(currentFrame.IsValid(), "current frame is valid")
296 if self.getArchitecture() in ['amd64', 'i386', 'x86_64']:
298 # reg value must-have
299 ("fcw", "0x0000ff0e", False),
300 ("fsw", "0x0000ff0e", False),
301 ("ftw", "0x0000ff0e", False),
302 ("ip", "0x0000ff0e", False),
303 ("dp", "0x0000ff0e", False),
304 ("mxcsr", "0x0000ff0e", False),
305 ("mxcsrmask", "0x0000ff0e", False),
309 if currentFrame.FindRegister("st0").IsValid():
311 elif currentFrame.FindRegister("stmm0").IsValid():
313 if st0regname is not None:
317 (st0regname, "{0x01 0x02 0x03 0x00 0x00 0x00 0x00 0x00 0x00 0x00}", True))
320 "{0x01 0x02 0x03 0x00 0x00 0x00 0x00 0x00 0x09 0x0a 0x2f 0x2f 0x2f 0x2f 0x2f 0x2f}",
324 "{0x01 0x02 0x03 0x00 0x00 0x00 0x00 0x00 0x09 0x0a 0x2f 0x2f 0x2f 0x2f 0x0e 0x0f}",
326 elif self.getArchitecture() in ['arm']:
330 ("fpscr", "0xfbf79f9f", True),
331 ("s0", "1.25", True),
332 ("s31", "0.75", True),
334 ("d17", "987", False),
335 ("q1", "{0x01 0x02 0x03 0x00 0x00 0x00 0x00 0x00 0x09 0x0a 0x2f 0x2f 0x2f 0x2f 0x2f 0x2f}", True),
337 "{0x01 0x02 0x03 0x00 0x00 0x00 0x00 0x00 0x09 0x0a 0x2f 0x2f 0x2f 0x2f 0x0e 0x0f}",
341 for (reg, val, must) in reg_list:
342 self.write_and_read(currentFrame, reg, val, must)
344 if self.getArchitecture() in ['amd64', 'i386', 'x86_64']:
348 " \"{0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00}\"")
359 # Returns an SBValueList.
360 registerSets = currentFrame.GetRegisters()
361 for registerSet in registerSets:
362 if 'advanced vector extensions' in registerSet.GetName().lower():
364 if 'memory protection extension' in registerSet.GetName().lower():
368 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}"
369 self.write_and_read(currentFrame, "ymm0", new_value)
370 self.write_and_read(currentFrame, "ymm7", new_value)
371 self.expect("expr $ymm0", substrs=['vector_type'])
373 self.runCmd("register read ymm0")
376 # Test write and read for bnd0.
377 new_value_w = "{0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09 0x0a 0x0b 0x0c 0x0d 0x0e 0x0f 0x10}"
378 self.runCmd("register write bnd0 \'" + new_value_w + "\'")
379 new_value_r = "{0x0807060504030201 0x100f0e0d0c0b0a09}"
380 self.expect("register read bnd0", substrs = ['bnd0 = ', new_value_r])
381 self.expect("expr $bnd0", substrs = ['vector_type'])
383 # Test write and for bndstatus.
384 new_value = "{0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08}"
385 self.write_and_read(currentFrame, "bndstatus", new_value)
386 self.expect("expr $bndstatus", substrs = ['vector_type'])
388 self.runCmd("register read bnd0")
390 def convenience_registers(self):
391 """Test convenience registers."""
394 # The command "register read -a" does output a derived register like
396 self.expect("register read -a", matching=True,
399 # ...however, the vanilla "register read" command should not output derived registers like eax.
400 self.expect("register read", matching=False,
403 # Test reading of rax and eax.
404 self.expect("register read rax eax",
405 substrs=['rax = 0x', 'eax = 0x'])
407 # Now write rax with a unique bit pattern and test that eax indeed
408 # represents the lower half of rax.
409 self.runCmd("register write rax 0x1234567887654321")
410 self.expect("register read rax 0x1234567887654321",
411 substrs=['0x1234567887654321'])
413 def convenience_registers_with_process_attach(self, test_16bit_regs):
414 """Test convenience registers after a 'process attach'."""
415 exe = os.path.join(os.getcwd(), "a.out")
417 # Spawn a new process
418 pid = self.spawnSubprocess(exe, ['wait_for_attach']).pid
419 self.addTearDownHook(self.cleanupSubprocesses)
422 print("pid of spawned process: %d" % pid)
424 self.runCmd("process attach -p %d" % pid)
426 # Check that "register read eax" works.
427 self.runCmd("register read eax")
429 if self.getArchitecture() in ['amd64', 'x86_64']:
430 self.expect("expr -- ($rax & 0xffffffff) == $eax",
434 self.expect("expr -- $ax == (($ah << 8) | $al)",