]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - packages/Python/lldbsuite/test/python_api/process/TestProcessAPI.py
Vendor import of lldb trunk r338150:
[FreeBSD/FreeBSD.git] / packages / Python / lldbsuite / test / python_api / process / TestProcessAPI.py
1 """
2 Test SBProcess APIs, including ReadMemory(), WriteMemory(), and others.
3 """
4
5 from __future__ import print_function
6
7
8 import os
9 import time
10 import lldb
11 from lldbsuite.test.decorators import *
12 from lldbsuite.test.lldbtest import *
13 from lldbsuite.test.lldbutil import get_stopped_thread, state_type_to_str
14
15
16 class ProcessAPITestCase(TestBase):
17
18     mydir = TestBase.compute_mydir(__file__)
19
20     def setUp(self):
21         # Call super's setUp().
22         TestBase.setUp(self)
23         # Find the line number to break inside main().
24         self.line = line_number(
25             "main.cpp",
26             "// Set break point at this line and check variable 'my_char'.")
27
28     @add_test_categories(['pyapi'])
29     def test_read_memory(self):
30         """Test Python SBProcess.ReadMemory() API."""
31         self.build()
32         exe = self.getBuildArtifact("a.out")
33
34         target = self.dbg.CreateTarget(exe)
35         self.assertTrue(target, VALID_TARGET)
36
37         breakpoint = target.BreakpointCreateByLocation("main.cpp", self.line)
38         self.assertTrue(breakpoint, VALID_BREAKPOINT)
39
40         # Launch the process, and do not stop at the entry point.
41         process = target.LaunchSimple(
42             None, None, self.get_process_working_directory())
43
44         thread = get_stopped_thread(process, lldb.eStopReasonBreakpoint)
45         self.assertTrue(
46             thread.IsValid(),
47             "There should be a thread stopped due to breakpoint")
48         frame = thread.GetFrameAtIndex(0)
49
50         # Get the SBValue for the global variable 'my_char'.
51         val = frame.FindValue("my_char", lldb.eValueTypeVariableGlobal)
52         self.DebugSBValue(val)
53
54         # Due to the typemap magic (see lldb.swig), we pass in 1 to ReadMemory and
55         # expect to get a Python string as the result object!
56         error = lldb.SBError()
57         self.assertFalse(val.TypeIsPointerType())
58         content = process.ReadMemory(
59             val.AddressOf().GetValueAsUnsigned(), 1, error)
60         if not error.Success():
61             self.fail("SBProcess.ReadMemory() failed")
62         if self.TraceOn():
63             print("memory content:", content)
64
65         self.expect(
66             content,
67             "Result from SBProcess.ReadMemory() matches our expected output: 'x'",
68             exe=False,
69             startstr=b'x')
70
71         # Read (char *)my_char_ptr.
72         val = frame.FindValue("my_char_ptr", lldb.eValueTypeVariableGlobal)
73         self.DebugSBValue(val)
74         cstring = process.ReadCStringFromMemory(
75             val.GetValueAsUnsigned(), 256, error)
76         if not error.Success():
77             self.fail("SBProcess.ReadCStringFromMemory() failed")
78         if self.TraceOn():
79             print("cstring read is:", cstring)
80
81         self.expect(
82             cstring,
83             "Result from SBProcess.ReadCStringFromMemory() matches our expected output",
84             exe=False,
85             startstr='Does it work?')
86
87         # Get the SBValue for the global variable 'my_cstring'.
88         val = frame.FindValue("my_cstring", lldb.eValueTypeVariableGlobal)
89         self.DebugSBValue(val)
90
91         # Due to the typemap magic (see lldb.swig), we pass in 256 to read at most 256 bytes
92         # from the address, and expect to get a Python string as the result
93         # object!
94         self.assertFalse(val.TypeIsPointerType())
95         cstring = process.ReadCStringFromMemory(
96             val.AddressOf().GetValueAsUnsigned(), 256, error)
97         if not error.Success():
98             self.fail("SBProcess.ReadCStringFromMemory() failed")
99         if self.TraceOn():
100             print("cstring read is:", cstring)
101
102         self.expect(
103             cstring,
104             "Result from SBProcess.ReadCStringFromMemory() matches our expected output",
105             exe=False,
106             startstr='lldb.SBProcess.ReadCStringFromMemory() works!')
107
108         # Get the SBValue for the global variable 'my_uint32'.
109         val = frame.FindValue("my_uint32", lldb.eValueTypeVariableGlobal)
110         self.DebugSBValue(val)
111
112         # Due to the typemap magic (see lldb.swig), we pass in 4 to read 4 bytes
113         # from the address, and expect to get an int as the result!
114         self.assertFalse(val.TypeIsPointerType())
115         my_uint32 = process.ReadUnsignedFromMemory(
116             val.AddressOf().GetValueAsUnsigned(), 4, error)
117         if not error.Success():
118             self.fail("SBProcess.ReadCStringFromMemory() failed")
119         if self.TraceOn():
120             print("uint32 read is:", my_uint32)
121
122         if my_uint32 != 12345:
123             self.fail(
124                 "Result from SBProcess.ReadUnsignedFromMemory() does not match our expected output")
125
126     @add_test_categories(['pyapi'])
127     def test_write_memory(self):
128         """Test Python SBProcess.WriteMemory() API."""
129         self.build()
130         exe = self.getBuildArtifact("a.out")
131
132         target = self.dbg.CreateTarget(exe)
133         self.assertTrue(target, VALID_TARGET)
134
135         breakpoint = target.BreakpointCreateByLocation("main.cpp", self.line)
136         self.assertTrue(breakpoint, VALID_BREAKPOINT)
137
138         # Launch the process, and do not stop at the entry point.
139         process = target.LaunchSimple(
140             None, None, self.get_process_working_directory())
141
142         thread = get_stopped_thread(process, lldb.eStopReasonBreakpoint)
143         self.assertTrue(
144             thread.IsValid(),
145             "There should be a thread stopped due to breakpoint")
146         frame = thread.GetFrameAtIndex(0)
147
148         # Get the SBValue for the global variable 'my_char'.
149         val = frame.FindValue("my_char", lldb.eValueTypeVariableGlobal)
150         self.DebugSBValue(val)
151
152         # If the variable does not have a load address, there's no sense
153         # continuing.
154         if not val.GetLocation().startswith("0x"):
155             return
156
157         # OK, let's get the hex location of the variable.
158         location = int(val.GetLocation(), 16)
159
160         # The program logic makes the 'my_char' variable to have memory content as 'x'.
161         # But we want to use the WriteMemory() API to assign 'a' to the
162         # variable.
163
164         # Now use WriteMemory() API to write 'a' into the global variable.
165         error = lldb.SBError()
166         result = process.WriteMemory(location, 'a', error)
167         if not error.Success() or result != 1:
168             self.fail("SBProcess.WriteMemory() failed")
169
170         # Read from the memory location.  This time it should be 'a'.
171         # Due to the typemap magic (see lldb.swig), we pass in 1 to ReadMemory and
172         # expect to get a Python string as the result object!
173         content = process.ReadMemory(location, 1, error)
174         if not error.Success():
175             self.fail("SBProcess.ReadMemory() failed")
176         if self.TraceOn():
177             print("memory content:", content)
178
179         self.expect(
180             content,
181             "Result from SBProcess.ReadMemory() matches our expected output: 'a'",
182             exe=False,
183             startstr=b'a')
184
185     @add_test_categories(['pyapi'])
186     def test_access_my_int(self):
187         """Test access 'my_int' using Python SBProcess.GetByteOrder() and other APIs."""
188         self.build()
189         exe = self.getBuildArtifact("a.out")
190
191         target = self.dbg.CreateTarget(exe)
192         self.assertTrue(target, VALID_TARGET)
193
194         breakpoint = target.BreakpointCreateByLocation("main.cpp", self.line)
195         self.assertTrue(breakpoint, VALID_BREAKPOINT)
196
197         # Launch the process, and do not stop at the entry point.
198         process = target.LaunchSimple(
199             None, None, self.get_process_working_directory())
200
201         thread = get_stopped_thread(process, lldb.eStopReasonBreakpoint)
202         self.assertTrue(
203             thread.IsValid(),
204             "There should be a thread stopped due to breakpoint")
205         frame = thread.GetFrameAtIndex(0)
206
207         # Get the SBValue for the global variable 'my_int'.
208         val = frame.FindValue("my_int", lldb.eValueTypeVariableGlobal)
209         self.DebugSBValue(val)
210
211         # If the variable does not have a load address, there's no sense
212         # continuing.
213         if not val.GetLocation().startswith("0x"):
214             return
215
216         # OK, let's get the hex location of the variable.
217         location = int(val.GetLocation(), 16)
218
219         # Note that the canonical from of the bytearray is little endian.
220         from lldbsuite.test.lldbutil import int_to_bytearray, bytearray_to_int
221
222         byteSize = val.GetByteSize()
223         bytes = int_to_bytearray(256, byteSize)
224
225         byteOrder = process.GetByteOrder()
226         if byteOrder == lldb.eByteOrderBig:
227             bytes.reverse()
228         elif byteOrder == lldb.eByteOrderLittle:
229             pass
230         else:
231             # Neither big endian nor little endian?  Return for now.
232             # Add more logic here if we want to handle other types.
233             return
234
235         # The program logic makes the 'my_int' variable to have int type and value of 0.
236         # But we want to use the WriteMemory() API to assign 256 to the
237         # variable.
238
239         # Now use WriteMemory() API to write 256 into the global variable.
240         error = lldb.SBError()
241         result = process.WriteMemory(location, bytes, error)
242         if not error.Success() or result != byteSize:
243             self.fail("SBProcess.WriteMemory() failed")
244
245         # Make sure that the val we got originally updates itself to notice the
246         # change:
247         self.expect(
248             val.GetValue(),
249             "SBProcess.ReadMemory() successfully writes (int)256 to the memory location for 'my_int'",
250             exe=False,
251             startstr='256')
252
253         # And for grins, get the SBValue for the global variable 'my_int'
254         # again, to make sure that also tracks the new value:
255         val = frame.FindValue("my_int", lldb.eValueTypeVariableGlobal)
256         self.expect(
257             val.GetValue(),
258             "SBProcess.ReadMemory() successfully writes (int)256 to the memory location for 'my_int'",
259             exe=False,
260             startstr='256')
261
262         # Now read the memory content.  The bytearray should have (byte)1 as
263         # the second element.
264         content = process.ReadMemory(location, byteSize, error)
265         if not error.Success():
266             self.fail("SBProcess.ReadMemory() failed")
267
268         # The bytearray_to_int utility function expects a little endian
269         # bytearray.
270         if byteOrder == lldb.eByteOrderBig:
271             content = bytearray(content, 'ascii')
272             content.reverse()
273
274         new_value = bytearray_to_int(content, byteSize)
275         if new_value != 256:
276             self.fail("Memory content read from 'my_int' does not match (int)256")
277
278         # Dump the memory content....
279         if self.TraceOn():
280             for i in content:
281                 print("byte:", i)
282
283     @add_test_categories(['pyapi'])
284     def test_remote_launch(self):
285         """Test SBProcess.RemoteLaunch() API with a process not in eStateConnected, and it should fail."""
286         self.build()
287         exe = self.getBuildArtifact("a.out")
288
289         target = self.dbg.CreateTarget(exe)
290         self.assertTrue(target, VALID_TARGET)
291
292         # Launch the process, and do not stop at the entry point.
293         process = target.LaunchSimple(
294             None, None, self.get_process_working_directory())
295
296         if self.TraceOn():
297             print("process state:", state_type_to_str(process.GetState()))
298         self.assertTrue(process.GetState() != lldb.eStateConnected)
299
300         error = lldb.SBError()
301         success = process.RemoteLaunch(
302             None, None, None, None, None, None, 0, False, error)
303         self.assertTrue(
304             not success,
305             "RemoteLaunch() should fail for process state != eStateConnected")
306
307     @add_test_categories(['pyapi'])
308     def test_get_num_supported_hardware_watchpoints(self):
309         """Test SBProcess.GetNumSupportedHardwareWatchpoints() API with a process."""
310         self.build()
311         exe = self.getBuildArtifact("a.out")
312         self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET)
313
314         target = self.dbg.CreateTarget(exe)
315         self.assertTrue(target, VALID_TARGET)
316
317         breakpoint = target.BreakpointCreateByLocation("main.cpp", self.line)
318         self.assertTrue(breakpoint, VALID_BREAKPOINT)
319
320         # Launch the process, and do not stop at the entry point.
321         process = target.LaunchSimple(
322             None, None, self.get_process_working_directory())
323
324         error = lldb.SBError()
325         num = process.GetNumSupportedHardwareWatchpoints(error)
326         if self.TraceOn() and error.Success():
327             print("Number of supported hardware watchpoints: %d" % num)
328
329     @add_test_categories(['pyapi'])
330     @no_debug_info_test
331     def test_get_process_info(self):
332         """Test SBProcess::GetProcessInfo() API with a locally launched process."""
333         self.build()
334         exe = self.getBuildArtifact("a.out")
335         self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET)
336
337         target = self.dbg.CreateTarget(exe)
338         self.assertTrue(target, VALID_TARGET)
339
340         # Launch the process and stop at the entry point.
341         launch_info = lldb.SBLaunchInfo(None)
342         launch_info.SetWorkingDirectory(self.get_process_working_directory())
343         launch_flags = launch_info.GetLaunchFlags()
344         launch_flags |= lldb.eLaunchFlagStopAtEntry
345         launch_info.SetLaunchFlags(launch_flags)
346         error = lldb.SBError()
347         process = target.Launch(launch_info, error)
348
349         if not error.Success():
350             self.fail("Failed to launch process")
351
352         # Verify basic process info can be retrieved successfully
353         process_info = process.GetProcessInfo()
354         self.assertTrue(process_info.IsValid())
355         file_spec = process_info.GetExecutableFile()
356         self.assertTrue(file_spec.IsValid())
357         process_name = process_info.GetName()
358         self.assertIsNotNone(process_name, "Process has a name")
359         self.assertGreater(len(process_name), 0, "Process name isn't blank")
360         self.assertEqual(file_spec.GetFilename(), "a.out")
361         self.assertNotEqual(
362             process_info.GetProcessID(), lldb.LLDB_INVALID_PROCESS_ID,
363             "Process ID is valid")
364
365         # Additional process info varies by platform, so just check that
366         # whatever info was retrieved is consistent and nothing blows up.
367         if process_info.UserIDIsValid():
368             self.assertNotEqual(
369                 process_info.GetUserID(), lldb.UINT32_MAX,
370                 "Process user ID is valid")
371         else:
372             self.assertEqual(
373                 process_info.GetUserID(), lldb.UINT32_MAX,
374                 "Process user ID is invalid")
375
376         if process_info.GroupIDIsValid():
377             self.assertNotEqual(
378                 process_info.GetGroupID(), lldb.UINT32_MAX,
379                 "Process group ID is valid")
380         else:
381             self.assertEqual(
382                 process_info.GetGroupID(), lldb.UINT32_MAX,
383                 "Process group ID is invalid")
384
385         if process_info.EffectiveUserIDIsValid():
386             self.assertNotEqual(
387                 process_info.GetEffectiveUserID(), lldb.UINT32_MAX,
388                 "Process effective user ID is valid")
389         else:
390             self.assertEqual(
391                 process_info.GetEffectiveUserID(), lldb.UINT32_MAX,
392                 "Process effective user ID is invalid")
393
394         if process_info.EffectiveGroupIDIsValid():
395             self.assertNotEqual(
396                 process_info.GetEffectiveGroupID(), lldb.UINT32_MAX,
397                 "Process effective group ID is valid")
398         else:
399             self.assertEqual(
400                 process_info.GetEffectiveGroupID(), lldb.UINT32_MAX,
401                 "Process effective group ID is invalid")
402
403         process_info.GetParentProcessID()