2 Test SBProcess APIs, including ReadMemory(), WriteMemory(), and others.
7 from lldbsuite
.test
.decorators
import *
8 from lldbsuite
.test
.lldbtest
import *
9 from lldbsuite
.test
.lldbutil
import get_stopped_thread
, state_type_to_str
12 class ProcessAPITestCase(TestBase
):
14 # Call super's setUp().
16 # Find the line number to break inside main().
17 self
.line
= line_number(
18 "main.cpp", "// Set break point at this line and check variable 'my_char'."
21 def test_scripted_implementation(self
):
23 exe
= self
.getBuildArtifact("a.out")
25 (target
, process
, _
, _
) = lldbutil
.run_to_source_breakpoint(
26 self
, "Set break point", lldb
.SBFileSpec("main.cpp")
29 self
.assertTrue(process
, PROCESS_IS_VALID
)
30 self
.assertEqual(process
.GetScriptedImplementation(), None)
32 def test_read_memory(self
):
33 """Test Python SBProcess.ReadMemory() API."""
35 exe
= self
.getBuildArtifact("a.out")
37 target
= self
.dbg
.CreateTarget(exe
)
38 self
.assertTrue(target
, VALID_TARGET
)
40 breakpoint
= target
.BreakpointCreateByLocation("main.cpp", self
.line
)
41 self
.assertTrue(breakpoint
, VALID_BREAKPOINT
)
43 # Launch the process, and do not stop at the entry point.
44 process
= target
.LaunchSimple(None, None, self
.get_process_working_directory())
46 thread
= get_stopped_thread(process
, lldb
.eStopReasonBreakpoint
)
48 thread
.IsValid(), "There should be a thread stopped due to breakpoint"
50 frame
= thread
.GetFrameAtIndex(0)
52 # Get the SBValue for the file static variable 'my_char'.
53 val
= frame
.FindValue("my_char", lldb
.eValueTypeVariableStatic
)
54 self
.DebugSBValue(val
)
56 # Due to the typemap magic (see lldb.swig), we pass in 1 to ReadMemory and
57 # expect to get a Python string as the result object!
58 error
= lldb
.SBError()
59 self
.assertFalse(val
.TypeIsPointerType())
60 content
= process
.ReadMemory(val
.AddressOf().GetValueAsUnsigned(), 1, error
)
61 if not error
.Success():
62 self
.fail("SBProcess.ReadMemory() failed")
64 print("memory content:", content
)
68 "Result from SBProcess.ReadMemory() matches our expected output: 'x'",
73 # Read (char *)my_char_ptr.
74 val
= frame
.FindValue("my_char_ptr", lldb
.eValueTypeVariableGlobal
)
75 self
.DebugSBValue(val
)
76 cstring
= process
.ReadCStringFromMemory(val
.GetValueAsUnsigned(), 256, error
)
77 if not error
.Success():
78 self
.fail("SBProcess.ReadCStringFromMemory() failed")
80 print("cstring read is:", cstring
)
84 "Result from SBProcess.ReadCStringFromMemory() matches our expected output",
86 startstr
="Does it work?",
89 # Get the SBValue for the global variable 'my_cstring'.
90 val
= frame
.FindValue("my_cstring", lldb
.eValueTypeVariableGlobal
)
91 self
.DebugSBValue(val
)
93 # Due to the typemap magic (see lldb.swig), we pass in 256 to read at most 256 bytes
94 # from the address, and expect to get a Python string as the result
96 self
.assertFalse(val
.TypeIsPointerType())
97 cstring
= process
.ReadCStringFromMemory(
98 val
.AddressOf().GetValueAsUnsigned(), 256, error
100 if not error
.Success():
101 self
.fail("SBProcess.ReadCStringFromMemory() failed")
103 print("cstring read is:", cstring
)
107 "Result from SBProcess.ReadCStringFromMemory() matches our expected output",
109 startstr
="lldb.SBProcess.ReadCStringFromMemory() works!",
112 # Get the SBValue for the global variable 'my_uint32'.
113 val
= frame
.FindValue("my_uint32", lldb
.eValueTypeVariableGlobal
)
114 self
.DebugSBValue(val
)
116 # Due to the typemap magic (see lldb.swig), we pass in 4 to read 4 bytes
117 # from the address, and expect to get an int as the result!
118 self
.assertFalse(val
.TypeIsPointerType())
119 my_uint32
= process
.ReadUnsignedFromMemory(
120 val
.AddressOf().GetValueAsUnsigned(), 4, error
122 if not error
.Success():
123 self
.fail("SBProcess.ReadCStringFromMemory() failed")
125 print("uint32 read is:", my_uint32
)
127 if my_uint32
!= 12345:
129 "Result from SBProcess.ReadUnsignedFromMemory() does not match our expected output"
132 def test_write_memory(self
):
133 """Test Python SBProcess.WriteMemory() API."""
135 exe
= self
.getBuildArtifact("a.out")
137 target
= self
.dbg
.CreateTarget(exe
)
138 self
.assertTrue(target
, VALID_TARGET
)
140 breakpoint
= target
.BreakpointCreateByLocation("main.cpp", self
.line
)
141 self
.assertTrue(breakpoint
, VALID_BREAKPOINT
)
143 # Launch the process, and do not stop at the entry point.
144 process
= target
.LaunchSimple(None, None, self
.get_process_working_directory())
146 thread
= get_stopped_thread(process
, lldb
.eStopReasonBreakpoint
)
148 thread
.IsValid(), "There should be a thread stopped due to breakpoint"
150 frame
= thread
.GetFrameAtIndex(0)
152 # Get the SBValue for the static variable 'my_char'.
153 val
= frame
.FindValue("my_char", lldb
.eValueTypeVariableStatic
)
154 self
.DebugSBValue(val
)
156 # If the variable does not have a load address, there's no sense
158 if not val
.GetLocation().startswith("0x"):
161 # OK, let's get the hex location of the variable.
162 location
= int(val
.GetLocation(), 16)
164 # The program logic makes the 'my_char' variable to have memory content as 'x'.
165 # But we want to use the WriteMemory() API to assign 'a' to the
168 # Now use WriteMemory() API to write 'a' into the global variable.
169 error
= lldb
.SBError()
170 result
= process
.WriteMemory(location
, "a", error
)
171 if not error
.Success() or result
!= 1:
172 self
.fail("SBProcess.WriteMemory() failed")
174 # Read from the memory location. This time it should be 'a'.
175 # Due to the typemap magic (see lldb.swig), we pass in 1 to ReadMemory and
176 # expect to get a Python string as the result object!
177 content
= process
.ReadMemory(location
, 1, error
)
178 if not error
.Success():
179 self
.fail("SBProcess.ReadMemory() failed")
181 print("memory content:", content
)
185 "Result from SBProcess.ReadMemory() matches our expected output: 'a'",
190 # Get the SBValue for the global variable 'my_cstring'.
191 val
= frame
.FindValue("my_cstring", lldb
.eValueTypeVariableGlobal
)
192 self
.DebugSBValue(val
)
194 addr
= val
.AddressOf().GetValueAsUnsigned()
196 # Write an empty string to memory
197 bytes_written
= process
.WriteMemoryAsCString(addr
, "", error
)
198 self
.assertEqual(bytes_written
, 0)
199 if not error
.Success():
200 self
.fail("SBProcess.WriteMemoryAsCString() failed")
203 bytes_written
= process
.WriteMemoryAsCString(addr
, message
, error
)
204 self
.assertEqual(bytes_written
, len(message
) + 1)
205 if not error
.Success():
206 self
.fail("SBProcess.WriteMemoryAsCString() failed")
208 cstring
= process
.ReadCStringFromMemory(
209 val
.AddressOf().GetValueAsUnsigned(), 256, error
211 if not error
.Success():
212 self
.fail("SBProcess.ReadCStringFromMemory() failed")
214 self
.assertEqual(cstring
, message
)
216 def test_access_my_int(self
):
217 """Test access 'my_int' using Python SBProcess.GetByteOrder() and other APIs."""
219 exe
= self
.getBuildArtifact("a.out")
221 target
= self
.dbg
.CreateTarget(exe
)
222 self
.assertTrue(target
, VALID_TARGET
)
224 breakpoint
= target
.BreakpointCreateByLocation("main.cpp", self
.line
)
225 self
.assertTrue(breakpoint
, VALID_BREAKPOINT
)
227 # Launch the process, and do not stop at the entry point.
228 process
= target
.LaunchSimple(None, None, self
.get_process_working_directory())
230 thread
= get_stopped_thread(process
, lldb
.eStopReasonBreakpoint
)
232 thread
.IsValid(), "There should be a thread stopped due to breakpoint"
234 frame
= thread
.GetFrameAtIndex(0)
236 # Get the SBValue for the global variable 'my_int'.
237 val
= frame
.FindValue("my_int", lldb
.eValueTypeVariableGlobal
)
238 self
.DebugSBValue(val
)
240 # If the variable does not have a load address, there's no sense
242 if not val
.GetLocation().startswith("0x"):
245 # OK, let's get the hex location of the variable.
246 location
= int(val
.GetLocation(), 16)
248 # Note that the canonical from of the bytearray is little endian.
249 from lldbsuite
.test
.lldbutil
import int_to_bytearray
, bytearray_to_int
251 byteSize
= val
.GetByteSize()
252 bytes
= int_to_bytearray(256, byteSize
)
254 byteOrder
= process
.GetByteOrder()
255 if byteOrder
== lldb
.eByteOrderBig
:
257 elif byteOrder
== lldb
.eByteOrderLittle
:
260 # Neither big endian nor little endian? Return for now.
261 # Add more logic here if we want to handle other types.
264 # The program logic makes the 'my_int' variable to have int type and value of 0.
265 # But we want to use the WriteMemory() API to assign 256 to the
268 # Now use WriteMemory() API to write 256 into the global variable.
269 error
= lldb
.SBError()
270 result
= process
.WriteMemory(location
, bytes
, error
)
271 if not error
.Success() or result
!= byteSize
:
272 self
.fail("SBProcess.WriteMemory() failed")
274 # Make sure that the val we got originally updates itself to notice the
278 "SBProcess.ReadMemory() successfully writes (int)256 to the memory location for 'my_int'",
283 # And for grins, get the SBValue for the global variable 'my_int'
284 # again, to make sure that also tracks the new value:
285 val
= frame
.FindValue("my_int", lldb
.eValueTypeVariableGlobal
)
288 "SBProcess.ReadMemory() successfully writes (int)256 to the memory location for 'my_int'",
293 # Now read the memory content. The bytearray should have (byte)1 as
294 # the second element.
295 content
= process
.ReadMemory(location
, byteSize
, error
)
296 if not error
.Success():
297 self
.fail("SBProcess.ReadMemory() failed")
299 # The bytearray_to_int utility function expects a little endian
301 if byteOrder
== lldb
.eByteOrderBig
:
302 content
= bytearray(content
, "ascii")
305 new_value
= bytearray_to_int(content
, byteSize
)
307 self
.fail("Memory content read from 'my_int' does not match (int)256")
309 # Dump the memory content....
314 def test_remote_launch(self
):
315 """Test SBProcess.RemoteLaunch() API with a process not in eStateConnected, and it should fail."""
317 exe
= self
.getBuildArtifact("a.out")
319 target
= self
.dbg
.CreateTarget(exe
)
320 self
.assertTrue(target
, VALID_TARGET
)
322 # Launch the process, and do not stop at the entry point.
323 process
= target
.LaunchSimple(None, None, self
.get_process_working_directory())
326 print("process state:", state_type_to_str(process
.GetState()))
327 self
.assertTrue(process
.GetState() != lldb
.eStateConnected
)
329 error
= lldb
.SBError()
330 success
= process
.RemoteLaunch(
331 None, None, None, None, None, None, 0, False, error
335 "RemoteLaunch() should fail for process state != eStateConnected",
338 def test_get_num_supported_hardware_watchpoints(self
):
339 """Test SBProcess.GetNumSupportedHardwareWatchpoints() API with a process."""
341 exe
= self
.getBuildArtifact("a.out")
342 self
.runCmd("file " + exe
, CURRENT_EXECUTABLE_SET
)
344 target
= self
.dbg
.CreateTarget(exe
)
345 self
.assertTrue(target
, VALID_TARGET
)
347 breakpoint
= target
.BreakpointCreateByLocation("main.cpp", self
.line
)
348 self
.assertTrue(breakpoint
, VALID_BREAKPOINT
)
350 # Launch the process, and do not stop at the entry point.
351 process
= target
.LaunchSimple(None, None, self
.get_process_working_directory())
353 error
= lldb
.SBError()
354 num
= process
.GetNumSupportedHardwareWatchpoints(error
)
355 if self
.TraceOn() and error
.Success():
356 print("Number of supported hardware watchpoints: %d" % num
)
360 def test_get_process_info(self
):
361 """Test SBProcess::GetProcessInfo() API with a locally launched process."""
363 exe
= self
.getBuildArtifact("a.out")
364 self
.runCmd("file " + exe
, CURRENT_EXECUTABLE_SET
)
366 target
= self
.dbg
.CreateTarget(exe
)
367 self
.assertTrue(target
, VALID_TARGET
)
369 # Launch the process and stop at the entry point.
370 launch_info
= target
.GetLaunchInfo()
371 launch_info
.SetWorkingDirectory(self
.get_process_working_directory())
372 launch_flags
= launch_info
.GetLaunchFlags()
373 launch_flags |
= lldb
.eLaunchFlagStopAtEntry
374 launch_info
.SetLaunchFlags(launch_flags
)
375 error
= lldb
.SBError()
376 process
= target
.Launch(launch_info
, error
)
378 if not error
.Success():
379 self
.fail("Failed to launch process")
381 # Verify basic process info can be retrieved successfully
382 process_info
= process
.GetProcessInfo()
383 self
.assertTrue(process_info
.IsValid())
384 file_spec
= process_info
.GetExecutableFile()
385 self
.assertTrue(file_spec
.IsValid())
386 process_name
= process_info
.GetName()
387 self
.assertIsNotNone(process_name
, "Process has a name")
388 self
.assertGreater(len(process_name
), 0, "Process name isn't blank")
389 self
.assertEqual(file_spec
.GetFilename(), "a.out")
391 process_info
.GetProcessID(),
392 lldb
.LLDB_INVALID_PROCESS_ID
,
393 "Process ID is valid",
395 triple
= process_info
.GetTriple()
396 self
.assertIsNotNone(triple
, "Process has a triple")
398 # Additional process info varies by platform, so just check that
399 # whatever info was retrieved is consistent and nothing blows up.
400 if process_info
.UserIDIsValid():
402 process_info
.GetUserID(), lldb
.UINT32_MAX
, "Process user ID is valid"
406 process_info
.GetUserID(), lldb
.UINT32_MAX
, "Process user ID is invalid"
409 if process_info
.GroupIDIsValid():
411 process_info
.GetGroupID(), lldb
.UINT32_MAX
, "Process group ID is valid"
415 process_info
.GetGroupID(),
417 "Process group ID is invalid",
420 if process_info
.EffectiveUserIDIsValid():
422 process_info
.GetEffectiveUserID(),
424 "Process effective user ID is valid",
428 process_info
.GetEffectiveUserID(),
430 "Process effective user ID is invalid",
433 if process_info
.EffectiveGroupIDIsValid():
435 process_info
.GetEffectiveGroupID(),
437 "Process effective group ID is valid",
441 process_info
.GetEffectiveGroupID(),
443 "Process effective group ID is invalid",
446 process_info
.GetParentProcessID()
448 def test_allocate_deallocate_memory(self
):
449 """Test Python SBProcess.AllocateMemory() and SBProcess.DeallocateMemory() APIs."""
456 ) = lldbutil
.run_to_source_breakpoint(
457 self
, "// Set break point at this line", lldb
.SBFileSpec("main.cpp")
460 # Allocate a block of memory in the target process
461 error
= lldb
.SBError()
462 addr
= process
.AllocateMemory(16384, lldb
.ePermissionsReadable
, error
)
463 if not error
.Success() or addr
== lldb
.LLDB_INVALID_ADDRESS
:
464 self
.fail("SBProcess.AllocateMemory() failed")
466 # Now use WriteMemory() API to write 'a' into the allocated
467 # memory. Note that the debugger can do this even though the
468 # block is not set writable.
469 result
= process
.WriteMemory(addr
, "a", error
)
470 if not error
.Success() or result
!= 1:
471 self
.fail("SBProcess.WriteMemory() failed")
473 # Read from the memory location. This time it should be 'a'.
474 # Due to the typemap magic (see lldb.swig), we pass in 1 to ReadMemory and
475 # expect to get a Python string as the result object!
476 content
= process
.ReadMemory(addr
, 1, error
)
477 if not error
.Success():
478 self
.fail("SBProcess.ReadMemory() failed")
480 print("memory content:", content
)
484 "Result from SBProcess.ReadMemory() matches our expected output: 'a'",
489 # Verify that the process itself can read the allocated memory
490 frame
= main_thread
.GetFrameAtIndex(0)
491 val
= frame
.EvaluateExpression(
492 "test_read(reinterpret_cast<char *>({:#x}))".format(addr
)
496 "Result of test_read() matches expected output 'a'",
501 # Verify that the process cannot write into the block
502 val
= frame
.EvaluateExpression(
503 "test_write(reinterpret_cast<char *>({:#x}), 'b')".format(addr
)
505 if val
.GetError().Success():
507 "test_write() to allocated memory without write permission unexpectedly succeeded"
510 # Deallocate the memory
511 error
= process
.DeallocateMemory(addr
)
512 if not error
.Success():
513 self
.fail("SBProcess.DeallocateMemory() failed")