2 Test the 'register' command.
5 from __future__ import print_function
12 from lldbsuite.test.lldbtest import *
13 import lldbsuite.test.lldbutil as lldbutil
15 class RegisterCommandsTestCase(TestBase):
17 mydir = TestBase.compute_mydir(__file__)
21 self.has_teardown = False
24 self.dbg.GetSelectedTarget().GetProcess().Destroy()
25 TestBase.tearDown(self)
28 @skipUnlessArch(['amd64', 'arm', 'i386', 'x86_64'])
29 def test_register_commands(self):
30 """Test commands related to registers, in particular vector registers."""
34 # verify that logging does not assert
35 self.log_enable("registers")
37 self.expect("register read -a", MISSING_EXPECTED_REGISTERS,
38 substrs = ['registers were unavailable'], matching = False)
40 if self.getArchitecture() in ['amd64', 'i386', 'x86_64']:
41 self.runCmd("register read xmm0")
42 self.runCmd("register read ymm15") # may be available
43 elif self.getArchitecture() in ['arm']:
44 self.runCmd("register read s0")
45 self.runCmd("register read q15") # may be available
47 self.expect("register read -s 3", substrs = ['invalid register set index: 3'], error = True)
50 @skipIfTargetAndroid(archs=["i386"]) # Writing of mxcsr register fails, presumably due to a kernel/hardware problem
51 @skipUnlessArch(['amd64', 'arm', 'i386', 'x86_64'])
52 def test_fp_register_write(self):
53 """Test commands that write to registers, in particular floating-point registers."""
55 self.fp_register_write()
58 @expectedFailureAndroid(archs=["i386"]) # "register read fstat" always return 0xffff
59 @skipIfFreeBSD #llvm.org/pr25057
60 @skipUnlessArch(['amd64', 'i386', 'x86_64'])
61 def test_fp_special_purpose_register_read(self):
62 """Test commands that read fpu special purpose registers."""
64 self.fp_special_purpose_register_read()
67 @skipUnlessArch(['amd64', 'arm', 'i386', 'x86_64'])
68 def test_register_expressions(self):
69 """Test expression evaluation with commands related to registers."""
73 if self.getArchitecture() in ['amd64', 'i386', 'x86_64']:
76 elif self.getArchitecture() in ['arm']:
80 self.expect("expr/x $%s" % gpr, substrs = ['unsigned int', ' = 0x'])
81 self.expect("expr $%s" % vector, substrs = ['vector_type'])
82 self.expect("expr (unsigned int)$%s[0]" % vector, substrs = ['unsigned int'])
84 if self.getArchitecture() in ['amd64', 'x86_64']:
85 self.expect("expr -- ($rax & 0xffffffff) == $eax", substrs = ['true'])
88 @skipUnlessArch(['amd64', 'x86_64'])
89 def test_convenience_registers(self):
90 """Test convenience registers."""
92 self.convenience_registers()
95 @skipUnlessArch(['amd64', 'x86_64'])
96 def test_convenience_registers_with_process_attach(self):
97 """Test convenience registers after a 'process attach'."""
99 self.convenience_registers_with_process_attach(test_16bit_regs=False)
102 @skipUnlessArch(['amd64', 'x86_64'])
103 def test_convenience_registers_16bit_with_process_attach(self):
104 """Test convenience registers after a 'process attach'."""
106 self.convenience_registers_with_process_attach(test_16bit_regs=True)
108 def common_setup(self):
109 exe = os.path.join(os.getcwd(), "a.out")
111 self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET)
114 lldbutil.run_break_set_by_symbol (self, "main", num_expected_locations=-1)
116 self.runCmd("run", RUN_SUCCEEDED)
118 # The stop reason of the thread should be breakpoint.
119 self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT,
120 substrs = ['stopped', 'stop reason = breakpoint'])
122 # platform specific logging of the specified category
123 def log_enable(self, category):
124 # This intentionally checks the host platform rather than the target
125 # platform as logging is host side.
127 if sys.platform.startswith("darwin"):
128 self.platform = "" # TODO: add support for "log enable darwin registers"
130 if sys.platform.startswith("freebsd"):
131 self.platform = "freebsd"
133 if sys.platform.startswith("linux"):
134 self.platform = "linux"
136 if sys.platform.startswith("netbsd"):
137 self.platform = "netbsd"
139 if self.platform != "":
140 self.log_file = os.path.join(os.getcwd(), 'TestRegisters.log')
141 self.runCmd("log enable " + self.platform + " " + str(category) + " registers -v -f " + self.log_file, RUN_SUCCEEDED)
142 if not self.has_teardown:
143 def remove_log(self):
144 if os.path.exists(self.log_file):
145 os.remove(self.log_file)
146 self.has_teardown = True
147 self.addTearDownHook(remove_log)
149 def write_and_read(self, frame, register, new_value, must_exist = True):
150 value = frame.FindValue(register, lldb.eValueTypeRegister)
152 self.assertTrue(value.IsValid(), "finding a value for register " + register)
153 elif not value.IsValid():
154 return # If register doesn't exist, skip this test
156 self.runCmd("register write " + register + " \'" + new_value + "\'")
157 self.expect("register read " + register, substrs = [register + ' = ', new_value])
159 def fp_special_purpose_register_read(self):
160 exe = os.path.join(os.getcwd(), "a.out")
162 # Create a target by the debugger.
163 target = self.dbg.CreateTarget(exe)
164 self.assertTrue(target, VALID_TARGET)
166 # Launch the process and stop.
167 self.expect ("run", PROCESS_STOPPED, substrs = ['stopped'])
169 # Check stop reason; Should be either signal SIGTRAP or EXC_BREAKPOINT
170 output = self.res.GetOutput()
172 substrs = ['stop reason = EXC_BREAKPOINT', 'stop reason = signal SIGTRAP']
174 matched = output.find(str1) != -1
175 with recording(self, False) as sbuf:
176 print("%s sub string: %s" % ('Expecting', str1), file=sbuf)
177 print("Matched" if matched else "Not Matched", file=sbuf)
180 self.assertTrue(matched, STOPPED_DUE_TO_SIGNAL)
182 process = target.GetProcess()
183 self.assertTrue(process.GetState() == lldb.eStateStopped,
186 thread = process.GetThreadAtIndex(0)
187 self.assertTrue(thread.IsValid(), "current thread is valid")
189 currentFrame = thread.GetFrameAtIndex(0)
190 self.assertTrue(currentFrame.IsValid(), "current frame is valid")
192 # Extract the value of fstat and ftag flag at the point just before
193 # we start pushing floating point values on st% register stack
194 value = currentFrame.FindValue("fstat", lldb.eValueTypeRegister)
195 error = lldb.SBError()
196 reg_value_fstat_initial = value.GetValueAsUnsigned(error, 0)
198 self.assertTrue(error.Success(), "reading a value for fstat")
199 value = currentFrame.FindValue("ftag", lldb.eValueTypeRegister)
200 error = lldb.SBError()
201 reg_value_ftag_initial = value.GetValueAsUnsigned(error, 0)
203 self.assertTrue(error.Success(), "reading a value for ftag")
204 fstat_top_pointer_initial = (reg_value_fstat_initial & 0x3800)>>11
206 # Execute 'si' aka 'thread step-inst' instruction 5 times and with
207 # every execution verify the value of fstat and ftag registers
209 # step into the next instruction to push a value on 'st' register stack
210 self.runCmd ("si", RUN_SUCCEEDED)
212 # Verify fstat and save it to be used for verification in next execution of 'si' command
213 if not (reg_value_fstat_initial & 0x3800):
214 self.expect("register read fstat",
215 substrs = ['fstat' + ' = ', str("0x%0.4x" %((reg_value_fstat_initial & ~(0x3800))| 0x3800))])
216 reg_value_fstat_initial = ((reg_value_fstat_initial & ~(0x3800))| 0x3800)
217 fstat_top_pointer_initial = 7
219 self.expect("register read fstat",
220 substrs = ['fstat' + ' = ', str("0x%0.4x" % (reg_value_fstat_initial - 0x0800))])
221 reg_value_fstat_initial = (reg_value_fstat_initial - 0x0800)
222 fstat_top_pointer_initial -= 1
224 # Verify ftag and save it to be used for verification in next execution of 'si' command
225 self.expect("register read ftag",
226 substrs = ['ftag' + ' = ', str("0x%0.2x" % (reg_value_ftag_initial | (1<< fstat_top_pointer_initial)))])
227 reg_value_ftag_initial = reg_value_ftag_initial | (1<< fstat_top_pointer_initial)
229 def fp_register_write(self):
230 exe = os.path.join(os.getcwd(), "a.out")
232 # Create a target by the debugger.
233 target = self.dbg.CreateTarget(exe)
234 self.assertTrue(target, VALID_TARGET)
236 lldbutil.run_break_set_by_symbol (self, "main", num_expected_locations=-1)
238 # Launch the process, and do not stop at the entry point.
239 process = target.LaunchSimple (None, None, self.get_process_working_directory())
241 process = target.GetProcess()
242 self.assertTrue(process.GetState() == lldb.eStateStopped, PROCESS_STOPPED)
244 thread = process.GetThreadAtIndex(0)
245 self.assertTrue(thread.IsValid(), "current thread is valid")
247 currentFrame = thread.GetFrameAtIndex(0)
248 self.assertTrue(currentFrame.IsValid(), "current frame is valid")
250 if self.getArchitecture() in ['amd64', 'i386', 'x86_64']:
252 # reg value must-have
253 ("fcw", "0x0000ff0e", False),
254 ("fsw", "0x0000ff0e", False),
255 ("ftw", "0x0000ff0e", False),
256 ("ip", "0x0000ff0e", False),
257 ("dp", "0x0000ff0e", False),
258 ("mxcsr", "0x0000ff0e", False),
259 ("mxcsrmask", "0x0000ff0e", False),
263 if currentFrame.FindRegister("st0").IsValid():
265 elif currentFrame.FindRegister("stmm0").IsValid():
267 if st0regname is not None:
268 # reg value must-have
269 reg_list.append((st0regname, "{0x01 0x02 0x03 0x00 0x00 0x00 0x00 0x00 0x00 0x00}", True))
270 reg_list.append(("xmm0", "{0x01 0x02 0x03 0x00 0x00 0x00 0x00 0x00 0x09 0x0a 0x2f 0x2f 0x2f 0x2f 0x2f 0x2f}", True))
271 reg_list.append(("xmm15", "{0x01 0x02 0x03 0x00 0x00 0x00 0x00 0x00 0x09 0x0a 0x2f 0x2f 0x2f 0x2f 0x0e 0x0f}", False))
272 elif self.getArchitecture() in ['arm']:
274 # reg value must-have
275 ("fpscr", "0xfbf79f9f", True),
276 ("s0", "1.25", True),
277 ("s31", "0.75", True),
279 ("d17", "987", False),
280 ("q1", "{0x01 0x02 0x03 0x00 0x00 0x00 0x00 0x00 0x09 0x0a 0x2f 0x2f 0x2f 0x2f 0x2f 0x2f}", True),
281 ("q14", "{0x01 0x02 0x03 0x00 0x00 0x00 0x00 0x00 0x09 0x0a 0x2f 0x2f 0x2f 0x2f 0x0e 0x0f}", False),
284 for (reg, val, must) in reg_list:
285 self.write_and_read(currentFrame, reg, val, must)
287 if self.getArchitecture() in ['amd64', 'i386', 'x86_64']:
288 self.runCmd("register write " + st0regname + " \"{0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00}\"")
289 self.expect("register read " + st0regname + " --format f", substrs = [st0regname + ' = 0'])
292 registerSets = currentFrame.GetRegisters() # Returns an SBValueList.
293 for registerSet in registerSets:
294 if 'advanced vector extensions' in registerSet.GetName().lower():
299 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}"
300 self.write_and_read(currentFrame, "ymm0", new_value)
301 self.write_and_read(currentFrame, "ymm7", new_value)
302 self.expect("expr $ymm0", substrs = ['vector_type'])
304 self.runCmd("register read ymm0")
306 def convenience_registers(self):
307 """Test convenience registers."""
310 # The command "register read -a" does output a derived register like eax...
311 self.expect("register read -a", matching=True,
314 # ...however, the vanilla "register read" command should not output derived registers like eax.
315 self.expect("register read", matching=False,
318 # Test reading of rax and eax.
319 self.expect("register read rax eax",
320 substrs = ['rax = 0x', 'eax = 0x'])
322 # Now write rax with a unique bit pattern and test that eax indeed represents the lower half of rax.
323 self.runCmd("register write rax 0x1234567887654321")
324 self.expect("register read rax 0x1234567887654321",
325 substrs = ['0x1234567887654321'])
327 def convenience_registers_with_process_attach(self, test_16bit_regs):
328 """Test convenience registers after a 'process attach'."""
329 exe = os.path.join(os.getcwd(), "a.out")
331 # Spawn a new process
332 pid = self.spawnSubprocess(exe, ['wait_for_attach']).pid
333 self.addTearDownHook(self.cleanupSubprocesses)
336 print("pid of spawned process: %d" % pid)
338 self.runCmd("process attach -p %d" % pid)
340 # Check that "register read eax" works.
341 self.runCmd("register read eax")
343 if self.getArchitecture() in ['amd64', 'x86_64']:
344 self.expect("expr -- ($rax & 0xffffffff) == $eax",
348 self.expect("expr -- $ax == (($ah << 8) | $al)",