def test_access_my_int(self): """Test access 'my_int' using Python SBProcess.GetByteOrder() and other APIs.""" self.build() exe = self.getBuildArtifact("a.out") target = self.dbg.CreateTarget(exe) self.assertTrue(target, VALID_TARGET) breakpoint = target.BreakpointCreateByLocation("main.cpp", self.line) self.assertTrue(breakpoint, VALID_BREAKPOINT) # Launch the process, and do not stop at the entry point. process = target.LaunchSimple(None, None, self.get_process_working_directory()) thread = get_stopped_thread(process, lldb.eStopReasonBreakpoint) self.assertTrue(thread.IsValid(), "There should be a thread stopped due to breakpoint") frame = thread.GetFrameAtIndex(0) # Get the SBValue for the global variable 'my_int'. val = frame.FindValue("my_int", lldb.eValueTypeVariableGlobal) self.DebugSBValue(val) # If the variable does not have a load address, there's no sense # continuing. if not val.GetLocation().startswith("0x"): return # OK, let's get the hex location of the variable. location = int(val.GetLocation(), 16) # Note that the canonical from of the bytearray is little endian. from lldbsuite.test.lldbutil import int_to_bytearray, bytearray_to_int byteSize = val.GetByteSize() bytes = int_to_bytearray(256, byteSize) byteOrder = process.GetByteOrder() if byteOrder == lldb.eByteOrderBig: bytes.reverse() elif byteOrder == lldb.eByteOrderLittle: pass else: # Neither big endian nor little endian? Return for now. # Add more logic here if we want to handle other types. return # The program logic makes the 'my_int' variable to have int type and value of 0. # But we want to use the WriteMemory() API to assign 256 to the # variable. # Now use WriteMemory() API to write 256 into the global variable. error = lldb.SBError() result = process.WriteMemory(location, bytes, error) if not error.Success() or result != byteSize: self.fail("SBProcess.WriteMemory() failed") # Make sure that the val we got originally updates itself to notice the # change: self.expect( val.GetValue(), "SBProcess.ReadMemory() successfully writes (int)256 to the memory location for 'my_int'", exe=False, startstr='256') # And for grins, get the SBValue for the global variable 'my_int' # again, to make sure that also tracks the new value: val = frame.FindValue("my_int", lldb.eValueTypeVariableGlobal) self.expect( val.GetValue(), "SBProcess.ReadMemory() successfully writes (int)256 to the memory location for 'my_int'", exe=False, startstr='256') # Now read the memory content. The bytearray should have (byte)1 as # the second element. content = process.ReadMemory(location, byteSize, error) if not error.Success(): self.fail("SBProcess.ReadMemory() failed") # The bytearray_to_int utility function expects a little endian # bytearray. if byteOrder == lldb.eByteOrderBig: content = bytearray(content, 'ascii') content.reverse() new_value = bytearray_to_int(content, byteSize) if new_value != 256: self.fail( "Memory content read from 'my_int' does not match (int)256") # Dump the memory content.... if self.TraceOn(): for i in content: print("byte:", i)
def test_access_my_int(self): """Test access 'my_int' using Python SBProcess.GetByteOrder() and other APIs.""" self.build() exe = os.path.join(os.getcwd(), "a.out") target = self.dbg.CreateTarget(exe) self.assertTrue(target, VALID_TARGET) breakpoint = target.BreakpointCreateByLocation("main.cpp", self.line) self.assertTrue(breakpoint, VALID_BREAKPOINT) # Launch the process, and do not stop at the entry point. process = target.LaunchSimple (None, None, self.get_process_working_directory()) thread = get_stopped_thread(process, lldb.eStopReasonBreakpoint) self.assertTrue(thread.IsValid(), "There should be a thread stopped due to breakpoint") frame = thread.GetFrameAtIndex(0) # Get the SBValue for the global variable 'my_int'. val = frame.FindValue("my_int", lldb.eValueTypeVariableGlobal) self.DebugSBValue(val) # If the variable does not have a load address, there's no sense continuing. if not val.GetLocation().startswith("0x"): return # OK, let's get the hex location of the variable. location = int(val.GetLocation(), 16) # Note that the canonical from of the bytearray is little endian. from lldbsuite.test.lldbutil import int_to_bytearray, bytearray_to_int byteSize = val.GetByteSize() bytes = int_to_bytearray(256, byteSize) byteOrder = process.GetByteOrder() if byteOrder == lldb.eByteOrderBig: bytes.reverse() elif byteOrder == lldb.eByteOrderLittle: pass else: # Neither big endian nor little endian? Return for now. # Add more logic here if we want to handle other types. return # The program logic makes the 'my_int' variable to have int type and value of 0. # But we want to use the WriteMemory() API to assign 256 to the variable. # Now use WriteMemory() API to write 256 into the global variable. error = lldb.SBError() result = process.WriteMemory(location, bytes, error) if not error.Success() or result != byteSize: self.fail("SBProcess.WriteMemory() failed") # Make sure that the val we got originally updates itself to notice the change: self.expect(val.GetValue(), "SBProcess.ReadMemory() successfully writes (int)256 to the memory location for 'my_int'", exe=False, startstr = '256') # And for grins, get the SBValue for the global variable 'my_int' again, to make sure that also tracks the new value: val = frame.FindValue("my_int", lldb.eValueTypeVariableGlobal) self.expect(val.GetValue(), "SBProcess.ReadMemory() successfully writes (int)256 to the memory location for 'my_int'", exe=False, startstr = '256') # Now read the memory content. The bytearray should have (byte)1 as the second element. content = process.ReadMemory(location, byteSize, error) if not error.Success(): self.fail("SBProcess.ReadMemory() failed") # The bytearray_to_int utility function expects a little endian bytearray. if byteOrder == lldb.eByteOrderBig: new_bytes.reverse() new_value = bytearray_to_int(content, byteSize) if new_value != 256: self.fail("Memory content read from 'my_int' does not match (int)256") # Dump the memory content.... if self.TraceOn(): for i in new_bytes: print("byte:", i)