]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - packages/Python/lldbsuite/test/functionalities/register/register_command/TestRegisters.py
Vendor import of lldb release_39 branch r287912:
[FreeBSD/FreeBSD.git] / packages / Python / lldbsuite / test / functionalities / register / register_command / TestRegisters.py
1 """
2 Test the 'register' command.
3 """
4
5 from __future__ import print_function
6
7
8 import os
9 import sys
10 import time
11 import re
12 import lldb
13 from lldbsuite.test.decorators import *
14 from lldbsuite.test.lldbtest import *
15 from lldbsuite.test import lldbutil
16
17
18 class RegisterCommandsTestCase(TestBase):
19
20     mydir = TestBase.compute_mydir(__file__)
21
22     def setUp(self):
23         TestBase.setUp(self)
24         self.has_teardown = False
25
26     def tearDown(self):
27         self.dbg.GetSelectedTarget().GetProcess().Destroy()
28         TestBase.tearDown(self)
29
30     @skipIfiOSSimulator
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."""
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']:
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     def test_fp_register_write(self):
62         """Test commands that write to registers, in particular floating-point registers."""
63         self.build()
64         self.fp_register_write()
65
66     @skipIfiOSSimulator
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."""
73         self.build()
74         self.fp_special_purpose_register_read()
75
76     @skipIfiOSSimulator
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."""
80         self.build()
81         self.common_setup()
82
83         if self.getArchitecture() in ['amd64', 'i386', 'x86_64']:
84             gpr = "eax"
85             vector = "xmm0"
86         elif self.getArchitecture() in ['arm']:
87             gpr = "r0"
88             vector = "q0"
89
90         self.expect("expr/x $%s" % gpr, substrs=['unsigned int', ' = 0x'])
91         self.expect("expr $%s" % vector, substrs=['vector_type'])
92         self.expect(
93             "expr (unsigned int)$%s[0]" %
94             vector, substrs=['unsigned int'])
95
96         if self.getArchitecture() in ['amd64', 'x86_64']:
97             self.expect(
98                 "expr -- ($rax & 0xffffffff) == $eax",
99                 substrs=['true'])
100
101     @skipIfiOSSimulator
102     @skipIf(archs=no_match(['amd64', 'x86_64']))
103     def test_convenience_registers(self):
104         """Test convenience registers."""
105         self.build()
106         self.convenience_registers()
107
108     @skipIfiOSSimulator
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'."""
112         self.build()
113         self.convenience_registers_with_process_attach(test_16bit_regs=False)
114
115     @skipIfiOSSimulator
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'."""
119         self.build()
120         self.convenience_registers_with_process_attach(test_16bit_regs=True)
121
122     def common_setup(self):
123         exe = os.path.join(os.getcwd(), "a.out")
124
125         self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET)
126
127         # Break in main().
128         lldbutil.run_break_set_by_symbol(
129             self, "main", num_expected_locations=-1)
130
131         self.runCmd("run", RUN_SUCCEEDED)
132
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'])
136
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.
141         self.platform = ""
142         if sys.platform.startswith("darwin"):
143             self.platform = ""  # TODO: add support for "log enable darwin registers"
144
145         if sys.platform.startswith("freebsd"):
146             self.platform = "freebsd"
147
148         if sys.platform.startswith("linux"):
149             self.platform = "linux"
150
151         if sys.platform.startswith("netbsd"):
152             self.platform = "netbsd"
153
154         if self.platform != "":
155             self.log_file = os.path.join(os.getcwd(), 'TestRegisters.log')
156             self.runCmd(
157                 "log enable " +
158                 self.platform +
159                 " " +
160                 str(category) +
161                 " registers -v -f " +
162                 self.log_file,
163                 RUN_SUCCEEDED)
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)
170
171     def write_and_read(self, frame, register, new_value, must_exist=True):
172         value = frame.FindValue(register, lldb.eValueTypeRegister)
173         if must_exist:
174             self.assertTrue(
175                 value.IsValid(),
176                 "finding a value for register " +
177                 register)
178         elif not value.IsValid():
179             return  # If register doesn't exist, skip this test
180
181         self.runCmd("register write " + register + " \'" + new_value + "\'")
182         self.expect(
183             "register read " +
184             register,
185             substrs=[
186                 register +
187                 ' = ',
188                 new_value])
189
190     def fp_special_purpose_register_read(self):
191         exe = os.path.join(os.getcwd(), "a.out")
192
193         # Create a target by the debugger.
194         target = self.dbg.CreateTarget(exe)
195         self.assertTrue(target, VALID_TARGET)
196
197         # Launch the process and stop.
198         self.expect("run", PROCESS_STOPPED, substrs=['stopped'])
199
200         # Check stop reason; Should be either signal SIGTRAP or EXC_BREAKPOINT
201         output = self.res.GetOutput()
202         matched = False
203         substrs = [
204             'stop reason = EXC_BREAKPOINT',
205             'stop reason = signal SIGTRAP']
206         for str1 in substrs:
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)
211             if matched:
212                 break
213         self.assertTrue(matched, STOPPED_DUE_TO_SIGNAL)
214
215         process = target.GetProcess()
216         self.assertTrue(process.GetState() == lldb.eStateStopped,
217                         PROCESS_STOPPED)
218
219         thread = process.GetThreadAtIndex(0)
220         self.assertTrue(thread.IsValid(), "current thread is valid")
221
222         currentFrame = thread.GetFrameAtIndex(0)
223         self.assertTrue(currentFrame.IsValid(), "current frame is valid")
224
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)
230
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)
235
236         self.assertTrue(error.Success(), "reading a value for ftag")
237         fstat_top_pointer_initial = (reg_value_fstat_initial & 0x3800) >> 11
238
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
243             # stack
244             self.runCmd("si", RUN_SUCCEEDED)
245
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
254             else:
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
259
260             # Verify ftag and save it to be used for verification in next
261             # execution of 'si' command
262             self.expect(
263                 "register read ftag", substrs=[
264                     'ftag' + ' = ', str(
265                         "0x%0.2x" %
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)
270
271     def fp_register_write(self):
272         exe = os.path.join(os.getcwd(), "a.out")
273
274         # Create a target by the debugger.
275         target = self.dbg.CreateTarget(exe)
276         self.assertTrue(target, VALID_TARGET)
277
278         lldbutil.run_break_set_by_symbol(
279             self, "main", num_expected_locations=-1)
280
281         # Launch the process, and do not stop at the entry point.
282         process = target.LaunchSimple(
283             None, None, self.get_process_working_directory())
284
285         process = target.GetProcess()
286         self.assertTrue(
287             process.GetState() == lldb.eStateStopped,
288             PROCESS_STOPPED)
289
290         thread = process.GetThreadAtIndex(0)
291         self.assertTrue(thread.IsValid(), "current thread is valid")
292
293         currentFrame = thread.GetFrameAtIndex(0)
294         self.assertTrue(currentFrame.IsValid(), "current frame is valid")
295
296         if self.getArchitecture() in ['amd64', 'i386', 'x86_64']:
297             reg_list = [
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),
306             ]
307
308             st0regname = None
309             if currentFrame.FindRegister("st0").IsValid():
310                 st0regname = "st0"
311             elif currentFrame.FindRegister("stmm0").IsValid():
312                 st0regname = "stmm0"
313             if st0regname is not None:
314                 # reg          value
315                 # must-have
316                 reg_list.append(
317                     (st0regname, "{0x01 0x02 0x03 0x00 0x00 0x00 0x00 0x00 0x00 0x00}", True))
318                 reg_list.append(
319                     ("xmm0",
320                      "{0x01 0x02 0x03 0x00 0x00 0x00 0x00 0x00 0x09 0x0a 0x2f 0x2f 0x2f 0x2f 0x2f 0x2f}",
321                      True))
322                 reg_list.append(
323                     ("xmm15",
324                      "{0x01 0x02 0x03 0x00 0x00 0x00 0x00 0x00 0x09 0x0a 0x2f 0x2f 0x2f 0x2f 0x0e 0x0f}",
325                      False))
326         elif self.getArchitecture() in ['arm']:
327             reg_list = [
328                 # reg      value
329                 # must-have
330                 ("fpscr", "0xfbf79f9f", True),
331                 ("s0", "1.25", True),
332                 ("s31", "0.75", True),
333                 ("d1", "123", True),
334                 ("d17", "987", False),
335                 ("q1", "{0x01 0x02 0x03 0x00 0x00 0x00 0x00 0x00 0x09 0x0a 0x2f 0x2f 0x2f 0x2f 0x2f 0x2f}", True),
336                 ("q14",
337                  "{0x01 0x02 0x03 0x00 0x00 0x00 0x00 0x00 0x09 0x0a 0x2f 0x2f 0x2f 0x2f 0x0e 0x0f}",
338                  False),
339             ]
340
341         for (reg, val, must) in reg_list:
342             self.write_and_read(currentFrame, reg, val, must)
343
344         if self.getArchitecture() in ['amd64', 'i386', 'x86_64']:
345             self.runCmd(
346                 "register write " +
347                 st0regname +
348                 " \"{0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00}\"")
349             self.expect(
350                 "register read " +
351                 st0regname +
352                 " --format f",
353                 substrs=[
354                     st0regname +
355                     ' = 0'])
356
357             has_avx = False
358             has_mpx = False
359             # Returns an SBValueList.
360             registerSets = currentFrame.GetRegisters()
361             for registerSet in registerSets:
362                 if 'advanced vector extensions' in registerSet.GetName().lower():
363                     has_avx = True
364                 if 'memory protection extension' in registerSet.GetName().lower():
365                     has_mpx = True
366
367             if has_avx:
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'])
372             else:
373                 self.runCmd("register read ymm0")
374
375             if has_mpx:
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'])
382
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'])
387             else:
388                 self.runCmd("register read bnd0")
389
390     def convenience_registers(self):
391         """Test convenience registers."""
392         self.common_setup()
393
394         # The command "register read -a" does output a derived register like
395         # eax...
396         self.expect("register read -a", matching=True,
397                     substrs=['eax'])
398
399         # ...however, the vanilla "register read" command should not output derived registers like eax.
400         self.expect("register read", matching=False,
401                     substrs=['eax'])
402
403         # Test reading of rax and eax.
404         self.expect("register read rax eax",
405                     substrs=['rax = 0x', 'eax = 0x'])
406
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'])
412
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")
416
417         # Spawn a new process
418         pid = self.spawnSubprocess(exe, ['wait_for_attach']).pid
419         self.addTearDownHook(self.cleanupSubprocesses)
420
421         if self.TraceOn():
422             print("pid of spawned process: %d" % pid)
423
424         self.runCmd("process attach -p %d" % pid)
425
426         # Check that "register read eax" works.
427         self.runCmd("register read eax")
428
429         if self.getArchitecture() in ['amd64', 'x86_64']:
430             self.expect("expr -- ($rax & 0xffffffff) == $eax",
431                         substrs=['true'])
432
433         if test_16bit_regs:
434             self.expect("expr -- $ax == (($ah << 8) | $al)",
435                         substrs=['true'])