2 Test SBProcess APIs, including ReadMemory(), WriteMemory(), and others.
5 from __future__ import print_function
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
16 class ProcessAPITestCase(TestBase):
18 mydir = TestBase.compute_mydir(__file__)
21 # Call super's setUp().
23 # Find the line number to break inside main().
24 self.line = line_number(
26 "// Set break point at this line and check variable 'my_char'.")
28 @add_test_categories(['pyapi'])
29 def test_read_memory(self):
30 """Test Python SBProcess.ReadMemory() API."""
32 exe = self.getBuildArtifact("a.out")
34 target = self.dbg.CreateTarget(exe)
35 self.assertTrue(target, VALID_TARGET)
37 breakpoint = target.BreakpointCreateByLocation("main.cpp", self.line)
38 self.assertTrue(breakpoint, VALID_BREAKPOINT)
40 # Launch the process, and do not stop at the entry point.
41 process = target.LaunchSimple(
42 None, None, self.get_process_working_directory())
44 thread = get_stopped_thread(process, lldb.eStopReasonBreakpoint)
47 "There should be a thread stopped due to breakpoint")
48 frame = thread.GetFrameAtIndex(0)
50 # Get the SBValue for the global variable 'my_char'.
51 val = frame.FindValue("my_char", lldb.eValueTypeVariableGlobal)
52 self.DebugSBValue(val)
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")
63 print("memory content:", content)
67 "Result from SBProcess.ReadMemory() matches our expected output: 'x'",
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")
79 print("cstring read is:", cstring)
83 "Result from SBProcess.ReadCStringFromMemory() matches our expected output",
85 startstr='Does it work?')
87 # Get the SBValue for the global variable 'my_cstring'.
88 val = frame.FindValue("my_cstring", lldb.eValueTypeVariableGlobal)
89 self.DebugSBValue(val)
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
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")
100 print("cstring read is:", cstring)
104 "Result from SBProcess.ReadCStringFromMemory() matches our expected output",
106 startstr='lldb.SBProcess.ReadCStringFromMemory() works!')
108 # Get the SBValue for the global variable 'my_uint32'.
109 val = frame.FindValue("my_uint32", lldb.eValueTypeVariableGlobal)
110 self.DebugSBValue(val)
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")
120 print("uint32 read is:", my_uint32)
122 if my_uint32 != 12345:
124 "Result from SBProcess.ReadUnsignedFromMemory() does not match our expected output")
126 @add_test_categories(['pyapi'])
127 def test_write_memory(self):
128 """Test Python SBProcess.WriteMemory() API."""
130 exe = self.getBuildArtifact("a.out")
132 target = self.dbg.CreateTarget(exe)
133 self.assertTrue(target, VALID_TARGET)
135 breakpoint = target.BreakpointCreateByLocation("main.cpp", self.line)
136 self.assertTrue(breakpoint, VALID_BREAKPOINT)
138 # Launch the process, and do not stop at the entry point.
139 process = target.LaunchSimple(
140 None, None, self.get_process_working_directory())
142 thread = get_stopped_thread(process, lldb.eStopReasonBreakpoint)
145 "There should be a thread stopped due to breakpoint")
146 frame = thread.GetFrameAtIndex(0)
148 # Get the SBValue for the global variable 'my_char'.
149 val = frame.FindValue("my_char", lldb.eValueTypeVariableGlobal)
150 self.DebugSBValue(val)
152 # If the variable does not have a load address, there's no sense
154 if not val.GetLocation().startswith("0x"):
157 # OK, let's get the hex location of the variable.
158 location = int(val.GetLocation(), 16)
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
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")
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")
177 print("memory content:", content)
181 "Result from SBProcess.ReadMemory() matches our expected output: 'a'",
185 @add_test_categories(['pyapi'])
186 def test_access_my_int(self):
187 """Test access 'my_int' using Python SBProcess.GetByteOrder() and other APIs."""
189 exe = self.getBuildArtifact("a.out")
191 target = self.dbg.CreateTarget(exe)
192 self.assertTrue(target, VALID_TARGET)
194 breakpoint = target.BreakpointCreateByLocation("main.cpp", self.line)
195 self.assertTrue(breakpoint, VALID_BREAKPOINT)
197 # Launch the process, and do not stop at the entry point.
198 process = target.LaunchSimple(
199 None, None, self.get_process_working_directory())
201 thread = get_stopped_thread(process, lldb.eStopReasonBreakpoint)
204 "There should be a thread stopped due to breakpoint")
205 frame = thread.GetFrameAtIndex(0)
207 # Get the SBValue for the global variable 'my_int'.
208 val = frame.FindValue("my_int", lldb.eValueTypeVariableGlobal)
209 self.DebugSBValue(val)
211 # If the variable does not have a load address, there's no sense
213 if not val.GetLocation().startswith("0x"):
216 # OK, let's get the hex location of the variable.
217 location = int(val.GetLocation(), 16)
219 # Note that the canonical from of the bytearray is little endian.
220 from lldbsuite.test.lldbutil import int_to_bytearray, bytearray_to_int
222 byteSize = val.GetByteSize()
223 bytes = int_to_bytearray(256, byteSize)
225 byteOrder = process.GetByteOrder()
226 if byteOrder == lldb.eByteOrderBig:
228 elif byteOrder == lldb.eByteOrderLittle:
231 # Neither big endian nor little endian? Return for now.
232 # Add more logic here if we want to handle other types.
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
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")
245 # Make sure that the val we got originally updates itself to notice the
249 "SBProcess.ReadMemory() successfully writes (int)256 to the memory location for 'my_int'",
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)
258 "SBProcess.ReadMemory() successfully writes (int)256 to the memory location for 'my_int'",
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")
268 # The bytearray_to_int utility function expects a little endian
270 if byteOrder == lldb.eByteOrderBig:
271 content = bytearray(content, 'ascii')
274 new_value = bytearray_to_int(content, byteSize)
276 self.fail("Memory content read from 'my_int' does not match (int)256")
278 # Dump the memory content....
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."""
287 exe = self.getBuildArtifact("a.out")
289 target = self.dbg.CreateTarget(exe)
290 self.assertTrue(target, VALID_TARGET)
292 # Launch the process, and do not stop at the entry point.
293 process = target.LaunchSimple(
294 None, None, self.get_process_working_directory())
297 print("process state:", state_type_to_str(process.GetState()))
298 self.assertTrue(process.GetState() != lldb.eStateConnected)
300 error = lldb.SBError()
301 success = process.RemoteLaunch(
302 None, None, None, None, None, None, 0, False, error)
305 "RemoteLaunch() should fail for process state != eStateConnected")
307 @add_test_categories(['pyapi'])
308 def test_get_num_supported_hardware_watchpoints(self):
309 """Test SBProcess.GetNumSupportedHardwareWatchpoints() API with a process."""
311 exe = self.getBuildArtifact("a.out")
312 self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET)
314 target = self.dbg.CreateTarget(exe)
315 self.assertTrue(target, VALID_TARGET)
317 breakpoint = target.BreakpointCreateByLocation("main.cpp", self.line)
318 self.assertTrue(breakpoint, VALID_BREAKPOINT)
320 # Launch the process, and do not stop at the entry point.
321 process = target.LaunchSimple(
322 None, None, self.get_process_working_directory())
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)
329 @add_test_categories(['pyapi'])
331 def test_get_process_info(self):
332 """Test SBProcess::GetProcessInfo() API with a locally launched process."""
334 exe = self.getBuildArtifact("a.out")
335 self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET)
337 target = self.dbg.CreateTarget(exe)
338 self.assertTrue(target, VALID_TARGET)
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)
349 if not error.Success():
350 self.fail("Failed to launch process")
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")
362 process_info.GetProcessID(), lldb.LLDB_INVALID_PROCESS_ID,
363 "Process ID is valid")
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():
369 process_info.GetUserID(), lldb.UINT32_MAX,
370 "Process user ID is valid")
373 process_info.GetUserID(), lldb.UINT32_MAX,
374 "Process user ID is invalid")
376 if process_info.GroupIDIsValid():
378 process_info.GetGroupID(), lldb.UINT32_MAX,
379 "Process group ID is valid")
382 process_info.GetGroupID(), lldb.UINT32_MAX,
383 "Process group ID is invalid")
385 if process_info.EffectiveUserIDIsValid():
387 process_info.GetEffectiveUserID(), lldb.UINT32_MAX,
388 "Process effective user ID is valid")
391 process_info.GetEffectiveUserID(), lldb.UINT32_MAX,
392 "Process effective user ID is invalid")
394 if process_info.EffectiveGroupIDIsValid():
396 process_info.GetEffectiveGroupID(), lldb.UINT32_MAX,
397 "Process effective group ID is valid")
400 process_info.GetEffectiveGroupID(), lldb.UINT32_MAX,
401 "Process effective group ID is invalid")
403 process_info.GetParentProcessID()