01d2367c85502314fe8191057c9f974d55f43f0c
[openbsd] /
1 """
2 Test the 'register' command.
3 """
4
5 from __future__ import print_function
6
7
8 import os
9 import sys
10 import lldb
11 from lldbsuite.test.decorators import *
12 from lldbsuite.test.lldbtest import *
13 from lldbsuite.test import lldbutil
14
15
16 class 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     @expectedFailureNetBSD
32     def test_register_commands(self):
33         """Test commands related to registers, in particular vector registers."""
34         self.build()
35         self.common_setup()
36
37         # verify that logging does not assert
38         self.log_enable("registers")
39
40         self.expect("register read -a", MISSING_EXPECTED_REGISTERS,
41                     substrs=['registers were unavailable'], matching=False)
42
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
50
51         self.expect(
52             "register read -s 4",
53             substrs=['invalid register set index: 4'],
54             error=True)
55
56     @skipIfiOSSimulator
57     # Writing of mxcsr register fails, presumably due to a kernel/hardware
58     # problem
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."""
64         self.build()
65         self.fp_register_write()
66
67     @skipIfiOSSimulator
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."""
77         self.build()
78         self.fp_special_purpose_register_read()
79
80     @skipIfiOSSimulator
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."""
85         self.build()
86         self.common_setup()
87
88         if self.getArchitecture() in ['amd64', 'i386', 'x86_64']:
89             gpr = "eax"
90             vector = "xmm0"
91         elif self.getArchitecture() in ['arm64', 'aarch64', 'arm64e', 'arm64_32']:
92             gpr = "w0"
93             vector = "v0"
94         elif self.getArchitecture() in ['arm', 'armv7', 'armv7k']:
95             gpr = "r0"
96             vector = "q0"
97
98         self.expect("expr/x $%s" % gpr, substrs=['unsigned int', ' = 0x'])
99         self.expect("expr $%s" % vector, substrs=['vector_type'])
100         self.expect(
101             "expr (unsigned int)$%s[0]" %
102             vector, substrs=['unsigned int'])
103
104         if self.getArchitecture() in ['amd64', 'x86_64']:
105             self.expect(
106                 "expr -- ($rax & 0xffffffff) == $eax",
107                 substrs=['true'])
108
109     @skipIfiOSSimulator
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."""
114         self.build()
115         self.convenience_registers()
116
117     @skipIfiOSSimulator
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'."""
123         self.build()
124         self.convenience_registers_with_process_attach(test_16bit_regs=False)
125
126     @skipIfiOSSimulator
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'."""
132         self.build()
133         self.convenience_registers_with_process_attach(test_16bit_regs=True)
134
135     def common_setup(self):
136         exe = self.getBuildArtifact("a.out")
137
138         self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET)
139
140         # Break in main().
141         lldbutil.run_break_set_by_symbol(
142             self, "main", num_expected_locations=-1)
143
144         self.runCmd("run", RUN_SUCCEEDED)
145
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'])
149
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.
154         self.platform = ""
155         if (sys.platform.startswith("freebsd") or
156                 sys.platform.startswith("linux") or
157                 sys.platform.startswith("netbsd")):
158             self.platform = "posix"
159
160         if self.platform != "":
161             self.log_file = self.getBuildArtifact('TestRegisters.log')
162             self.runCmd(
163                 "log enable " +
164                 self.platform +
165                 " " +
166                 str(category) +
167                 " registers -v -f " +
168                 self.log_file,
169                 RUN_SUCCEEDED)
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)
176
177     def write_and_read(self, frame, register, new_value, must_exist=True):
178         value = frame.FindValue(register, lldb.eValueTypeRegister)
179         if must_exist:
180             self.assertTrue(
181                 value.IsValid(),
182                 "finding a value for register " +
183                 register)
184         elif not value.IsValid():
185             return  # If register doesn't exist, skip this test
186
187         # Also test the 're' alias.
188         self.runCmd("re write " + register + " \'" + new_value + "\'")
189         self.expect(
190             "register read " +
191             register,
192             substrs=[
193                 register +
194                 ' = ',
195                 new_value])
196
197     def fp_special_purpose_register_read(self):
198         exe = self.getBuildArtifact("a.out")
199
200         # Create a target by the debugger.
201         target = self.dbg.CreateTarget(exe)
202         self.assertTrue(target, VALID_TARGET)
203
204         # Launch the process and stop.
205         self.expect("run", PROCESS_STOPPED, substrs=['stopped'])
206
207         # Check stop reason; Should be either signal SIGTRAP or EXC_BREAKPOINT
208         output = self.res.GetOutput()
209         matched = False
210         substrs = [
211             'stop reason = EXC_BREAKPOINT',
212             'stop reason = signal SIGTRAP']
213         for str1 in substrs:
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)
218             if matched:
219                 break
220         self.assertTrue(matched, STOPPED_DUE_TO_SIGNAL)
221
222         process = target.GetProcess()
223         self.assertTrue(process.GetState() == lldb.eStateStopped,
224                         PROCESS_STOPPED)
225
226         thread = process.GetThreadAtIndex(0)
227         self.assertTrue(thread.IsValid(), "current thread is valid")
228
229         currentFrame = thread.GetFrameAtIndex(0)
230         self.assertTrue(currentFrame.IsValid(), "current frame is valid")
231
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)
237
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)
242
243         self.assertTrue(error.Success(), "reading a value for ftag")
244         fstat_top_pointer_initial = (reg_value_fstat_initial & 0x3800) >> 11
245
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
250             # stack
251             self.runCmd("si", RUN_SUCCEEDED)
252
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
261             else:
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
266
267             # Verify ftag and save it to be used for verification in next
268             # execution of 'si' command
269             self.expect(
270                 "register read ftag", substrs=[
271                     'ftag' + ' = ', str(
272                         "0x%0.4x" %
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)
277
278     def fp_register_write(self):
279         exe = self.getBuildArtifact("a.out")
280
281         # Create a target by the debugger.
282         target = self.dbg.CreateTarget(exe)
283         self.assertTrue(target, VALID_TARGET)
284
285         # Launch the process, stop at the entry point.
286         error = lldb.SBError()
287         process = target.Launch(
288                 lldb.SBListener(),
289                 None, None, # argv, envp
290                 None, None, None, # stdin/out/err
291                 self.get_process_working_directory(),
292                 0, # launch flags
293                 True, # stop at entry
294                 error)
295         self.assertTrue(error.Success(), "Launch succeeds. Error is :" + str(error))
296
297         self.assertTrue(
298             process.GetState() == lldb.eStateStopped,
299             PROCESS_STOPPED)
300
301         thread = process.GetThreadAtIndex(0)
302         self.assertTrue(thread.IsValid(), "current thread is valid")
303
304         currentFrame = thread.GetFrameAtIndex(0)
305         self.assertTrue(currentFrame.IsValid(), "current frame is valid")
306
307         if self.getArchitecture() in ['amd64', 'i386', 'x86_64']:
308             reg_list = [
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),
317             ]
318
319             st0regname = None
320             if currentFrame.FindRegister("st0").IsValid():
321                 st0regname = "st0"
322             elif currentFrame.FindRegister("stmm0").IsValid():
323                 st0regname = "stmm0"
324             if st0regname is not None:
325                 # reg          value
326                 # must-have
327                 reg_list.append(
328                     (st0regname, "{0x01 0x02 0x03 0x00 0x00 0x00 0x00 0x00 0x00 0x00}", True))
329                 reg_list.append(
330                     ("xmm0",
331                      "{0x01 0x02 0x03 0x00 0x00 0x00 0x00 0x00 0x09 0x0a 0x2f 0x2f 0x2f 0x2f 0x2f 0x2f}",
332                      True))
333                 reg_list.append(
334                     ("xmm15",
335                      "{0x01 0x02 0x03 0x00 0x00 0x00 0x00 0x00 0x09 0x0a 0x2f 0x2f 0x2f 0x2f 0x0e 0x0f}",
336                      False))
337         elif self.getArchitecture() in ['arm64', 'aarch64', 'arm64e', 'arm64_32']:
338             reg_list = [
339                 # reg      value
340                 # must-have
341                 ("fpsr", "0xfbf79f9f", True),
342                 ("s0", "1.25", True),
343                 ("s31", "0.75", True),
344                 ("d1", "123", True),
345                 ("d17", "987", False),
346                 ("v1", "{0x01 0x02 0x03 0x00 0x00 0x00 0x00 0x00 0x09 0x0a 0x2f 0x2f 0x2f 0x2f 0x2f 0x2f}", True),
347                 ("v14",
348                  "{0x01 0x02 0x03 0x00 0x00 0x00 0x00 0x00 0x09 0x0a 0x2f 0x2f 0x2f 0x2f 0x0e 0x0f}",
349                  False),
350             ]
351         elif self.getArchitecture() in ['armv7'] and self.platformIsDarwin():
352             reg_list = [
353                 # reg      value
354                 # must-have
355                 ("fpsr", "0xfbf79f9f", True),
356                 ("s0", "1.25", True),
357                 ("s31", "0.75", True),
358                 ("d1", "123", True),
359                 ("d17", "987", False),
360                 ("q1", "{0x01 0x02 0x03 0x00 0x00 0x00 0x00 0x00 0x09 0x0a 0x2f 0x2f 0x2f 0x2f 0x2f 0x2f}", True),
361                 ("q14",
362                  "{0x01 0x02 0x03 0x00 0x00 0x00 0x00 0x00 0x09 0x0a 0x2f 0x2f 0x2f 0x2f 0x0e 0x0f}",
363                  False),
364             ]
365         elif self.getArchitecture() in ['arm', 'armv7k']:
366             reg_list = [
367                 # reg      value
368                 # must-have
369                 ("fpscr", "0xfbf79f9f", True),
370                 ("s0", "1.25", True),
371                 ("s31", "0.75", True),
372                 ("d1", "123", True),
373                 ("d17", "987", False),
374                 ("q1", "{0x01 0x02 0x03 0x00 0x00 0x00 0x00 0x00 0x09 0x0a 0x2f 0x2f 0x2f 0x2f 0x2f 0x2f}", True),
375                 ("q14",
376                  "{0x01 0x02 0x03 0x00 0x00 0x00 0x00 0x00 0x09 0x0a 0x2f 0x2f 0x2f 0x2f 0x0e 0x0f}",
377                  False),
378             ]
379
380         for (reg, val, must) in reg_list:
381             self.write_and_read(currentFrame, reg, val, must)
382
383         if self.getArchitecture() in ['amd64', 'i386', 'x86_64']:
384             if st0regname is None:
385                 self.fail("st0regname could not be determined")
386             self.runCmd(
387                 "register write " +
388                 st0regname +
389                 " \"{0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00}\"")
390             self.expect(
391                 "register read " +
392                 st0regname +
393                 " --format f",
394                 substrs=[
395                     st0regname +
396                     ' = 0'])
397
398             has_avx = False
399             has_mpx = False
400             # Returns an SBValueList.
401             registerSets = currentFrame.GetRegisters()
402             for registerSet in registerSets:
403                 if 'advanced vector extensions' in registerSet.GetName().lower():
404                     has_avx = True
405                 if 'memory protection extension' in registerSet.GetName().lower():
406                     has_mpx = True
407
408             if has_avx:
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'])
413             else:
414                 self.runCmd("register read ymm0")
415
416             if has_mpx:
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'])
423
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'])
428             else:
429                 self.runCmd("register read bnd0")
430
431     def convenience_registers(self):
432         """Test convenience registers."""
433         self.common_setup()
434
435         # The command "register read -a" does output a derived register like
436         # eax...
437         self.expect("register read -a", matching=True,
438                     substrs=['eax'])
439
440         # ...however, the vanilla "register read" command should not output derived registers like eax.
441         self.expect("register read", matching=False,
442                     substrs=['eax'])
443
444         # Test reading of rax and eax.
445         self.expect("register read rax eax",
446                     substrs=['rax = 0x', 'eax = 0x'])
447
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'])
453
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")
457
458         # Spawn a new process
459         pid = self.spawnSubprocess(exe, ['wait_for_attach']).pid
460         self.addTearDownHook(self.cleanupSubprocesses)
461
462         if self.TraceOn():
463             print("pid of spawned process: %d" % pid)
464
465         self.runCmd("process attach -p %d" % pid)
466
467         # Check that "register read eax" works.
468         self.runCmd("register read eax")
469
470         if self.getArchitecture() in ['amd64', 'x86_64']:
471             self.expect("expr -- ($rax & 0xffffffff) == $eax",
472                         substrs=['true'])
473
474         if test_16bit_regs:
475             self.expect("expr -- $ax == (($ah << 8) | $al)",
476                         substrs=['true'])
477
478     @skipIfiOSSimulator
479     @skipIf(archs=no_match(['amd64', 'arm', 'i386', 'x86_64']))
480     def test_invalid_invocation(self):
481         self.build()
482         self.common_setup()
483
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"])
486
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"])
489
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>"])
494
495     @skipIfiOSSimulator
496     @skipIf(archs=no_match(['amd64', 'arm', 'i386', 'x86_64']))
497     def test_write_unknown_register(self):
498         self.build()
499         self.common_setup()
500
501         self.expect("register write blub 1", error=True,
502                     substrs=["error: Register not found for 'blub'."])