]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - packages/Python/lldbsuite/test/functionalities/register/TestRegisters.py
Vendor import of lldb trunk r256945:
[FreeBSD/FreeBSD.git] / packages / Python / lldbsuite / test / functionalities / register / TestRegisters.py
1 """
2 Test the 'register' command.
3 """
4
5 from __future__ import print_function
6
7
8
9 import os, sys, time
10 import re
11 import lldb
12 from lldbsuite.test.lldbtest import *
13 import lldbsuite.test.lldbutil as lldbutil
14
15 class RegisterCommandsTestCase(TestBase):
16
17     mydir = TestBase.compute_mydir(__file__)
18
19     def setUp(self):
20         TestBase.setUp(self)
21         self.has_teardown = False
22
23     def tearDown(self):
24         self.dbg.GetSelectedTarget().GetProcess().Destroy()
25         TestBase.tearDown(self)
26
27     @skipIfiOSSimulator
28     @skipUnlessArch(['amd64', 'arm', 'i386', 'x86_64'])
29     def test_register_commands(self):
30         """Test commands related to registers, in particular vector registers."""
31         self.build()
32         self.common_setup()
33
34         # verify that logging does not assert
35         self.log_enable("registers")
36
37         self.expect("register read -a", MISSING_EXPECTED_REGISTERS,
38             substrs = ['registers were unavailable'], matching = False)
39
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
46
47         self.expect("register read -s 3", substrs = ['invalid register set index: 3'], error = True)
48
49     @skipIfiOSSimulator
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."""
54         self.build()
55         self.fp_register_write()
56
57     @skipIfiOSSimulator
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."""
63         self.build()
64         self.fp_special_purpose_register_read()
65
66     @skipIfiOSSimulator
67     @skipUnlessArch(['amd64', 'arm', 'i386', 'x86_64'])
68     def test_register_expressions(self):
69         """Test expression evaluation with commands related to registers."""
70         self.build()
71         self.common_setup()
72
73         if self.getArchitecture() in ['amd64', 'i386', 'x86_64']:
74             gpr = "eax"
75             vector = "xmm0"
76         elif self.getArchitecture() in ['arm']:
77             gpr = "r0"
78             vector = "q0"
79
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'])
83
84         if self.getArchitecture() in ['amd64', 'x86_64']:
85             self.expect("expr -- ($rax & 0xffffffff) == $eax", substrs = ['true'])
86
87     @skipIfiOSSimulator
88     @skipUnlessArch(['amd64', 'x86_64'])
89     def test_convenience_registers(self):
90         """Test convenience registers."""
91         self.build()
92         self.convenience_registers()
93
94     @skipIfiOSSimulator
95     @skipUnlessArch(['amd64', 'x86_64'])
96     def test_convenience_registers_with_process_attach(self):
97         """Test convenience registers after a 'process attach'."""
98         self.build()
99         self.convenience_registers_with_process_attach(test_16bit_regs=False)
100
101     @skipIfiOSSimulator
102     @skipUnlessArch(['amd64', 'x86_64'])
103     def test_convenience_registers_16bit_with_process_attach(self):
104         """Test convenience registers after a 'process attach'."""
105         self.build()
106         self.convenience_registers_with_process_attach(test_16bit_regs=True)
107
108     def common_setup(self):
109         exe = os.path.join(os.getcwd(), "a.out")
110
111         self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET)
112
113         # Break in main().
114         lldbutil.run_break_set_by_symbol (self, "main", num_expected_locations=-1)
115
116         self.runCmd("run", RUN_SUCCEEDED)
117
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'])
121
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.
126         self.platform = ""
127         if sys.platform.startswith("darwin"):
128             self.platform = "" # TODO: add support for "log enable darwin registers"
129
130         if sys.platform.startswith("freebsd"):
131             self.platform = "freebsd"
132
133         if sys.platform.startswith("linux"):
134             self.platform = "linux"
135
136         if sys.platform.startswith("netbsd"):
137             self.platform = "netbsd"
138
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)
148
149     def write_and_read(self, frame, register, new_value, must_exist = True):
150         value = frame.FindValue(register, lldb.eValueTypeRegister)
151         if must_exist:
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
155
156         self.runCmd("register write " + register + " \'" + new_value + "\'")
157         self.expect("register read " + register, substrs = [register + ' = ', new_value])
158
159     def fp_special_purpose_register_read(self):
160         exe = os.path.join(os.getcwd(), "a.out")
161
162         # Create a target by the debugger.
163         target = self.dbg.CreateTarget(exe)
164         self.assertTrue(target, VALID_TARGET)
165
166         # Launch the process and stop.
167         self.expect ("run", PROCESS_STOPPED, substrs = ['stopped'])
168
169         # Check stop reason; Should be either signal SIGTRAP or EXC_BREAKPOINT
170         output = self.res.GetOutput()
171         matched = False
172         substrs = ['stop reason = EXC_BREAKPOINT', 'stop reason = signal SIGTRAP']
173         for str1 in substrs:
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)
178             if matched:
179                 break
180         self.assertTrue(matched, STOPPED_DUE_TO_SIGNAL)
181
182         process = target.GetProcess()
183         self.assertTrue(process.GetState() == lldb.eStateStopped,
184                         PROCESS_STOPPED)
185
186         thread = process.GetThreadAtIndex(0)
187         self.assertTrue(thread.IsValid(), "current thread is valid")
188
189         currentFrame = thread.GetFrameAtIndex(0)
190         self.assertTrue(currentFrame.IsValid(), "current frame is valid")
191
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)
197
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)
202
203         self.assertTrue(error.Success(), "reading a value for ftag")
204         fstat_top_pointer_initial = (reg_value_fstat_initial & 0x3800)>>11
205
206         # Execute 'si' aka 'thread step-inst' instruction 5 times and with
207         # every execution verify the value of fstat and ftag registers
208         for x in range(0,5):
209             # step into the next instruction to push a value on 'st' register stack
210             self.runCmd ("si", RUN_SUCCEEDED)
211
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
218             else :
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
223
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)
228
229     def fp_register_write(self):
230         exe = os.path.join(os.getcwd(), "a.out")
231
232         # Create a target by the debugger.
233         target = self.dbg.CreateTarget(exe)
234         self.assertTrue(target, VALID_TARGET)
235
236         lldbutil.run_break_set_by_symbol (self, "main", num_expected_locations=-1)
237
238         # Launch the process, and do not stop at the entry point.
239         process = target.LaunchSimple (None, None, self.get_process_working_directory())
240
241         process = target.GetProcess()
242         self.assertTrue(process.GetState() == lldb.eStateStopped, PROCESS_STOPPED)
243
244         thread = process.GetThreadAtIndex(0)
245         self.assertTrue(thread.IsValid(), "current thread is valid")
246
247         currentFrame = thread.GetFrameAtIndex(0)
248         self.assertTrue(currentFrame.IsValid(), "current frame is valid")
249
250         if self.getArchitecture() in ['amd64', 'i386', 'x86_64']:
251             reg_list = [
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),
260             ]
261
262             st0regname = None
263             if currentFrame.FindRegister("st0").IsValid():
264                 st0regname = "st0"
265             elif currentFrame.FindRegister("stmm0").IsValid():
266                 st0regname = "stmm0"
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']:
273             reg_list = [
274                 # reg      value                                                                               must-have
275                 ("fpscr", "0xfbf79f9f",                                                                        True),
276                 ("s0",    "1.25",                                                                              True),
277                 ("s31",   "0.75",                                                                              True),
278                 ("d1",    "123",                                                                               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),
282             ]
283
284         for (reg, val, must) in reg_list:
285             self.write_and_read(currentFrame, reg, val, must)
286
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'])
290
291             has_avx = False 
292             registerSets = currentFrame.GetRegisters() # Returns an SBValueList.
293             for registerSet in registerSets:
294                 if 'advanced vector extensions' in registerSet.GetName().lower():
295                     has_avx = True
296                     break
297
298             if has_avx:
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'])
303             else:
304                 self.runCmd("register read ymm0")
305
306     def convenience_registers(self):
307         """Test convenience registers."""
308         self.common_setup()
309
310         # The command "register read -a" does output a derived register like eax...
311         self.expect("register read -a", matching=True,
312             substrs = ['eax'])
313
314         # ...however, the vanilla "register read" command should not output derived registers like eax.
315         self.expect("register read", matching=False,
316             substrs = ['eax'])
317         
318         # Test reading of rax and eax.
319         self.expect("register read rax eax",
320             substrs = ['rax = 0x', 'eax = 0x'])
321
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'])
326
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")
330
331         # Spawn a new process
332         pid = self.spawnSubprocess(exe, ['wait_for_attach']).pid
333         self.addTearDownHook(self.cleanupSubprocesses)
334
335         if self.TraceOn():
336             print("pid of spawned process: %d" % pid)
337
338         self.runCmd("process attach -p %d" % pid)
339
340         # Check that "register read eax" works.
341         self.runCmd("register read eax")
342
343         if self.getArchitecture() in ['amd64', 'x86_64']:
344             self.expect("expr -- ($rax & 0xffffffff) == $eax",
345                 substrs = ['true'])
346
347         if test_16bit_regs:
348             self.expect("expr -- $ax == (($ah << 8) | $al)",
349                 substrs = ['true'])