def test_watch_address(self): """Exercise SBTarget.WatchAddress() API to set a watchpoint.""" self.build() exe = self.getBuildArtifact("a.out") # Create a target by the debugger. target = self.dbg.CreateTarget(exe) self.assertTrue(target, VALID_TARGET) # Now create a breakpoint on main.c. breakpoint = target.BreakpointCreateByLocation(self.source, self.line) self.assertTrue(breakpoint and breakpoint.GetNumLocations() == 1, VALID_BREAKPOINT) # Now launch the process, and do not stop at the entry point. process = target.LaunchSimple(None, None, self.get_process_working_directory()) # We should be stopped due to the breakpoint. Get frame #0. process = target.GetProcess() self.assertEqual(process.GetState(), lldb.eStateStopped, PROCESS_STOPPED) thread = lldbutil.get_stopped_thread(process, lldb.eStopReasonBreakpoint) frame0 = thread.GetFrameAtIndex(0) value = frame0.FindValue('g_char_ptr', lldb.eValueTypeVariableGlobal) pointee = value.CreateValueFromAddress( "pointee", value.GetValueAsUnsigned(0), value.GetType().GetPointeeType()) # Watch for write to *g_char_ptr. error = lldb.SBError() watchpoint = target.WatchAddress(value.GetValueAsUnsigned(), 1, False, True, error) self.assertTrue(value and watchpoint, "Successfully found the pointer and set a watchpoint") self.DebugSBValue(value) self.DebugSBValue(pointee) # Hide stdout if not running with '-t' option. if not self.TraceOn(): self.HideStdout() print(watchpoint) # Continue. Expect the program to stop due to the variable being # written to. process.Continue() if (self.TraceOn()): lldbutil.print_stacktraces(process) thread = lldbutil.get_stopped_thread(process, lldb.eStopReasonWatchpoint) self.assertTrue(thread, "The thread stopped due to watchpoint") self.DebugSBValue(value) self.DebugSBValue(pointee) self.expect(lldbutil.print_stacktrace(thread, string_buffer=True), exe=False, substrs=[self.violating_func])
def test_read_memory(self): """Test Python SBProcess.ReadMemory() API.""" 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_char'. val = frame.FindValue("my_char", lldb.eValueTypeVariableGlobal) self.DebugSBValue(val) # Due to the typemap magic (see lldb.swig), we pass in 1 to ReadMemory and # expect to get a Python string as the result object! error = lldb.SBError() self.assertFalse(val.TypeIsPointerType()) content = process.ReadMemory(val.AddressOf().GetValueAsUnsigned(), 1, error) if not error.Success(): self.fail("SBProcess.ReadMemory() failed") if self.TraceOn(): print("memory content:", content) self.expect(content, "Result from SBProcess.ReadMemory() matches our expected output: 'x'", exe=False, startstr = 'x') # Read (char *)my_char_ptr. val = frame.FindValue("my_char_ptr", lldb.eValueTypeVariableGlobal) self.DebugSBValue(val) cstring = process.ReadCStringFromMemory(val.GetValueAsUnsigned(), 256, error) if not error.Success(): self.fail("SBProcess.ReadCStringFromMemory() failed") if self.TraceOn(): print("cstring read is:", cstring) self.expect(cstring, "Result from SBProcess.ReadCStringFromMemory() matches our expected output", exe=False, startstr = 'Does it work?') # Get the SBValue for the global variable 'my_cstring'. val = frame.FindValue("my_cstring", lldb.eValueTypeVariableGlobal) self.DebugSBValue(val) # Due to the typemap magic (see lldb.swig), we pass in 256 to read at most 256 bytes # from the address, and expect to get a Python string as the result object! self.assertFalse(val.TypeIsPointerType()) cstring = process.ReadCStringFromMemory(val.AddressOf().GetValueAsUnsigned(), 256, error) if not error.Success(): self.fail("SBProcess.ReadCStringFromMemory() failed") if self.TraceOn(): print("cstring read is:", cstring) self.expect(cstring, "Result from SBProcess.ReadCStringFromMemory() matches our expected output", exe=False, startstr = 'lldb.SBProcess.ReadCStringFromMemory() works!') # Get the SBValue for the global variable 'my_uint32'. val = frame.FindValue("my_uint32", lldb.eValueTypeVariableGlobal) self.DebugSBValue(val) # Due to the typemap magic (see lldb.swig), we pass in 4 to read 4 bytes # from the address, and expect to get an int as the result! self.assertFalse(val.TypeIsPointerType()) my_uint32 = process.ReadUnsignedFromMemory(val.AddressOf().GetValueAsUnsigned(), 4, error) if not error.Success(): self.fail("SBProcess.ReadCStringFromMemory() failed") if self.TraceOn(): print("uint32 read is:", my_uint32) if my_uint32 != 12345: self.fail("Result from SBProcess.ReadUnsignedFromMemory() does not match our expected output")
def address_breakpoints(self): """Test address breakpoints set with shared library of SBAddress work correctly.""" exe = os.path.join(os.getcwd(), "a.out") # Create a target by the debugger. target = self.dbg.CreateTarget(exe) self.assertTrue(target, VALID_TARGET) # Now create a breakpoint on main.c by name 'c'. breakpoint = target.BreakpointCreateBySourceRegex( "Set a breakpoint here", lldb.SBFileSpec("main.c")) self.assertTrue(breakpoint and breakpoint.GetNumLocations() >= 1, VALID_BREAKPOINT) # Get the breakpoint location from breakpoint after we verified that, # indeed, it has one location. location = breakpoint.GetLocationAtIndex(0) self.assertTrue(location and location.IsEnabled(), VALID_BREAKPOINT_LOCATION) # Next get the address from the location, and create an address breakpoint using # that address: address = location.GetAddress() target.BreakpointDelete(breakpoint.GetID()) breakpoint = target.BreakpointCreateBySBAddress(address) # Disable ASLR. This will allow us to actually test (on platforms that support this flag) # that the breakpoint was able to track the module. launch_info = lldb.SBLaunchInfo(None) flags = launch_info.GetLaunchFlags() flags &= ~lldb.eLaunchFlagDisableASLR launch_info.SetLaunchFlags(flags) error = lldb.SBError() process = target.Launch(launch_info, error) self.assertTrue(process, PROCESS_IS_VALID) # Did we hit our breakpoint? from lldbsuite.test.lldbutil import get_threads_stopped_at_breakpoint threads = get_threads_stopped_at_breakpoint(process, breakpoint) self.assertTrue( len(threads) == 1, "There should be a thread stopped at our breakpoint") # The hit count for the breakpoint should be 1. self.assertTrue(breakpoint.GetHitCount() == 1) process.Kill() # Now re-launch and see that we hit the breakpoint again: launch_info.Clear() launch_info.SetLaunchFlags(flags) process = target.Launch(launch_info, error) self.assertTrue(process, PROCESS_IS_VALID) thread = get_threads_stopped_at_breakpoint(process, breakpoint) self.assertTrue( len(threads) == 1, "There should be a thread stopped at our breakpoint") # The hit count for the breakpoint should now be 2. self.assertTrue(breakpoint.GetHitCount() == 2)
def test_with_run_command(self): """Test the SBData APIs.""" self.build() self.runCmd("file " + self.getBuildArtifact("a.out"), CURRENT_EXECUTABLE_SET) lldbutil.run_break_set_by_file_and_line( self, "main.cpp", self.line, num_expected_locations=1, loc_exact=True) self.runCmd("run", RUN_SUCCEEDED) # The stop reason of the thread should be breakpoint. self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, substrs=['stopped', 'stop reason = breakpoint']) target = self.dbg.GetSelectedTarget() process = target.GetProcess() thread = lldbutil.get_stopped_thread( process, lldb.eStopReasonBreakpoint) self.assertIsNotNone(thread) frame = thread.GetSelectedFrame() if self.TraceOn(): print(frame) foobar = frame.FindVariable('foobar') self.assertTrue(foobar.IsValid()) if self.TraceOn(): print(foobar) data = foobar.GetPointeeData(0, 2) offset = 0 error = lldb.SBError() self.assert_data(data.GetUnsignedInt32, offset, 1) offset += 4 low = data.GetSignedInt16(error, offset) self.assertTrue(error.Success()) offset += 2 high = data.GetSignedInt16(error, offset) self.assertTrue(error.Success()) offset += 2 self.assertTrue( (low == 9 and high == 0) or ( low == 0 and high == 9), 'foo[0].b == 9') self.assertTrue( fabs( data.GetFloat( error, offset) - 3.14) < 1, 'foo[0].c == 3.14') self.assertTrue(error.Success()) offset += 4 self.assert_data(data.GetUnsignedInt32, offset, 8) offset += 4 self.assert_data(data.GetUnsignedInt32, offset, 5) offset += 4 self.runCmd("n") offset = 16 self.assert_data(data.GetUnsignedInt32, offset, 5) data = foobar.GetPointeeData(1, 1) offset = 0 self.assert_data(data.GetSignedInt32, offset, 8) offset += 4 self.assert_data(data.GetSignedInt32, offset, 7) offset += 8 self.assertTrue( data.GetUnsignedInt32( error, offset) == 0, 'do not read beyond end') self.assertTrue(not error.Success()) error.Clear() # clear the error for the next test star_foobar = foobar.Dereference() self.assertTrue(star_foobar.IsValid()) data = star_foobar.GetData() if self.TraceOn(): print(data) offset = 0 self.assert_data(data.GetUnsignedInt32, offset, 1) offset += 4 self.assert_data(data.GetUnsignedInt32, offset, 9) foobar_addr = star_foobar.GetLoadAddress() foobar_addr += 12 # http://llvm.org/bugs/show_bug.cgi?id=11579 # lldb::SBValue::CreateValueFromAddress does not verify SBType::GetPointerType succeeds # This should not crash LLDB. nothing = foobar.CreateValueFromAddress( "nothing", foobar_addr, star_foobar.GetType().GetBasicType( lldb.eBasicTypeInvalid)) new_foobar = foobar.CreateValueFromAddress( "f00", foobar_addr, star_foobar.GetType()) self.assertTrue(new_foobar.IsValid()) if self.TraceOn(): print(new_foobar) data = new_foobar.GetData() if self.TraceOn(): print(data) self.assertTrue(data.uint32[0] == 8, 'then foo[1].a == 8') self.assertTrue(data.uint32[1] == 7, 'then foo[1].b == 7') # exploiting that sizeof(uint32) == sizeof(float) self.assertTrue(fabs(data.float[2] - 3.14) < 1, 'foo[1].c == 3.14') self.runCmd("n") offset = 0 self.assert_data(data.GetUnsignedInt32, offset, 8) offset += 4 self.assert_data(data.GetUnsignedInt32, offset, 7) offset += 4 self.assertTrue( fabs( data.GetFloat( error, offset) - 3.14) < 1, 'foo[1].c == 3.14') self.assertTrue(error.Success()) data = new_foobar.GetData() if self.TraceOn(): print(data) offset = 0 self.assert_data(data.GetUnsignedInt32, offset, 8) offset += 4 self.assert_data(data.GetUnsignedInt32, offset, 7) offset += 4 self.assertTrue( fabs( data.GetFloat( error, offset) - 6.28) < 1, 'foo[1].c == 6.28') self.assertTrue(error.Success()) self.runCmd("n") barfoo = frame.FindVariable('barfoo') data = barfoo.GetData() if self.TraceOn(): print(barfoo) if self.TraceOn(): print(data) offset = 0 self.assert_data(data.GetUnsignedInt32, offset, 1) offset += 4 self.assert_data(data.GetUnsignedInt32, offset, 2) offset += 4 self.assertTrue( fabs( data.GetFloat( error, offset) - 3) < 1, 'barfoo[0].c == 3') self.assertTrue(error.Success()) offset += 4 self.assert_data(data.GetUnsignedInt32, offset, 4) offset += 4 self.assert_data(data.GetUnsignedInt32, offset, 5) offset += 4 self.assertTrue( fabs( data.GetFloat( error, offset) - 6) < 1, 'barfoo[1].c == 6') self.assertTrue(error.Success()) new_object = barfoo.CreateValueFromData( "new_object", data, barfoo.GetType().GetBasicType( lldb.eBasicTypeInt)) if self.TraceOn(): print(new_object) self.assertTrue(new_object.GetValue() == "1", 'new_object == 1') if data.GetByteOrder() == lldb.eByteOrderBig: data.SetData( error, '\0\0\0A', data.GetByteOrder(), data.GetAddressByteSize()) else: data.SetData( error, 'A\0\0\0', data.GetByteOrder(), data.GetAddressByteSize()) self.assertTrue(error.Success()) data2 = lldb.SBData() data2.SetData( error, 'BCD', data.GetByteOrder(), data.GetAddressByteSize()) self.assertTrue(error.Success()) data.Append(data2) if self.TraceOn(): print(data) # this breaks on EBCDIC offset = 0 self.assert_data(data.GetUnsignedInt32, offset, 65) offset += 4 self.assert_data(data.GetUnsignedInt8, offset, 66) offset += 1 self.assert_data(data.GetUnsignedInt8, offset, 67) offset += 1 self.assert_data(data.GetUnsignedInt8, offset, 68) offset += 1 # check the new API calls introduced per LLVM llvm.org/prenhancement request # 11619 (Allow creating SBData values from arrays or primitives in # Python) hello_str = "hello!" data2 = lldb.SBData.CreateDataFromCString( process.GetByteOrder(), process.GetAddressByteSize(), hello_str) self.assertTrue(len(data2.uint8) == len(hello_str)) self.assertTrue(data2.uint8[0] == 104, 'h == 104') self.assertTrue(data2.uint8[1] == 101, 'e == 101') self.assertTrue(data2.uint8[2] == 108, 'l == 108') self.assert_data(data2.GetUnsignedInt8, 3, 108) # l self.assertTrue(data2.uint8[4] == 111, 'o == 111') self.assert_data(data2.GetUnsignedInt8, 5, 33) # ! uint_lists = [[1, 2, 3, 4, 5], [int(i) for i in [1, 2, 3, 4, 5]]] int_lists = [[2, -2], [int(i) for i in [2, -2]]] for l in uint_lists: data2 = lldb.SBData.CreateDataFromUInt64Array( process.GetByteOrder(), process.GetAddressByteSize(), l) self.assert_data(data2.GetUnsignedInt64, 0, 1) self.assert_data(data2.GetUnsignedInt64, 8, 2) self.assert_data(data2.GetUnsignedInt64, 16, 3) self.assert_data(data2.GetUnsignedInt64, 24, 4) self.assert_data(data2.GetUnsignedInt64, 32, 5) self.assertTrue( data2.uint64s == [ 1, 2, 3, 4, 5], 'read_data_helper failure: data2 == [1,2,3,4,5]') for l in int_lists: data2 = lldb.SBData.CreateDataFromSInt32Array( process.GetByteOrder(), process.GetAddressByteSize(), l) self.assertTrue( data2.sint32[ 0:2] == [ 2, -2], 'signed32 data2 = [2,-2]') data2.Append( lldb.SBData.CreateDataFromSInt64Array( process.GetByteOrder(), process.GetAddressByteSize(), int_lists[0])) self.assert_data(data2.GetSignedInt32, 0, 2) self.assert_data(data2.GetSignedInt32, 4, -2) self.assertTrue( data2.sint64[ 1:3] == [ 2, -2], 'signed64 data2 = [2,-2]') for l in int_lists: data2 = lldb.SBData.CreateDataFromSInt64Array( process.GetByteOrder(), process.GetAddressByteSize(), l) self.assert_data(data2.GetSignedInt64, 0, 2) self.assert_data(data2.GetSignedInt64, 8, -2) self.assertTrue( data2.sint64[ 0:2] == [ 2, -2], 'signed64 data2 = [2,-2]') for l in uint_lists: data2 = lldb.SBData.CreateDataFromUInt32Array( process.GetByteOrder(), process.GetAddressByteSize(), l) self.assert_data(data2.GetUnsignedInt32, 0, 1) self.assert_data(data2.GetUnsignedInt32, 4, 2) self.assert_data(data2.GetUnsignedInt32, 8, 3) self.assert_data(data2.GetUnsignedInt32, 12, 4) self.assert_data(data2.GetUnsignedInt32, 16, 5) bool_list = [True, True, False, False, True, False] data2 = lldb.SBData.CreateDataFromSInt32Array( process.GetByteOrder(), process.GetAddressByteSize(), bool_list) self.assertTrue( data2.sint32[ 0:6] == [ 1, 1, 0, 0, 1, 0], 'signed32 data2 = [1, 1, 0, 0, 1, 0]') data2 = lldb.SBData.CreateDataFromUInt32Array( process.GetByteOrder(), process.GetAddressByteSize(), bool_list) self.assertTrue( data2.uint32[ 0:6] == [ 1, 1, 0, 0, 1, 0], 'unsigned32 data2 = [1, 1, 0, 0, 1, 0]') data2 = lldb.SBData.CreateDataFromSInt64Array( process.GetByteOrder(), process.GetAddressByteSize(), bool_list) self.assertTrue( data2.sint64[ 0:6] == [ 1, 1, 0, 0, 1, 0], 'signed64 data2 = [1, 1, 0, 0, 1, 0]') data2 = lldb.SBData.CreateDataFromUInt64Array( process.GetByteOrder(), process.GetAddressByteSize(), bool_list) self.assertTrue( data2.uint64[ 0:6] == [ 1, 1, 0, 0, 1, 0], 'signed64 data2 = [1, 1, 0, 0, 1, 0]') data2 = lldb.SBData.CreateDataFromDoubleArray( process.GetByteOrder(), process.GetAddressByteSize(), [ 3.14, 6.28, 2.71]) self.assertTrue( fabs( data2.GetDouble( error, 0) - 3.14) < 0.5, 'double data2[0] = 3.14') self.assertTrue(error.Success()) self.assertTrue( fabs( data2.GetDouble( error, 8) - 6.28) < 0.5, 'double data2[1] = 6.28') self.assertTrue(error.Success()) self.assertTrue( fabs( data2.GetDouble( error, 16) - 2.71) < 0.5, 'double data2[2] = 2.71') self.assertTrue(error.Success()) data2 = lldb.SBData() data2.SetDataFromCString(hello_str) self.assertTrue(len(data2.uint8) == len(hello_str)) self.assert_data(data2.GetUnsignedInt8, 0, 104) self.assert_data(data2.GetUnsignedInt8, 1, 101) self.assert_data(data2.GetUnsignedInt8, 2, 108) self.assert_data(data2.GetUnsignedInt8, 3, 108) self.assert_data(data2.GetUnsignedInt8, 4, 111) self.assert_data(data2.GetUnsignedInt8, 5, 33) data2.SetDataFromUInt64Array([1, 2, 3, 4, 5]) self.assert_data(data2.GetUnsignedInt64, 0, 1) self.assert_data(data2.GetUnsignedInt64, 8, 2) self.assert_data(data2.GetUnsignedInt64, 16, 3) self.assert_data(data2.GetUnsignedInt64, 24, 4) self.assert_data(data2.GetUnsignedInt64, 32, 5) self.assertTrue( data2.uint64[0] == 1, 'read_data_helper failure: set data2[0] = 1') self.assertTrue( data2.uint64[1] == 2, 'read_data_helper failure: set data2[1] = 2') self.assertTrue( data2.uint64[2] == 3, 'read_data_helper failure: set data2[2] = 3') self.assertTrue( data2.uint64[3] == 4, 'read_data_helper failure: set data2[3] = 4') self.assertTrue( data2.uint64[4] == 5, 'read_data_helper failure: set data2[4] = 5') self.assertTrue( data2.uint64[ 0:2] == [ 1, 2], 'read_data_helper failure: set data2[0:2] = [1,2]') data2.SetDataFromSInt32Array([2, -2]) self.assert_data(data2.GetSignedInt32, 0, 2) self.assert_data(data2.GetSignedInt32, 4, -2) data2.SetDataFromSInt64Array([2, -2]) self.assert_data(data2.GetSignedInt64, 0, 2) self.assert_data(data2.GetSignedInt64, 8, -2) data2.SetDataFromUInt32Array([1, 2, 3, 4, 5]) self.assert_data(data2.GetUnsignedInt32, 0, 1) self.assert_data(data2.GetUnsignedInt32, 4, 2) self.assert_data(data2.GetUnsignedInt32, 8, 3) self.assert_data(data2.GetUnsignedInt32, 12, 4) self.assert_data(data2.GetUnsignedInt32, 16, 5) self.assertTrue( data2.uint32[0] == 1, 'read_data_helper failure: set 32-bit data2[0] = 1') self.assertTrue( data2.uint32[1] == 2, 'read_data_helper failure: set 32-bit data2[1] = 2') self.assertTrue( data2.uint32[2] == 3, 'read_data_helper failure: set 32-bit data2[2] = 3') self.assertTrue( data2.uint32[3] == 4, 'read_data_helper failure: set 32-bit data2[3] = 4') self.assertTrue( data2.uint32[4] == 5, 'read_data_helper failure: set 32-bit data2[4] = 5') data2.SetDataFromDoubleArray([3.14, 6.28, 2.71]) self.assertTrue(fabs(data2.GetDouble(error, 0) - 3.14) < 0.5, 'set double data2[0] = 3.14') self.assertTrue(fabs(data2.GetDouble(error, 8) - 6.28) < 0.5, 'set double data2[1] = 6.28') self.assertTrue(fabs(data2.GetDouble(error, 16) - 2.71) < 0.5, 'set double data2[2] = 2.71') self.assertTrue( fabs( data2.double[0] - 3.14) < 0.5, 'read_data_helper failure: set double data2[0] = 3.14') self.assertTrue( fabs( data2.double[1] - 6.28) < 0.5, 'read_data_helper failure: set double data2[1] = 6.28') self.assertTrue( fabs( data2.double[2] - 2.71) < 0.5, 'read_data_helper failure: set double data2[2] = 2.71')
def timeValueAsDouble(self): error = lldb.SBError() return self.valobj.GetChildMemberWithName( 'm_timeValueAsDouble').GetData().GetDouble(error, 0)
def main(argv): description = '''Debugs a program using the LLDB python API and uses asynchronous broadcast events to watch for process state changes.''' epilog = '''Examples: #---------------------------------------------------------------------- # Run "/bin/ls" with the arguments "-lAF /tmp/", and set a breakpoint # at "malloc" and backtrace and read all registers each time we stop #---------------------------------------------------------------------- % ./process_events.py --breakpoint malloc --stop-command bt --stop-command 'register read' -- /bin/ls -lAF /tmp/ ''' optparse.OptionParser.format_epilog = lambda self, formatter: self.epilog parser = optparse.OptionParser( description=description, prog='process_events', usage='usage: process_events [options] program [arg1 arg2]', epilog=epilog) parser.add_option('-v', '--verbose', action='store_true', dest='verbose', help="Enable verbose logging.", default=False) parser.add_option( '-b', '--breakpoint', action='append', type='string', metavar='BPEXPR', dest='breakpoints', help= 'Breakpoint commands to create after the target has been created, the values will be sent to the "_regexp-break" command which supports breakpoints by name, file:line, and address.' ) parser.add_option( '-a', '--arch', type='string', dest='arch', help='The architecture to use when creating the debug target.', default=None) parser.add_option( '--platform', type='string', metavar='platform', dest='platform', help= 'Specify the platform to use when creating the debug target. Valid values include "localhost", "darwin-kernel", "ios-simulator", "remote-freebsd", "remote-macosx", "remote-ios", "remote-linux".', default=None) parser.add_option( '-l', '--launch-command', action='append', type='string', metavar='CMD', dest='launch_commands', help= 'LLDB command interpreter commands to run once after the process has launched. This option can be specified more than once.', default=[]) parser.add_option( '-s', '--stop-command', action='append', type='string', metavar='CMD', dest='stop_commands', help= 'LLDB command interpreter commands to run each time the process stops. This option can be specified more than once.', default=[]) parser.add_option( '-c', '--crash-command', action='append', type='string', metavar='CMD', dest='crash_commands', help= 'LLDB command interpreter commands to run in case the process crashes. This option can be specified more than once.', default=[]) parser.add_option( '-x', '--exit-command', action='append', type='string', metavar='CMD', dest='exit_commands', help= 'LLDB command interpreter commands to run once after the process has exited. This option can be specified more than once.', default=[]) parser.add_option('-T', '--no-threads', action='store_false', dest='show_threads', help="Don't show threads when process stops.", default=True) parser.add_option( '--ignore-errors', action='store_false', dest='stop_on_error', help= "Don't stop executing LLDB commands if the command returns an error. This applies to all of the LLDB command interpreter commands that get run for launch, stop, crash and exit.", default=True) parser.add_option( '-n', '--run-count', type='int', dest='run_count', metavar='N', help='How many times to run the process in case the process exits.', default=1) parser.add_option( '-t', '--event-timeout', type='int', dest='event_timeout', metavar='SEC', help= 'Specify the timeout in seconds to wait for process state change events.', default=lldb.UINT32_MAX) parser.add_option( '-e', '--environment', action='append', type='string', metavar='ENV', dest='env_vars', help= 'Environment variables to set in the inferior process when launching a process.' ) parser.add_option( '-d', '--working-dir', type='string', metavar='DIR', dest='working_dir', help='The the current working directory when launching a process.', default=None) parser.add_option('-p', '--attach-pid', type='int', dest='attach_pid', metavar='PID', help='Specify a process to attach to by process ID.', default=-1) parser.add_option('-P', '--attach-name', type='string', dest='attach_name', metavar='PROCESSNAME', help='Specify a process to attach to by name.', default=None) parser.add_option( '-w', '--attach-wait', action='store_true', dest='attach_wait', help= 'Wait for the next process to launch when attaching to a process by name.', default=False) try: (options, args) = parser.parse_args(argv) except: return attach_info = None launch_info = None exe = None if args: exe = args.pop(0) launch_info = lldb.SBLaunchInfo(args) if options.env_vars: launch_info.SetEnvironmentEntries(options.env_vars, True) if options.working_dir: launch_info.SetWorkingDirectory(options.working_dir) elif options.attach_pid != -1: if options.run_count == 1: attach_info = lldb.SBAttachInfo(options.attach_pid) else: print "error: --run-count can't be used with the --attach-pid option" sys.exit(1) elif not options.attach_name is None: if options.run_count == 1: attach_info = lldb.SBAttachInfo(options.attach_name, options.attach_wait) else: print "error: --run-count can't be used with the --attach-name option" sys.exit(1) else: print 'error: a program path for a program to debug and its arguments are required' sys.exit(1) # Create a new debugger instance debugger = lldb.SBDebugger.Create() debugger.SetAsync(True) command_interpreter = debugger.GetCommandInterpreter() # Create a target from a file and arch if exe: print "Creating a target for '%s'" % exe error = lldb.SBError() target = debugger.CreateTarget(exe, options.arch, options.platform, True, error) if target: # Set any breakpoints that were specified in the args if we are launching. We use the # command line command to take advantage of the shorthand breakpoint creation if launch_info and options.breakpoints: for bp in options.breakpoints: debugger.HandleCommand("_regexp-break %s" % (bp)) run_commands(command_interpreter, ['breakpoint list']) for run_idx in range(options.run_count): # Launch the process. Since we specified synchronous mode, we won't return # from this function until we hit the breakpoint at main error = lldb.SBError() if launch_info: if options.run_count == 1: print 'Launching "%s"...' % (exe) else: print 'Launching "%s"... (launch %u of %u)' % ( exe, run_idx + 1, options.run_count) process = target.Launch(launch_info, error) else: if options.attach_pid != -1: print 'Attaching to process %i...' % (options.attach_pid) else: if options.attach_wait: print 'Waiting for next to process named "%s" to launch...' % ( options.attach_name) else: print 'Attaching to existing process named "%s"...' % ( options.attach_name) process = target.Attach(attach_info, error) # Make sure the launch went ok if process and process.GetProcessID( ) != lldb.LLDB_INVALID_PROCESS_ID: pid = process.GetProcessID() print 'Process is %i' % (pid) if attach_info: # continue process if we attached as we won't get an initial event process.Continue() listener = debugger.GetListener() # sign up for process state change events stop_idx = 0 done = False while not done: event = lldb.SBEvent() if listener.WaitForEvent(options.event_timeout, event): if lldb.SBProcess.EventIsProcessEvent(event): state = lldb.SBProcess.GetStateFromEvent(event) if state == lldb.eStateInvalid: # Not a state event print 'process event = %s' % (event) else: print "process state changed event: %s" % ( lldb.SBDebugger.StateAsCString(state)) if state == lldb.eStateStopped: if stop_idx == 0: if launch_info: print "process %u launched" % (pid) run_commands( command_interpreter, ['breakpoint list']) else: print "attached to process %u" % ( pid) for m in target.modules: print m if options.breakpoints: for bp in options.breakpoints: debugger.HandleCommand( "_regexp-break %s" % (bp)) run_commands( command_interpreter, ['breakpoint list']) run_commands(command_interpreter, options.launch_commands) else: if options.verbose: print "process %u stopped" % (pid) run_commands(command_interpreter, options.stop_commands) stop_idx += 1 print_threads(process, options) print "continuing process %u" % (pid) process.Continue() elif state == lldb.eStateExited: exit_desc = process.GetExitDescription() if exit_desc: print "process %u exited with status %u: %s" % ( pid, process.GetExitStatus(), exit_desc) else: print "process %u exited with status %u" % ( pid, process.GetExitStatus()) run_commands(command_interpreter, options.exit_commands) done = True elif state == lldb.eStateCrashed: print "process %u crashed" % (pid) print_threads(process, options) run_commands(command_interpreter, options.crash_commands) done = True elif state == lldb.eStateDetached: print "process %u detached" % (pid) done = True elif state == lldb.eStateRunning: # process is running, don't say anything, we will always get one of these after resuming if options.verbose: print "process %u resumed" % (pid) elif state == lldb.eStateUnloaded: print "process %u unloaded, this shouldn't happen" % ( pid) done = True elif state == lldb.eStateConnected: print "process connected" elif state == lldb.eStateAttaching: print "process attaching" elif state == lldb.eStateLaunching: print "process launching" else: print 'event = %s' % (event) else: # timeout waiting for an event print "no process event for %u seconds, killing the process..." % ( options.event_timeout) done = True # Now that we are done dump the stdout and stderr process_stdout = process.GetSTDOUT(1024) if process_stdout: print "Process STDOUT:\n%s" % (process_stdout) while process_stdout: process_stdout = process.GetSTDOUT(1024) print process_stdout process_stderr = process.GetSTDERR(1024) if process_stderr: print "Process STDERR:\n%s" % (process_stderr) while process_stderr: process_stderr = process.GetSTDERR(1024) print process_stderr process.Kill() # kill the process else: if error: print error else: if launch_info: print 'error: launch failed' else: print 'error: attach failed' lldb.SBDebugger.Terminate()
def change_value_api(self, exe_name): """Exercise some SBValue APIs.""" exe = os.path.join(os.getcwd(), exe_name) # Create a target by the debugger. target = self.dbg.CreateTarget(exe) self.assertTrue(target, VALID_TARGET) # Create the breakpoint inside function 'main'. breakpoint = target.BreakpointCreateByLocation('main.c', self.line) self.assertTrue(breakpoint, VALID_BREAKPOINT) # Create the breakpoint inside the function 'main' check_breakpoint = target.BreakpointCreateByLocation( 'main.c', self.check_line) self.assertTrue(check_breakpoint, VALID_BREAKPOINT) # Create the breakpoint inside function 'main'. end_breakpoint = target.BreakpointCreateByLocation( 'main.c', self.end_line) self.assertTrue(end_breakpoint, VALID_BREAKPOINT) # Now launch the process, and do not stop at entry point. process = target.LaunchSimple(None, None, os.getcwd()) self.assertTrue(process, PROCESS_IS_VALID) # Get Frame #0. self.assertTrue(process.GetState() == lldb.eStateStopped) thread = lldbutil.get_stopped_thread(process, lldb.eStopReasonBreakpoint) self.assertTrue( thread.IsValid(), "There should be a thread stopped due to breakpoint condition") frame0 = thread.GetFrameAtIndex(0) self.assertTrue(frame0.IsValid(), "Got a valid frame.") # Get the val variable and change it: error = lldb.SBError() val_value = frame0.FindVariable("val") self.assertTrue(val_value.IsValid(), "Got the SBValue for val") actual_value = val_value.GetValueAsSigned(error, 0) self.assertTrue(error.Success(), "Got a value from val") self.assertTrue(actual_value == 100, "Got the right value from val") result = val_value.SetValueFromCString("12345") self.assertTrue(result, "Setting val returned True.") actual_value = val_value.GetValueAsSigned(error, 0) self.assertTrue(error.Success(), "Got a changed value from val") self.assertTrue(actual_value == 12345, "Got the right changed value from val") # Now check that we can set a structure element: mine_value = frame0.FindVariable("mine") self.assertTrue(mine_value.IsValid(), "Got the SBValue for mine") mine_second_value = mine_value.GetChildMemberWithName("second_val") self.assertTrue(mine_second_value.IsValid(), "Got second_val from mine") actual_value = mine_second_value.GetValueAsUnsigned(error, 0) self.assertTrue(error.Success(), "Got an unsigned value for second_val") self.assertTrue(actual_value == 5555) result = mine_second_value.SetValueFromCString("98765") self.assertTrue(result, "Success setting mine.second_value.") actual_value = mine_second_value.GetValueAsSigned(error, 0) self.assertTrue(error.Success(), "Got a changed value from mine.second_val") self.assertTrue(actual_value == 98765, "Got the right changed value from mine.second_val") # Next do the same thing with the pointer version. ptr_value = frame0.FindVariable("ptr") self.assertTrue(ptr_value.IsValid(), "Got the SBValue for ptr") ptr_second_value = ptr_value.GetChildMemberWithName("second_val") self.assertTrue(ptr_second_value.IsValid(), "Got second_val from ptr") actual_value = ptr_second_value.GetValueAsUnsigned(error, 0) self.assertTrue(error.Success(), "Got an unsigned value for ptr->second_val") self.assertTrue(actual_value == 6666) result = ptr_second_value.SetValueFromCString("98765") self.assertTrue(result, "Success setting ptr->second_value.") actual_value = ptr_second_value.GetValueAsSigned(error, 0) self.assertTrue(error.Success(), "Got a changed value from ptr->second_val") self.assertTrue(actual_value == 98765, "Got the right changed value from ptr->second_val") # gcc may set multiple locations for breakpoint breakpoint.SetEnabled(False) # Now continue, grab the stdout and make sure we changed the real values as well... process.Continue() self.assertTrue(process.GetState() == lldb.eStateStopped) thread = lldbutil.get_stopped_thread(process, lldb.eStopReasonBreakpoint) self.assertTrue( thread.IsValid(), "There should be a thread stopped due to breakpoint condition") expected_value = "Val - 12345 Mine - 55, 98765, 55555555. Ptr - 66, 98765, 66666666" stdout = process.GetSTDOUT(1000) self.assertTrue(expected_value in stdout, "STDOUT showed changed values.") # Finally, change the stack pointer to 0, and we should not make it to our end breakpoint. frame0 = thread.GetFrameAtIndex(0) self.assertTrue(frame0.IsValid(), "Second time: got a valid frame.") sp_value = frame0.FindValue("sp", lldb.eValueTypeRegister) self.assertTrue(sp_value.IsValid(), "Got a stack pointer value") result = sp_value.SetValueFromCString("1") self.assertTrue(result, "Setting sp returned true.") actual_value = sp_value.GetValueAsUnsigned(error, 0) self.assertTrue(error.Success(), "Got a changed value for sp") self.assertTrue(actual_value == 1, "Got the right changed value for sp.") # Boundary condition test the SBValue.CreateValueFromExpression() API. # LLDB should not crash! nosuchval = mine_value.CreateValueFromExpression(None, None) process.Continue() self.assertTrue(process.GetState() == lldb.eStateStopped) thread = lldbutil.get_stopped_thread(process, lldb.eStopReasonBreakpoint) self.assertTrue( thread == None, "We should not have managed to hit our second breakpoint with sp == 1" ) process.Kill()
def ivars_in_blocks(self): """Test printing the ivars of the self when captured in blocks""" exe = os.path.join(os.getcwd(), "a.out") target = self.dbg.CreateTarget(exe) self.assertTrue(target, VALID_TARGET) breakpoint = target.BreakpointCreateBySourceRegex( '// Break here inside the block.', self.class_source_file_spec) self.assertTrue(breakpoint, VALID_BREAKPOINT) breakpoint_two = target.BreakpointCreateBySourceRegex( '// Break here inside the class method block.', self.class_source_file_spec) self.assertTrue(breakpoint, VALID_BREAKPOINT) process = target.LaunchSimple(None, None, os.getcwd()) self.assertTrue(process, "Created a process.") self.assertTrue(process.GetState() == lldb.eStateStopped, "Stopped it too.") thread_list = lldbutil.get_threads_stopped_at_breakpoint( process, breakpoint) self.assertTrue(len(thread_list) == 1) thread = thread_list[0] frame = thread.GetFrameAtIndex(0) self.assertTrue(frame, "frame 0 is valid") # First use the FindVariable API to see if we can find the ivar by undecorated name: direct_blocky = frame.GetValueForVariablePath("blocky_ivar") self.assertTrue(direct_blocky, "Found direct access to blocky_ivar.") # Now get it as a member of "self" and make sure the two values are equal: self_var = frame.GetValueForVariablePath("self") self.assertTrue(self_var, "Found self in block.") indirect_blocky = self_var.GetChildMemberWithName("blocky_ivar") self.assertTrue(indirect_blocky, "Found blocky_ivar through self") error = lldb.SBError() direct_value = direct_blocky.GetValueAsSigned(error) self.assertTrue(error.Success(), "Got direct value for blocky_ivar") indirect_value = indirect_blocky.GetValueAsSigned(error) self.assertTrue(error.Success(), "Got indirect value for blocky_ivar") self.assertTrue(direct_value == indirect_value, "Direct and indirect values are equal.") # Now make sure that we can get at the captured ivar through the expression parser. # Doing a little trivial math will force this into the real expression parser: direct_expr = frame.EvaluateExpression("blocky_ivar + 10") self.assertTrue(direct_expr, "Got blocky_ivar through the expression parser") # Again, get the value through self directly and make sure they are the same: indirect_expr = frame.EvaluateExpression("self->blocky_ivar + 10") self.assertTrue( indirect_expr, "Got blocky ivar through expression parser using self.") direct_value = direct_expr.GetValueAsSigned(error) self.assertTrue(error.Success(), "Got value from direct use of expression parser") indirect_value = indirect_expr.GetValueAsSigned(error) self.assertTrue( error.Success(), "Got value from indirect access using the expression parser") self.assertTrue( direct_value == indirect_value, "Direct ivar access and indirect through expression parser produce same value." ) process.Continue() self.assertTrue(process.GetState() == lldb.eStateStopped, "Stopped at the second breakpoint.") thread_list = lldbutil.get_threads_stopped_at_breakpoint( process, breakpoint_two) self.assertTrue(len(thread_list) == 1) thread = thread_list[0] frame = thread.GetFrameAtIndex(0) self.assertTrue(frame, "frame 0 is valid") expr = frame.EvaluateExpression("(ret)") self.assertTrue( expr, "Successfully got a local variable in a block in a class method.") ret_value_signed = expr.GetValueAsSigned(error) print 'ret_value_signed = %i' % (ret_value_signed) self.assertTrue( ret_value_signed == 5, "The local variable in the block was what we expected.")
def do_test(self, use_target_create): self.absent_file = '/nosuch_dir/nosuch_subdir/nosuch_executable' self.a_packet_file = None class MyResponder(MockGDBServerResponder): def __init__(self, testcase): MockGDBServerResponder.__init__(self) self.after_launch = False self.testcase = testcase self.current_thread = 0 def A(self, packet): # This is the main test, we want to see that lldb DID send the # A packet to get debugserver to load the file. # Skip the length and second length: print("Got A packet: {0}".format(packet)) a_arr = packet.split(",") self.testcase.a_packet_file = bytearray.fromhex(a_arr[2]).decode() return "OK" def qXferRead(self, obj, annex, offset, length): if annex == "target.xml": return """<?xml version="1.0"?> <target version="1.0"> <architecture>i386:x86-64</architecture> <feature name="org.gnu.gdb.i386.core"> <reg name="rip" bitsize="64" regnum="0" type="code_ptr" group="general"/> </feature> </target>""", False else: return None, False def qC(self): if not self.after_launch: return "QC0" return "0" def qfThreadInfo(self): if not self.after_launch: return "OK" return "m0" def qsThreadInfo(self): if not self.after_launch: return "OK" return "l" def qLaunchSuccess(self): return "OK" def qProcessInfo(self): return "$pid:10b70;parent-pid:10b20;real-uid:1f6;real-gid:14;effective-uid:1f6;effective-gid:14;cputype:1000007;cpusubtype:8;ptrsize:8;ostype:macosx;vendor:apple;endian:little;" error = lldb.SBError() self.server.responder = MyResponder(self) target = lldb.SBTarget() if (use_target_create): create_cmd = "target create --arch x86_64-apple-macosx --platform remote-macosx --remote-file {0}".format(self.absent_file) self.runCmd(create_cmd) target = self.dbg.GetSelectedTarget() self.assertTrue(target.IsValid(), "Made a valid target") else: target = self.dbg.CreateTarget(None, "x86_64-apple-macosx", "remote-macosx", False, error) self.assertSuccess(error, "Made a valid target") launch_info = target.GetLaunchInfo() if (not use_target_create): launch_info.SetExecutableFile(lldb.SBFileSpec(self.absent_file), True) flags = launch_info.GetLaunchFlags() flags |= lldb.eLaunchFlagStopAtEntry launch_info.SetLaunchFlags(flags) process = self.connect(target) self.assertTrue(process.IsValid(), "Process is valid") # We need to fetch the connected event: lldbutil.expect_state_changes(self, self.dbg.GetListener(), process, [lldb.eStateConnected]) self.server.responder.after_launch = True process = target.Launch(launch_info, error) self.assertSuccess(error, "Successfully launched.") self.assertEqual(process.GetState(), lldb.eStateStopped, "Should be stopped at entry") self.assertIsNotNone(self.a_packet_file, "A packet was sent") self.assertEqual(self.absent_file, self.a_packet_file, "The A packet file was correct")
def do_test(self): """Check that we can examine module globals in the expression parser""" exe_name = "a.out" exe = self.getBuildArtifact(exe_name) # Create the target target = self.dbg.CreateTarget(exe) self.assertTrue(target, VALID_TARGET) # Target variables. This is not actually expected to work, but # also shouldn't crash. g_counter = target.EvaluateExpression("g_counter") self.assertTrue( g_counter.IsValid(), "g_counter returned a valid value object.") # Set the breakpoints outer_bkpt = target.BreakpointCreateBySourceRegex( 'Set top_level breakpoint here', self.main_source_spec) self.assertTrue(outer_bkpt.GetNumLocations() > 0, VALID_BREAKPOINT) function_bkpt = target.BreakpointCreateBySourceRegex( 'Set function breakpoint here', self.main_source_spec) self.assertTrue(function_bkpt.GetNumLocations() > 0, VALID_BREAKPOINT) # Launch the process, and do not stop at the entry point. process = target.LaunchSimple(None, None, os.getcwd()) self.assertTrue(process, PROCESS_IS_VALID) # Frame #0 should be at our breakpoint. threads = lldbutil.get_threads_stopped_at_breakpoint( process, outer_bkpt) self.assertTrue(len(threads) == 1) self.thread = threads[0] # All the variables should be uninitialized at this point. Maybe sure # they look that way: frame = self.thread.frames[0] options = lldb.SBExpressionOptions() options.SetFetchDynamicValue(lldb.eDynamicCanRunTarget) error = lldb.SBError() # Examine the variables before initialization: g_counter = frame.EvaluateExpression("g_counter", options) self.assertTrue( g_counter.IsValid(), "g_counter returned a valid value object.") value = g_counter.GetValueAsSigned(error) self.assertSuccess(error, "Got a value for g_counter") self.assertTrue( value == 0, "g_counter value is the uninitialized one.") foo_var = frame.EvaluateExpression("my_foo", options) self.assertTrue( foo_var.IsValid(), "foo_var returned a valid value object.") value = foo_var.GetValueAsUnsigned(error) self.assertSuccess(error, "foo_var has a value.") self.assertTrue(value == 0, "foo_var is null before initialization.") my_large_dude = frame.EvaluateExpression("my_large_dude", options) self.assertTrue(my_large_dude.IsValid(), "my_large_dude returned a valid value object.") value = my_large_dude.GetValue() self.assertSuccess(error, "Got a value for my_large_dude") self.assertTrue( value is None, "my_large_dude value is the uninitialized one.") # Now proceed to the breakpoint in our main function, make sure we can # still read these variables and they now have the right values. threads = lldbutil.continue_to_breakpoint(process, function_bkpt) self.assertTrue(len(threads) == 1) self.thread = threads[0] # Examine the variables before initialization: g_counter = frame.EvaluateExpression("g_counter", options) self.assertTrue( g_counter.IsValid(), "g_counter returned a valid value object.") value = g_counter.GetValueAsSigned(error) self.assertSuccess(error, "Got a value for g_counter") self.assertTrue(value == 2, "g_counter value should be 2.") foo_var = frame.EvaluateExpression("my_foo", options) self.assertTrue( foo_var.IsValid(), "foo_var returned a valid value object.") foo_var_x = foo_var.GetChildMemberWithName("x") self.assertTrue(foo_var_x.IsValid(), "Got value object for foo_var.x") value = foo_var_x.GetValueAsUnsigned(error) self.assertSuccess(error, "foo_var.x has a value.") self.assertTrue(value == 1, "foo_var is null before initialization.") my_large_dude = frame.EvaluateExpression("my_large_dude", options) self.assertTrue(my_large_dude.IsValid(), "my_large_dude returned a valid value object.") my_large_dude_y = my_large_dude.GetChildMemberWithName("y") self.assertTrue( my_large_dude_y.IsValid(), "Got value object for my_large_dude.y") value = my_large_dude_y.GetValueAsUnsigned(error) self.assertSuccess(error, "Got a value for my_large_dude.y") self.assertTrue( value == 20, "my_large_dude value is the uninitialized one.")
def test_watch_iter(self): """Exercise SBTarget.watchpoint_iter() API to iterate on the available watchpoints.""" self.build() exe = self.getBuildArtifact("a.out") # Create a target by the debugger. target = self.dbg.CreateTarget(exe) self.assertTrue(target, VALID_TARGET) # Create a breakpoint on main.c in order to set our watchpoint later. breakpoint = target.BreakpointCreateByLocation(self.source, self.line) self.assertTrue(breakpoint and breakpoint.GetNumLocations() == 1, VALID_BREAKPOINT) # Now launch the process, and do not stop at the entry point. process = target.LaunchSimple(None, None, self.get_process_working_directory()) # We should be stopped due to the breakpoint. Get frame #0. process = target.GetProcess() self.assertTrue(process.GetState() == lldb.eStateStopped, PROCESS_STOPPED) thread = lldbutil.get_stopped_thread(process, lldb.eStopReasonBreakpoint) frame0 = thread.GetFrameAtIndex(0) # Watch 'global' for read and write. value = frame0.FindValue('global', lldb.eValueTypeVariableGlobal) error = lldb.SBError() watchpoint = value.Watch(True, False, True, error) self.assertTrue( value and watchpoint, "Successfully found the variable and set a watchpoint") self.DebugSBValue(value) # Hide stdout if not running with '-t' option. if not self.TraceOn(): self.HideStdout() # There should be only 1 watchpoint location under the target. self.assertTrue(target.GetNumWatchpoints() == 1) self.assertTrue(watchpoint.IsEnabled()) watch_id = watchpoint.GetID() self.assertTrue(watch_id != 0) # Continue. Expect the program to stop due to the variable being # written to. process.Continue() # Hide stdout if not running with '-t' option. if not self.TraceOn(): self.HideStdout() # Print the stack traces. lldbutil.print_stacktraces(process) thread = lldbutil.get_stopped_thread(process, lldb.eStopReasonWatchpoint) self.assertTrue(thread, "The thread stopped due to watchpoint") self.DebugSBValue(value) # We currently only support hardware watchpoint. Verify that we have a # meaningful hardware index at this point. Exercise the printed repr of # SBWatchpointLocation. print(watchpoint) if not self.affected_by_radar_34564183(): self.assertTrue(watchpoint.GetHardwareIndex() != -1) # SBWatchpoint.GetDescription() takes a description level arg. print(lldbutil.get_description(watchpoint, lldb.eDescriptionLevelFull)) # Now disable the 'rw' watchpoint. The program won't stop when it reads # 'global' next. watchpoint.SetEnabled(False) self.assertTrue(watchpoint.GetHardwareIndex() == -1) self.assertFalse(watchpoint.IsEnabled()) # Continue. The program does not stop again when the variable is being # read from because the watchpoint location has been disabled. process.Continue() # At this point, the inferior process should have exited. self.assertTrue(process.GetState() == lldb.eStateExited, PROCESS_EXITED) # Verify some vital statistics and exercise the iterator API. for watchpoint in target.watchpoint_iter(): self.assertTrue(watchpoint) self.assertTrue(watchpoint.GetWatchSize() == 4) self.assertTrue(watchpoint.GetHitCount() == 1) print(watchpoint)
def expr_syscall(self): exe = self.getBuildArtifact("a.out") # Create a target by the debugger. target = self.dbg.CreateTarget(exe) self.assertTrue(target, VALID_TARGET) listener = lldb.SBListener("my listener") # launch the inferior and don't wait for it to stop self.dbg.SetAsync(True) error = lldb.SBError() flags = target.GetLaunchInfo().GetLaunchFlags() process = target.Launch( listener, None, # argv None, # envp None, # stdin_path None, # stdout_path None, # stderr_path None, # working directory flags, # launch flags False, # Stop at entry error) # error self.assertTrue(process and process.IsValid(), PROCESS_IS_VALID) event = lldb.SBEvent() # Give the child enough time to reach the syscall, # while clearing out all the pending events. # The last WaitForEvent call will time out after 2 seconds. while listener.WaitForEvent(2, event): pass # now the process should be running (blocked in the syscall) self.assertEqual(process.GetState(), lldb.eStateRunning, "Process is running") # send the process a signal process.SendAsyncInterrupt() while listener.WaitForEvent(2, event): pass # as a result the process should stop # in all likelihood we have stopped in the middle of the sleep() # syscall self.assertEqual(process.GetState(), lldb.eStateStopped, PROCESS_STOPPED) thread = process.GetSelectedThread() # try evaluating a couple of expressions in this state self.expect_expr("release_flag = 1", result_value="1") self.expect_expr("(int)getpid()", result_value=str(process.GetProcessID())) # and run the process to completion process.Continue() # process all events while listener.WaitForEvent(10, event): new_state = lldb.SBProcess.GetStateFromEvent(event) if new_state == lldb.eStateExited: break self.assertEqual(process.GetState(), lldb.eStateExited) self.assertEqual(process.GetExitStatus(), 0)
def _GetValueAsUnsigned(self): serr = lldb.SBError() retval = self._sbval19k84obscure747.GetValueAsUnsigned(serr) if serr.success: return retval raise ValueError("Failed to read unsigned data. "+ str(self._sbval19k84obscure747) +"(type =" + str(self._sbval19k84obscure747_type) + ") Error description: " + serr.GetCString())
print("Target executable is '%s'." % target_path) print("Current working directory is '%s'" % os.getcwd()) # Start the timeout watchdog start_watchdog() # Create a new debugger instance debugger = lldb.SBDebugger.Create() # When we step or continue, don't return from the function until the process # stops. We do this by setting the async mode to false. debugger.SetAsync(False) # Create a target from a file and arch print("Creating a target for '%s'" % target_path) target_error = lldb.SBError() target = debugger.CreateTarget(target_path, None, None, True, target_error) if not target: print("Could not create debugging target '" + target_path + "': " + str(target_error) + ". Aborting.", file=sys.stderr) sys.exit(1) # Register the breakpoint callback for every breakpoint start_breakpoint_listener(target) command_interpreter = debugger.GetCommandInterpreter() try: script_file = open(script_path, 'r')
def test_get_process_info(self): """Test SBProcess::GetProcessInfo() API with a locally launched process.""" self.build() exe = self.getBuildArtifact("a.out") self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) target = self.dbg.CreateTarget(exe) self.assertTrue(target, VALID_TARGET) # Launch the process and stop at the entry point. launch_info = lldb.SBLaunchInfo(None) launch_info.SetWorkingDirectory(self.get_process_working_directory()) launch_flags = launch_info.GetLaunchFlags() launch_flags |= lldb.eLaunchFlagStopAtEntry launch_info.SetLaunchFlags(launch_flags) error = lldb.SBError() process = target.Launch(launch_info, error) if not error.Success(): self.fail("Failed to launch process") # Verify basic process info can be retrieved successfully process_info = process.GetProcessInfo() self.assertTrue(process_info.IsValid()) file_spec = process_info.GetExecutableFile() self.assertTrue(file_spec.IsValid()) process_name = process_info.GetName() self.assertIsNotNone(process_name, "Process has a name") self.assertGreater(len(process_name), 0, "Process name isn't blank") self.assertEqual(file_spec.GetFilename(), "a.out") self.assertNotEqual(process_info.GetProcessID(), lldb.LLDB_INVALID_PROCESS_ID, "Process ID is valid") # Additional process info varies by platform, so just check that # whatever info was retrieved is consistent and nothing blows up. if process_info.UserIDIsValid(): self.assertNotEqual(process_info.GetUserID(), lldb.UINT32_MAX, "Process user ID is valid") else: self.assertEqual(process_info.GetUserID(), lldb.UINT32_MAX, "Process user ID is invalid") if process_info.GroupIDIsValid(): self.assertNotEqual(process_info.GetGroupID(), lldb.UINT32_MAX, "Process group ID is valid") else: self.assertEqual(process_info.GetGroupID(), lldb.UINT32_MAX, "Process group ID is invalid") if process_info.EffectiveUserIDIsValid(): self.assertNotEqual(process_info.GetEffectiveUserID(), lldb.UINT32_MAX, "Process effective user ID is valid") else: self.assertEqual(process_info.GetEffectiveUserID(), lldb.UINT32_MAX, "Process effective user ID is invalid") if process_info.EffectiveGroupIDIsValid(): self.assertNotEqual(process_info.GetEffectiveGroupID(), lldb.UINT32_MAX, "Process effective group ID is valid") else: self.assertEqual(process_info.GetEffectiveGroupID(), lldb.UINT32_MAX, "Process effective group ID is invalid") process_info.GetParentProcessID()
def memfind(target, options, args, result): num_args = len(args) start_addr = 0 if num_args == 1: if options.size > 0: print_error( "error: --size must be specified if there is no ENDADDR argument", True, result) return start_addr = int(args[0], 0) elif num_args == 2: if options.size != 0: print_error( "error: --size can't be specified with an ENDADDR argument", True, result) return start_addr = int(args[0], 0) end_addr = int(args[1], 0) if start_addr >= end_addr: print_error( "error: inavlid memory range [%#x - %#x)" % (start_addr, end_addr), True, result) return options.size = end_addr - start_addr else: print_error("error: memfind takes 1 or 2 arguments", True, result) return if not options.data: print('error: no data specified to search for', file=result) return if not target: print('error: invalid target', file=result) return process = target.process if not process: print('error: invalid process', file=result) return error = lldb.SBError() bytes = process.ReadMemory(start_addr, options.size, error) if error.Success(): num_matches = 0 print("Searching memory range [%#x - %#x) for" % (start_addr, end_addr), end=' ', file=result) for byte in options.data: print('%2.2x' % ord(byte), end=' ', file=result) print(file=result) match_index = string.find(bytes, options.data) while match_index != -1: num_matches = num_matches + 1 print('%#x: %#x + %u' % (start_addr + match_index, start_addr, match_index), file=result) match_index = string.find(bytes, options.data, match_index + 1) if num_matches == 0: print("error: no matches found", file=result) else: print('error: %s' % (error.GetCString()), file=result)
def do_return_value(self): """Test getting return values from stepping out.""" exe = os.path.join(os.getcwd(), "a.out") error = lldb.SBError() self.target = self.dbg.CreateTarget(exe) self.assertTrue(self.target, VALID_TARGET) inner_sint_bkpt = self.target.BreakpointCreateByName("inner_sint", exe) self.assertTrue(inner_sint_bkpt, VALID_BREAKPOINT) # Now launch the process, and do not stop at entry point. self.process = self.target.LaunchSimple(None, None, os.getcwd()) self.assertTrue(self.process, PROCESS_IS_VALID) # The stop reason of the thread should be breakpoint. self.assertTrue(self.process.GetState() == lldb.eStateStopped, STOPPED_DUE_TO_BREAKPOINT) # Now finish, and make sure the return value is correct. thread = lldbutil.get_stopped_thread(self.process, lldb.eStopReasonBreakpoint) # inner_sint returns the variable value, so capture that here: in_int = thread.GetFrameAtIndex(0).FindVariable( "value").GetValueAsSigned(error) self.assertTrue(error.Success()) thread.StepOut() self.assertTrue(self.process.GetState() == lldb.eStateStopped) self.assertTrue(thread.GetStopReason() == lldb.eStopReasonPlanComplete) frame = thread.GetFrameAtIndex(0) fun_name = frame.GetFunctionName() self.assertTrue(fun_name == "outer_sint") return_value = thread.GetStopReturnValue() self.assertTrue(return_value.IsValid()) ret_int = return_value.GetValueAsSigned(error) self.assertTrue(error.Success()) self.assertTrue(in_int == ret_int) # Run again and we will stop in inner_sint the second time outer_sint is called. #Then test stepping out two frames at once: self.process.Continue() thread_list = lldbutil.get_threads_stopped_at_breakpoint( self.process, inner_sint_bkpt) self.assertTrue(len(thread_list) == 1) thread = thread_list[0] # We are done with the inner_sint breakpoint: self.target.BreakpointDelete(inner_sint_bkpt.GetID()) frame = thread.GetFrameAtIndex(1) fun_name = frame.GetFunctionName() self.assertTrue(fun_name == "outer_sint") in_int = frame.FindVariable("value").GetValueAsSigned(error) self.assertTrue(error.Success()) thread.StepOutOfFrame(frame) self.assertTrue(self.process.GetState() == lldb.eStateStopped) self.assertTrue(thread.GetStopReason() == lldb.eStopReasonPlanComplete) frame = thread.GetFrameAtIndex(0) fun_name = frame.GetFunctionName() self.assertTrue(fun_name == "main") ret_value = thread.GetStopReturnValue() self.assertTrue(return_value.IsValid()) ret_int = ret_value.GetValueAsSigned(error) self.assertTrue(error.Success()) self.assertTrue(2 * in_int == ret_int) # Now try some simple returns that have different types: inner_float_bkpt = self.target.BreakpointCreateByName( "inner_float", exe) self.assertTrue(inner_float_bkpt, VALID_BREAKPOINT) self.process.Continue() thread_list = lldbutil.get_threads_stopped_at_breakpoint( self.process, inner_float_bkpt) self.assertTrue(len(thread_list) == 1) thread = thread_list[0] self.target.BreakpointDelete(inner_float_bkpt.GetID()) frame = thread.GetFrameAtIndex(0) in_value = frame.FindVariable("value") in_float = float(in_value.GetValue()) thread.StepOut() self.assertTrue(self.process.GetState() == lldb.eStateStopped) self.assertTrue(thread.GetStopReason() == lldb.eStopReasonPlanComplete) frame = thread.GetFrameAtIndex(0) fun_name = frame.GetFunctionName() self.assertTrue(fun_name == "outer_float") return_value = thread.GetStopReturnValue() self.assertTrue(return_value.IsValid()) return_float = float(return_value.GetValue()) self.assertTrue(in_float == return_float) self.return_and_test_struct_value("return_one_int") self.return_and_test_struct_value("return_two_int") self.return_and_test_struct_value("return_three_int") self.return_and_test_struct_value("return_four_int") self.return_and_test_struct_value("return_five_int") self.return_and_test_struct_value("return_two_double") self.return_and_test_struct_value("return_one_double_two_float") self.return_and_test_struct_value("return_one_int_one_float_one_int") self.return_and_test_struct_value("return_one_pointer") self.return_and_test_struct_value("return_two_pointer") self.return_and_test_struct_value("return_one_float_one_pointer") self.return_and_test_struct_value("return_one_int_one_pointer") self.return_and_test_struct_value("return_three_short_one_float") self.return_and_test_struct_value("return_one_int_one_double") self.return_and_test_struct_value("return_one_int_one_double_one_int") self.return_and_test_struct_value( "return_one_short_one_double_one_short") self.return_and_test_struct_value("return_one_float_one_int_one_float") self.return_and_test_struct_value("return_two_float") # I am leaving out the packed test until we have a way to tell CLANG # about alignment when reading DWARF for packed types. #self.return_and_test_struct_value ("return_one_int_one_double_packed") self.return_and_test_struct_value("return_one_int_one_long")
def test_setpgid(self): self.build() exe = os.path.join(os.getcwd(), 'a.out') # Use a file as a synchronization point between test and inferior. pid_file_path = lldbutil.append_to_process_working_directory( "pid_file_%d" % (int(time.time()))) self.addTearDownHook( lambda: self.run_platform_command("rm %s" % (pid_file_path))) popen = self.spawnSubprocess(exe, [pid_file_path]) self.addTearDownHook(self.cleanupSubprocesses) max_attempts = 5 for i in range(max_attempts): err, retcode, msg = self.run_platform_command("ls %s" % pid_file_path) if err.Success() and retcode == 0: break else: print(msg) if i < max_attempts: # Exponential backoff! time.sleep(pow(2, i) * 0.30) else: self.fail("Child PID file %s not found even after %d attempts." % (pid_file_path, max_attempts)) err, retcode, pid = self.run_platform_command("cat %s" % (pid_file_path)) self.assertTrue( err.Success() and retcode == 0, "Failed to read file %s: %s, retcode: %d" % (pid_file_path, err.GetCString(), retcode)) # make sure we cleanup the forked child also def cleanupChild(): if lldb.remote_platform: lldb.remote_platform.Kill(int(pid)) else: if os.path.exists("/proc/" + pid): os.kill(int(pid), signal.SIGKILL) self.addTearDownHook(cleanupChild) # Create a target by the debugger. target = self.dbg.CreateTarget(exe) self.assertTrue(target, VALID_TARGET) listener = lldb.SBListener("my.attach.listener") error = lldb.SBError() process = target.AttachToProcessWithID(listener, int(pid), error) self.assertTrue(error.Success() and process, PROCESS_IS_VALID) # set a breakpoint just before the setpgid() call lldbutil.run_break_set_by_file_and_line(self, 'main.c', self.line, num_expected_locations=-1) thread = process.GetSelectedThread() # release the child from its loop value = thread.GetSelectedFrame().EvaluateExpression( "release_child_flag = 1") self.assertTrue(value.IsValid() and value.GetValueAsUnsigned(0) == 1) process.Continue() # make sure the child's process group id is different from its pid value = thread.GetSelectedFrame().EvaluateExpression("(int)getpgid(0)") self.assertTrue(value.IsValid()) self.assertNotEqual(value.GetValueAsUnsigned(0), int(pid)) # step over the setpgid() call thread.StepOver() self.assertEqual(thread.GetStopReason(), lldb.eStopReasonPlanComplete) # verify that the process group has been set correctly # this also checks that we are still in full control of the child value = thread.GetSelectedFrame().EvaluateExpression("(int)getpgid(0)") self.assertTrue(value.IsValid()) self.assertEqual(value.GetValueAsUnsigned(0), int(pid)) # run to completion process.Continue() self.assertEqual(process.GetState(), lldb.eStateExited)
def main(argv): description = '''Debugs a program using the LLDB python API and does crash analysis on stop events''' epilog = '''Examples: % ./exploitaben.py -- /path/to/app -exampleflag -otherflag file_that_causes.crash ''' optparse.OptionParser.format_epilog = lambda self, formatter: self.epilog parser = optparse.OptionParser( description=description, prog='process_events', usage='usage: process_events [options] program [arg1 arg2]', epilog=epilog) parser.add_option('-v', '--verbose', action='store_true', dest='verbose', help="Enable verbose logging.", default=False) parser.add_option( '-b', '--breakpoint', action='append', type='string', metavar='BPEXPR', dest='breakpoints', help= 'Breakpoint commands to create after the target has been created, the values will be sent to the "_regexp-break" command which supports breakpoints by name, file:line, and address.' ) parser.add_option( '-c', '--crash-command', action='append', type='string', metavar='CMD', dest='crash_commands', help= 'LLDB command interpreter commands to run in case the process crashes. This option can be specified more than once.', default=[]) parser.add_option( '-x', '--exit-command', action='append', type='string', metavar='CMD', dest='exit_commands', help= 'LLDB command interpreter commands to run once after the process has exited. This option can be specified more than once.', default=[]) parser.add_option( '--ignore-errors', action='store_false', dest='stop_on_error', help= "Don't stop executing LLDB commands if the command returns an error. This applies to all of the LLDB command interpreter commands that get run for launch, stop, crash and exit.", default=True) parser.add_option( '-t', '--event-timeout', type='int', dest='event_timeout', metavar='SEC', help= 'Specify the timeout in seconds to wait for process state change events.', default=lldb.UINT32_MAX) parser.add_option( '-e', '--environment', action='append', type='string', metavar='ENV', dest='env_vars', help= 'Environment variables to set in the inferior process when launching a process.' ) parser.add_option( '-d', '--working-dir', type='string', metavar='DIR', dest='working_dir', help='The the current working directory when launching a process.', default=None) parser.add_option('-p', '--attach-pid', type='int', dest='attach_pid', metavar='PID', help='Specify a process to attach to by process ID.', default=-1) parser.add_option('-P', '--attach-name', type='string', dest='attach_name', metavar='PROCESSNAME', help='Specify a process to attach to by name.', default=None) parser.add_option( '-w', '--attach-wait', action='store_true', dest='attach_wait', help= 'Wait for the next process to launch when attaching to a process by name.', default=False) parser.add_option( '-O', '--show-output', action='store_true', dest='show_output', help='Print the captured stdout/stderr from the target at exit.', default=False) parser.add_option('-N', '--no-color', action='store_true', dest='no_color', help='Print the output without color encoding', default=False) try: (options, args) = parser.parse_args(argv) except: return options.run_count = 1 # I used a closure because we need to wait until options have been parsed def debug(str): if options.verbose: print str attach_info = None launch_info = None exe = None if args: exe = args.pop(0) launch_info = lldb.SBLaunchInfo(args) if options.env_vars: launch_info.SetEnvironmentEntries(options.env_vars, True) if options.working_dir: launch_info.SetWorkingDirectory(options.working_dir) elif options.attach_pid != -1: if options.run_count == 1: attach_info = lldb.SBAttachInfo(options.attach_pid) else: print "error: --run-count can't be used with the --attach-pid option" sys.exit(1) elif options.attach_name is not None: attach_info = lldb.SBAttachInfo(options.attach_name, options.attach_wait) if options.attach_wait: waiting = True else: print 'error: a program path for a program to debug and its arguments are required' sys.exit(1) # Create a new debugger instance debugger = lldb.SBDebugger.Create() debugger.SetAsync(True) command_interpreter = debugger.GetCommandInterpreter() # Create a target from a file and arch if exe: debug("Creating a target for '%s'" % exe) error = lldb.SBError() target = debugger.CreateTarget(exe, None, None, True, error) if target: # Set any breakpoints that were specified in the args if we are launching. We use the # command line command to take advantage of the shorthand breakpoint creation if launch_info and options.breakpoints: for bp in options.breakpoints: debugger.HandleCommand("_regexp-break %s" % (bp)) run_commands(command_interpreter, ['breakpoint list'], options) for run_idx in range(options.run_count): # Launch the process. Since we specified synchronous mode, we won't return # from this function until we hit the breakpoint at main error = lldb.SBError() if launch_info: if options.run_count == 1: debug('Launching "%s"...' % (exe)) else: debug('Launching "%s"... (launch %u of %u)' % (exe, run_idx + 1, options.run_count)) process = target.Launch(launch_info, error) else: if options.attach_pid != -1: debug('Attaching to process %i...' % (options.attach_pid)) else: if options.attach_wait: debug( 'Waiting for next to process named "%s" to launch...' % (options.attach_name)) else: debug('Attaching to existing process named "%s"...' % (options.attach_name)) process = target.Attach(attach_info, error) # Make sure the launch went ok if process and options.attach_wait or process.GetProcessID( ) != lldb.LLDB_INVALID_PROCESS_ID: pid = process.GetProcessID() listener = debugger.GetListener() # sign up for process state change events done = False # moved this outside the main event loop so we re-use one C++ # object. Saves a lot of __init__ calls. event = lldb.SBEvent() while not done: if listener.WaitForEvent(options.event_timeout, event): if lldb.SBProcess.EventIsProcessEvent(event): state = lldb.SBProcess.GetStateFromEvent(event) if state == lldb.eStateInvalid: # Not a state event debug('process event = %s' % (event)) else: # don't call StateAsCString in the critical path! # debug("process state changed event: %s" % (lldb.SBDebugger.StateAsCString(state))) if state == lldb.eStateStopped: debug("process %u stopped" % (pid)) # handle initial stop event after attach ( including attach_wait ) if options.attach_name: debug("Attached to {}!".format( options.attach_name)) # clobber the attach_name option to save using a scratch variable ;) options.attach_name = False process.Continue() continue # OK, now it's a 'real' stop. # skip ahead to the first faulting thread. Not perfect, but better # than nothing. # TODO: Handle cases where multiple threads have a StopReason # ( need to find one first ) for thread in process: if thread.GetStopReason( ) != lldb.eStopReasonNone: process.SetSelectedThread(thread) break if not process.selected_thread.GetFrameAtIndex( 0).IsValid(): print "[ABORT] no valid frames in faulting thread" done = True continue # Adding some parser sugar... print "Stack trace:" run_commands(command_interpreter, ['bt 25'], options) print "Nearby code:" try: run_commands( command_interpreter, ['disass -p -c 10 -b -F intel'], options) except: print "<disassembly failed>" analyzer = lldbx86.Analyzer( target, options.no_color) # will fall back to uncolorized when termcolors is not available registers = analyzer.prettyRegisters() for reg, val in registers.iteritems(): print " %3.3s = %s" % (reg, val) print "Hash: %s" % stack_hash( process.selected_thread) print "ANALYSIS INDICATORS:" print "--------------------" print "StopDesc: %s" % analyzer.getStopDescription( ) print "AvNearNull: %s" % analyzer.isAvNearNull( ) print "AvNearSP: %s" % analyzer.isAvNearSP( ) print "BadBeef: %s" % analyzer.isAvBadBeef( ) print "Access Type: %s" % analyzer.getAccessType( analyzer.getCurrentInstruction()) regs = analyzer.getInsnRegisters( analyzer.getCurrentInstruction()) print "Registers: %s" % ' '.join( map( lambda r: "{}={}".format( r, regs[r]), regs.keys())) print "BlockMov: %s" % analyzer.isBlockMove( ) print "Weird PC: %s" % analyzer.isPcWeird( ) print "Weird SP: %s" % analyzer.isSpWeird( ) print "Suspicious Funcs: %s" % " ".join( analyzer.getSuspiciousStackFuncs()) print "Illegal Insn: %s" % analyzer.isIllegalInstruction( ) print "Huge Stack: %s" % analyzer.isStackHuge( ) done = True elif state == lldb.eStateExited: exit_desc = process.GetExitDescription() if exit_desc: debug( "process %u exited with status %u: %s" % (pid, process.GetExitStatus(), exit_desc)) else: debug( "process %u exited with status %u" % (pid, process.GetExitStatus())) run_commands(command_interpreter, options.exit_commands, options) done = True elif state == lldb.eStateCrashed: # TODO no idea when this happens without first hitting a stop event debug("process %u crashed" % (pid)) print_threads(process, options) run_commands(command_interpreter, options.crash_commands, options) done = True elif state == lldb.eStateDetached: debug("process %u detached" % (pid)) done = True elif state == lldb.eStateRunning: debug("process %u resumed" % (pid)) elif state == lldb.eStateUnloaded: debug( "process %u unloaded, this shouldn't happen" % (pid)) done = True elif state == lldb.eStateConnected: debug("process connected") elif state == lldb.eStateAttaching: debug("process attaching") elif state == lldb.eStateLaunching: debug("process launching") else: debug('event = %s' % (event)) else: # timeout waiting for an event print "no process event for %u seconds, killing the process..." % ( options.event_timeout) done = True if options.show_output: process_stdout = process.GetSTDOUT(1024) if process_stdout: print "Process STDOUT:\n%s" % (process_stdout) while process_stdout: process_stdout = process.GetSTDOUT(1024) print process_stdout process_stderr = process.GetSTDERR(1024) if process_stderr: print "Process STDERR:\n%s" % (process_stderr) while process_stderr: process_stderr = process.GetSTDERR(1024) print process_stderr process.Kill() else: if error: print error else: if launch_info: print 'error: launch failed' else: print 'error: attach failed' lldb.SBDebugger.Terminate()
def test(self): """Test stepping over watchpoints.""" self.build() exe = self.getBuildArtifact("a.out") target = self.dbg.CreateTarget(exe) self.assertTrue(self.target, VALID_TARGET) lldbutil.run_break_set_by_symbol(self, 'main') process = target.LaunchSimple(None, None, self.get_process_working_directory()) self.assertTrue(process.IsValid(), PROCESS_IS_VALID) self.assertTrue(process.GetState() == lldb.eStateStopped, PROCESS_STOPPED) thread = lldbutil.get_stopped_thread(process, lldb.eStopReasonBreakpoint) self.assertTrue(thread.IsValid(), "Failed to get thread.") frame = thread.GetFrameAtIndex(0) self.assertTrue(frame.IsValid(), "Failed to get frame.") read_value = frame.FindValue('g_watch_me_read', lldb.eValueTypeVariableGlobal) self.assertTrue(read_value.IsValid(), "Failed to find read value.") error = lldb.SBError() # resolve_location=True, read=True, write=False read_watchpoint = read_value.Watch(True, True, False, error) self.assertTrue( error.Success(), "Error while setting watchpoint: %s" % error.GetCString()) self.assertTrue(read_watchpoint, "Failed to set read watchpoint.") thread.StepOver() self.assertTrue(thread.GetStopReason() == lldb.eStopReasonWatchpoint, STOPPED_DUE_TO_WATCHPOINT) self.assertTrue(thread.GetStopDescription(20) == 'watchpoint 1') process.Continue() self.assertTrue(process.GetState() == lldb.eStateStopped, PROCESS_STOPPED) self.assertTrue(thread.GetStopDescription(20) == 'step over') self.step_inst_for_watchpoint(1) write_value = frame.FindValue('g_watch_me_write', lldb.eValueTypeVariableGlobal) self.assertTrue(write_value, "Failed to find write value.") # Most of the MIPS boards provide only one H/W watchpoints, and S/W # watchpoints are not supported yet arch = self.getArchitecture() if re.match("^mips", arch): self.runCmd("watchpoint delete 1") # resolve_location=True, read=False, write=True write_watchpoint = write_value.Watch(True, False, True, error) self.assertTrue(write_watchpoint, "Failed to set write watchpoint.") self.assertTrue( error.Success(), "Error while setting watchpoint: %s" % error.GetCString()) thread.StepOver() self.assertTrue(thread.GetStopReason() == lldb.eStopReasonWatchpoint, STOPPED_DUE_TO_WATCHPOINT) self.assertTrue(thread.GetStopDescription(20) == 'watchpoint 2') process.Continue() self.assertTrue(process.GetState() == lldb.eStateStopped, PROCESS_STOPPED) self.assertTrue(thread.GetStopDescription(20) == 'step over') self.step_inst_for_watchpoint(2)
def do_test(self): target = self.createTestTarget() # Now create a breakpoint in main.c at the source matching # "Set a breakpoint here" breakpoint = target.BreakpointCreateBySourceRegex( "Set a breakpoint here", lldb.SBFileSpec("main.c")) self.assertTrue(breakpoint and breakpoint.GetNumLocations() >= 1, VALID_BREAKPOINT) error = lldb.SBError() # This is the launch info. If you want to launch with arguments or # environment variables, add them using SetArguments or # SetEnvironmentEntries launch_info = target.GetLaunchInfo() process = target.Launch(launch_info, error) self.assertTrue(process, PROCESS_IS_VALID) # Did we hit our breakpoint? from lldbsuite.test.lldbutil import get_threads_stopped_at_breakpoint threads = get_threads_stopped_at_breakpoint(process, breakpoint) self.assertEqual(len(threads), 1, "There should be a thread stopped at our breakpoint") # The hit count for the breakpoint should be 1. self.assertEquals(breakpoint.GetHitCount(), 1) frame = threads[0].GetFrameAtIndex(0) command_result = lldb.SBCommandReturnObject() interp = self.dbg.GetCommandInterpreter() # Just get args: result = interp.HandleCommand("frame var -l", command_result) self.assertEqual(result, lldb.eReturnStatusSuccessFinishResult, "frame var -a didn't succeed") output = command_result.GetOutput() self.assertIn("argc", output, "Args didn't find argc") self.assertIn("argv", output, "Args didn't find argv") self.assertNotIn("test_var", output, "Args found a local") self.assertNotIn("g_var", output, "Args found a global") # Just get locals: result = interp.HandleCommand("frame var -a", command_result) self.assertEqual(result, lldb.eReturnStatusSuccessFinishResult, "frame var -a didn't succeed") output = command_result.GetOutput() self.assertNotIn("argc", output, "Locals found argc") self.assertNotIn("argv", output, "Locals found argv") self.assertIn("test_var", output, "Locals didn't find test_var") self.assertNotIn("g_var", output, "Locals found a global") # Get the file statics: result = interp.HandleCommand("frame var -l -a -g", command_result) self.assertEqual(result, lldb.eReturnStatusSuccessFinishResult, "frame var -a didn't succeed") output = command_result.GetOutput() self.assertNotIn("argc", output, "Globals found argc") self.assertNotIn("argv", output, "Globals found argv") self.assertNotIn("test_var", output, "Globals found test_var") self.assertIn("g_var", output, "Globals didn't find g_var")
def test_with_python_api(self): """Test that adding, deleting and modifying watchpoints sends the appropriate events.""" self.build() exe = self.getBuildArtifact("a.out") target = self.dbg.CreateTarget(exe) self.assertTrue(target, VALID_TARGET) self.main_source_spec = lldb.SBFileSpec(self.main_source) break_in_main = target.BreakpointCreateBySourceRegex( '// Put a breakpoint here.', self.main_source_spec) self.assertTrue(break_in_main, VALID_BREAKPOINT) # Now launch the process, and do not stop at entry point. process = target.LaunchSimple(None, None, self.get_process_working_directory()) self.assertTrue(process, PROCESS_IS_VALID) # The stop reason of the thread should be breakpoint. threads = lldbutil.get_threads_stopped_at_breakpoint( process, break_in_main) if len(threads) != 1: self.fail("Failed to stop at first breakpoint in main.") thread = threads[0] frame = thread.GetFrameAtIndex(0) local_var = frame.FindVariable("local_var") self.assertTrue(local_var.IsValid()) self.listener = lldb.SBListener("com.lldb.testsuite_listener") self.target_bcast = target.GetBroadcaster() self.target_bcast.AddListener( self.listener, lldb.SBTarget.eBroadcastBitWatchpointChanged) self.listener.StartListeningForEvents( self.target_bcast, lldb.SBTarget.eBroadcastBitWatchpointChanged) error = lldb.SBError() local_watch = local_var.Watch(True, False, True, error) if not error.Success(): self.fail("Failed to make watchpoint for local_var: %s" % (error.GetCString())) self.GetWatchpointEvent(lldb.eWatchpointEventTypeAdded) # Now change some of the features of this watchpoint and make sure we # get events: local_watch.SetEnabled(False) self.GetWatchpointEvent(lldb.eWatchpointEventTypeDisabled) local_watch.SetEnabled(True) self.GetWatchpointEvent(lldb.eWatchpointEventTypeEnabled) local_watch.SetIgnoreCount(10) self.GetWatchpointEvent(lldb.eWatchpointEventTypeIgnoreChanged) condition = "1 == 2" local_watch.SetCondition(condition) self.GetWatchpointEvent(lldb.eWatchpointEventTypeConditionChanged) self.assertTrue( local_watch.GetCondition() == condition, 'make sure watchpoint condition is "' + condition + '"')
def test_watch_val(self): """Exercise SBValue.Watch() API to set a watchpoint.""" self.build() exe = self.getBuildArtifact("a.out") # Create a target by the debugger. target = self.dbg.CreateTarget(exe) self.assertTrue(target, VALID_TARGET) # Now create a breakpoint on main.c. breakpoint = target.BreakpointCreateByLocation(self.source, self.line) self.assertTrue(breakpoint and breakpoint.GetNumLocations() == 1, VALID_BREAKPOINT) # Now launch the process, and do not stop at the entry point. process = target.LaunchSimple(None, None, self.get_process_working_directory()) # We should be stopped due to the breakpoint. Get frame #0. process = target.GetProcess() self.assertState(process.GetState(), lldb.eStateStopped, PROCESS_STOPPED) thread = lldbutil.get_stopped_thread(process, lldb.eStopReasonBreakpoint) frame0 = thread.GetFrameAtIndex(0) # Watch 'global' for read and write. value = frame0.FindValue('global', lldb.eValueTypeVariableGlobal) error = lldb.SBError() watchpoint = value.Watch(True, True, True, error) self.assertTrue( value and watchpoint, "Successfully found the variable and set a watchpoint") self.DebugSBValue(value) # Hide stdout if not running with '-t' option. if not self.TraceOn(): self.HideStdout() print(watchpoint) # Continue. Expect the program to stop due to the variable being # written to. process.Continue() if (self.TraceOn()): lldbutil.print_stacktraces(process) thread = lldbutil.get_stopped_thread(process, lldb.eStopReasonWatchpoint) self.assertTrue(thread, "The thread stopped due to watchpoint") self.DebugSBValue(value) # Continue. Expect the program to stop due to the variable being read # from. process.Continue() if (self.TraceOn()): lldbutil.print_stacktraces(process) thread = lldbutil.get_stopped_thread(process, lldb.eStopReasonWatchpoint) self.assertTrue(thread, "The thread stopped due to watchpoint") self.DebugSBValue(value) # Continue the process. We don't expect the program to be stopped # again. process.Continue() # At this point, the inferior process should have exited. self.assertEqual(process.GetState(), lldb.eStateExited, PROCESS_EXITED) self.dbg.DeleteTarget(target) self.assertFalse(watchpoint.IsValid())
def display_match_results(result, options, arg_str_description, expr_sbvalue, print_no_matches=True): if expr_sbvalue.error.Success(): if expr_sbvalue.unsigned: match_value = lldb.value(expr_sbvalue) i = 0 match_idx = 0 while 1: print_entry = True match_entry = match_value[i] i += 1 if i >= options.max_matches: result.AppendMessage( 'error: the max number of matches (%u) was reached, use the --max-matches option to get more results' % (options.max_matches)) break malloc_addr = match_entry.addr.sbvalue.unsigned if malloc_addr == 0: break malloc_size = int(match_entry.size) offset = int(match_entry.offset) if options.offset >= 0 and options.offset != offset: print_entry = False else: match_addr = malloc_addr + offset dynamic_value = match_entry.addr.sbvalue.GetDynamicValue( lldb.eDynamicCanRunTarget) description = '[%u] %s: addr = 0x%x' % ( match_idx, arg_str_description, malloc_addr) if offset != 0: description += ' + %u' % (offset) description += ', size = %u' % (malloc_size) derefed_dynamic_value = None if dynamic_value.type.name == 'void *': if options.type == 'pointer' and malloc_size == 4096: error = lldb.SBError() data = bytearray( lldb.process.ReadMemory( malloc_addr, 16, error)) if data == '\xa1\xa1\xa1\xa1AUTORELEASE!': description += ', type = (AUTORELEASE!)' else: derefed_dynamic_value = dynamic_value.deref if derefed_dynamic_value: derefed_dynamic_type = derefed_dynamic_value.type derefed_dynamic_type_size = derefed_dynamic_type.size derefed_dynamic_type_name = derefed_dynamic_type.name description += ', type = %s <%u>' % ( derefed_dynamic_type_name, derefed_dynamic_type_size) if offset < derefed_dynamic_type_size: member_list = list() get_member_types_for_offset( derefed_dynamic_type, offset, member_list) if member_list: member_path = '' for member in member_list: member_name = member.name if member_name: if member_path: member_path += '.' member_path += member_name if member_path: if options.ivar_regex_blacklist: for ivar_regex in options.ivar_regex_blacklist: if ivar_regex.match( member_path): print_entry = False description += ', ivar = %s' % ( member_path) if print_entry: match_idx += 1 result_output = '' if description: result_output += description if options.print_type and derefed_dynamic_value: result_output += '%s' % (derefed_dynamic_value) if options.print_object_description and dynamic_value: desc = dynamic_value.GetObjectDescription() if desc: result_output += ', po=%s' % (desc) if result_output: result.AppendMessage(result_output) if options.memory: cmd_result = lldb.SBCommandReturnObject() memory_command = "memory read -f %s 0x%x 0x%x" % ( options.format, malloc_addr, malloc_addr + malloc_size) lldb.debugger.GetCommandInterpreter().HandleCommand( memory_command, cmd_result) result.AppendMessage(cmd_result.GetOutput()) if options.stack_history: dump_stack_history_entries(result, malloc_addr, 1) elif options.stack: dump_stack_history_entries(result, malloc_addr, 0) return i elif print_no_matches: result.AppendMessage('no matches found for %s' % (arg_str_description)) else: result.AppendMessage(str(expr_sbvalue.error)) return 0
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. new_value = str(bytes) error = lldb.SBError() result = process.WriteMemory(location, new_value, 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") # Use "ascii" as the encoding because each element of 'content' is in the range [0..255]. new_bytes = bytearray(content, "ascii") # The bytearray_to_int utility function expects a little endian bytearray. if byteOrder == lldb.eByteOrderBig: new_bytes.reverse() new_value = bytearray_to_int(new_bytes, 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)
def test_set_watch_ignore_count(self): """Test SBWatchpoint.SetIgnoreCount() API.""" self.build() exe = self.getBuildArtifact("a.out") # Create a target by the debugger. target = self.dbg.CreateTarget(exe) self.assertTrue(target, VALID_TARGET) # Create a breakpoint on main.c in order to set our watchpoint later. breakpoint = target.BreakpointCreateByLocation(self.source, self.line) self.assertTrue(breakpoint and breakpoint.GetNumLocations() == 1, VALID_BREAKPOINT) # Now launch the process, and do not stop at the entry point. process = target.LaunchSimple(None, None, self.get_process_working_directory()) # We should be stopped due to the breakpoint. Get frame #0. process = target.GetProcess() self.assertEqual(process.GetState(), lldb.eStateStopped, PROCESS_STOPPED) thread = lldbutil.get_stopped_thread(process, lldb.eStopReasonBreakpoint) frame0 = thread.GetFrameAtIndex(0) # Watch 'global' for read and write. value = frame0.FindValue('global', lldb.eValueTypeVariableGlobal) error = lldb.SBError() watchpoint = value.Watch(True, True, True, error) self.assertTrue( value and watchpoint, "Successfully found the variable and set a watchpoint") self.DebugSBValue(value) # Hide stdout if not running with '-t' option. if not self.TraceOn(): self.HideStdout() # There should be only 1 watchpoint location under the target. self.assertEqual(target.GetNumWatchpoints(), 1) watchpoint = target.GetWatchpointAtIndex(0) self.assertTrue(watchpoint.IsEnabled()) self.assertEqual(watchpoint.GetIgnoreCount(), 0) watch_id = watchpoint.GetID() self.assertNotEqual(watch_id, 0) print(watchpoint) # Now immediately set the ignore count to 2. When we continue, expect the # inferior to run to its completion without stopping due to watchpoint. watchpoint.SetIgnoreCount(2) print(watchpoint) process.Continue() # At this point, the inferior process should have exited. self.assertEqual(process.GetState(), lldb.eStateExited, PROCESS_EXITED) # Verify some vital statistics. self.assertTrue(watchpoint) self.assertEqual(watchpoint.GetWatchSize(), 4) self.assertEqual(watchpoint.GetHitCount(), 2) print(watchpoint)
target = dbg.CreateTarget(binpath) for module in target.module_iter(): print str(module) for symbol in module: if (symbol.GetType() == lldb.eSymbolTypeCode): if (symbol.GetName()): print("{} {}-{}".format(symbol.GetName(), symbol.GetStartAddress(), symbol.GetEndAddress())) target.BreakpointCreateByName(symbol.GetName(), binpath) print("Start Tracing...") error = lldb.SBError() listener = lldb.SBListener("my listener") event = lldb.SBEvent() stream = lldb.SBStream() process = target.Launch( listener, None, # argv None, # envp None, # stdin_path None, # stdout_path None, # stderr_path None, # working directory 0, # launch flag True, # stop at entry error) # error
def test_with_python(self): """Test getting return values from stepping out.""" self.build() exe = self.getBuildArtifact("a.out") (self.target, self.process, thread, inner_sint_bkpt) = lldbutil.run_to_name_breakpoint(self, "inner_sint", exe_name=exe) error = lldb.SBError() # inner_sint returns the variable value, so capture that here: in_int = thread.GetFrameAtIndex(0).FindVariable( "value").GetValueAsSigned(error) self.assertTrue(error.Success()) thread.StepOut() self.assertTrue(self.process.GetState() == lldb.eStateStopped) self.assertTrue(thread.GetStopReason() == lldb.eStopReasonPlanComplete) frame = thread.GetFrameAtIndex(0) fun_name = frame.GetFunctionName() self.assertTrue(fun_name == "outer_sint(int)") return_value = thread.GetStopReturnValue() self.assertTrue(return_value.IsValid()) ret_int = return_value.GetValueAsSigned(error) self.assertTrue(error.Success()) self.assertTrue(in_int == ret_int) # Run again and we will stop in inner_sint the second time outer_sint is called. # Then test stepping out two frames at once: thread_list = lldbutil.continue_to_breakpoint(self.process, inner_sint_bkpt) self.assertTrue(len(thread_list) == 1) thread = thread_list[0] # We are done with the inner_sint breakpoint: self.target.BreakpointDelete(inner_sint_bkpt.GetID()) frame = thread.GetFrameAtIndex(1) fun_name = frame.GetFunctionName() self.assertTrue(fun_name == "outer_sint(int)") in_int = frame.FindVariable("value").GetValueAsSigned(error) self.assertTrue(error.Success()) thread.StepOutOfFrame(frame) self.assertTrue(self.process.GetState() == lldb.eStateStopped) self.assertTrue(thread.GetStopReason() == lldb.eStopReasonPlanComplete) frame = thread.GetFrameAtIndex(0) fun_name = frame.GetFunctionName() self.assertTrue(fun_name == "main") ret_value = thread.GetStopReturnValue() self.assertTrue(return_value.IsValid()) ret_int = ret_value.GetValueAsSigned(error) self.assertTrue(error.Success()) self.assertTrue(2 * in_int == ret_int) # Now try some simple returns that have different types: inner_float_bkpt = self.target.BreakpointCreateByName( "inner_float(float)", exe) self.assertTrue(inner_float_bkpt, VALID_BREAKPOINT) self.process.Continue() thread_list = lldbutil.get_threads_stopped_at_breakpoint( self.process, inner_float_bkpt) self.assertTrue(len(thread_list) == 1) thread = thread_list[0] self.target.BreakpointDelete(inner_float_bkpt.GetID()) frame = thread.GetFrameAtIndex(0) in_value = frame.FindVariable("value") in_float = float(in_value.GetValue()) thread.StepOut() self.assertTrue(self.process.GetState() == lldb.eStateStopped) self.assertTrue(thread.GetStopReason() == lldb.eStopReasonPlanComplete) frame = thread.GetFrameAtIndex(0) fun_name = frame.GetFunctionName() self.assertTrue(fun_name == "outer_float(float)") #return_value = thread.GetStopReturnValue() #self.assertTrue(return_value.IsValid()) #return_float = float(return_value.GetValue()) #self.assertTrue(in_float == return_float) if not self.affected_by_radar_34562999( ) and not self.affected_by_pr44132(): self.return_and_test_struct_value("return_one_int") self.return_and_test_struct_value("return_two_int") self.return_and_test_struct_value("return_three_int") self.return_and_test_struct_value("return_four_int") if not self.affected_by_pr33042(): self.return_and_test_struct_value("return_five_int") self.return_and_test_struct_value("return_two_double") self.return_and_test_struct_value("return_one_double_two_float") self.return_and_test_struct_value( "return_one_int_one_float_one_int") self.return_and_test_struct_value("return_one_pointer") self.return_and_test_struct_value("return_two_pointer") self.return_and_test_struct_value("return_one_float_one_pointer") self.return_and_test_struct_value("return_one_int_one_pointer") self.return_and_test_struct_value("return_three_short_one_float") self.return_and_test_struct_value("return_one_int_one_double") self.return_and_test_struct_value( "return_one_int_one_double_one_int") self.return_and_test_struct_value( "return_one_short_one_double_one_short") self.return_and_test_struct_value( "return_one_float_one_int_one_float") self.return_and_test_struct_value("return_two_float") # I am leaving out the packed test until we have a way to tell CLANG # about alignment when reading DWARF for packed types. #self.return_and_test_struct_value ("return_one_int_one_double_packed") self.return_and_test_struct_value("return_one_int_one_long")
def test(self): """Test expr + formatters for good interoperability.""" self.build() # This is the function to remove the custom formats in order to have a # clean slate for the next test case. def cleanup(): self.runCmd('type summary clear', check=False) self.runCmd('type synthetic clear', check=False) # Execute the cleanup function during test case tear down. self.addTearDownHook(cleanup) """Test expr + formatters for good interoperability.""" self.runCmd("file " + self.getBuildArtifact("a.out"), CURRENT_EXECUTABLE_SET) lldbutil.run_break_set_by_file_and_line(self, "main.cpp", self.line, loc_exact=True) self.runCmd("run", RUN_SUCCEEDED) self.runCmd("command script import formatters.py") self.runCmd("command script import foosynth.py") if self.TraceOn(): self.runCmd("frame variable foo1 --show-types") self.runCmd("frame variable foo1.b --show-types") self.runCmd("frame variable foo1.b.b_ref --show-types") self.filecheck("expression --show-types -- *(new_foo(47))", __file__, '-check-prefix=EXPR-TYPES-NEW-FOO') # EXPR-TYPES-NEW-FOO: (foo) ${{.*}} = { # EXPR-TYPES-NEW-FOO-NEXT: (int) a = 47 # EXPR-TYPES-NEW-FOO-NEXT: (int *) a_ptr = 0x # EXPR-TYPES-NEW-FOO-NEXT: (bar) b = { # EXPR-TYPES-NEW-FOO-NEXT: (int) i = 94 # EXPR-TYPES-NEW-FOO-NEXT: (int *) i_ptr = 0x # EXPR-TYPES-NEW-FOO-NEXT: (baz) b = { # EXPR-TYPES-NEW-FOO-NEXT: (int) h = 97 # EXPR-TYPES-NEW-FOO-NEXT: (int) k = 99 # EXPR-TYPES-NEW-FOO-NEXT: } # EXPR-TYPES-NEW-FOO-NEXT: (baz &) b_ref = 0x # EXPR-TYPES-NEW-FOO-NEXT: } # EXPR-TYPES-NEW-FOO-NEXT: } self.runCmd("type summary add -F formatters.foo_SummaryProvider3 foo") self.filecheck("expression foo1", __file__, '-check-prefix=EXPR-FOO1opts') # EXPR-FOO1opts: (foo) $ # EXPR-FOO1opts-SAME: a = 12 # EXPR-FOO1opts-SAME: a_ptr = {{[0-9]+}} -> 13 # EXPR-FOO1opts-SAME: i = 24 # EXPR-FOO1opts-SAME: i_ptr = {{[0-9]+}} -> 25 # EXPR-FOO1opts-SAME: b_ref = {{[0-9]+}} # EXPR-FOO1opts-SAME: h = 27 # EXPR-FOO1opts-SAME: k = 29 # EXPR-FOO1opts-SAME: WITH_OPTS self.runCmd("type summary delete foo") self.runCmd("type summary add -F formatters.foo_SummaryProvider foo") self.expect("expression new_int(12)", substrs=['(int *) $', ' = 0x']) self.runCmd( "type summary add -s \"${var%pointer} -> ${*var%decimal}\" \"int *\"" ) self.expect("expression new_int(12)", substrs=['(int *) $', '= 0x', ' -> 12']) self.expect("expression foo1.a_ptr", substrs=['(int *) $', '= 0x', ' -> 13']) self.filecheck("expression foo1", __file__, '-check-prefix=EXPR-FOO1') # EXPR-FOO1: (foo) $ # EXPR-FOO1-SAME: a = 12 # EXPR-FOO1-SAME: a_ptr = {{[0-9]+}} -> 13 # EXPR-FOO1-SAME: i = 24 # EXPR-FOO1-SAME: i_ptr = {{[0-9]+}} -> 25 # EXPR-FOO1-SAME: b_ref = {{[0-9]+}} # EXPR-FOO1-SAME: h = 27 # EXPR-FOO1-SAME: k = 29 self.filecheck("expression --ptr-depth=1 -- new_foo(47)", __file__, '-check-prefix=EXPR-PTR-DEPTH1') # EXPR-PTR-DEPTH1: (foo *) $ # EXPR-PTR-DEPTH1-SAME: a = 47 # EXPR-PTR-DEPTH1-SAME: a_ptr = {{[0-9]+}} -> 48 # EXPR-PTR-DEPTH1-SAME: i = 94 # EXPR-PTR-DEPTH1-SAME: i_ptr = {{[0-9]+}} -> 95 self.filecheck("expression foo2", __file__, '-check-prefix=EXPR-FOO2') # EXPR-FOO2: (foo) $ # EXPR-FOO2-SAME: a = 121 # EXPR-FOO2-SAME: a_ptr = {{[0-9]+}} -> 122 # EXPR-FOO2-SAME: i = 242 # EXPR-FOO2-SAME: i_ptr = {{[0-9]+}} -> 243 # EXPR-FOO2-SAME: h = 245 # EXPR-FOO2-SAME: k = 247 object_name = self.res.GetOutput() object_name = object_name[7:] object_name = object_name[0:object_name.find(' =')] self.filecheck("frame variable foo2", __file__, '-check-prefix=VAR-FOO2') # VAR-FOO2: (foo) foo2 # VAR-FOO2-SAME: a = 121 # VAR-FOO2-SAME: a_ptr = {{[0-9]+}} -> 122 # VAR-FOO2-SAME: i = 242 # VAR-FOO2-SAME: i_ptr = {{[0-9]+}} -> 243 # VAR-FOO2-SAME: h = 245 # VAR-FOO2-SAME: k = 247 # The object is the same as foo2, so use the EXPR-FOO2 checks. self.filecheck("expression $" + object_name, __file__, '-check-prefix=EXPR-FOO2') self.runCmd("type summary delete foo") self.runCmd( "type synthetic add --python-class foosynth.FooSyntheticProvider foo" ) self.expect("expression --show-types -- $" + object_name, substrs=['(foo) $', ' = {', '(int) *i_ptr = 243']) self.runCmd("n") self.runCmd("n") self.runCmd("type synthetic delete foo") self.runCmd("type summary add -F formatters.foo_SummaryProvider foo") self.expect("expression foo2", substrs=[ '(foo) $', 'a = 7777', 'a_ptr = ', ' -> 122', 'i = 242', 'i_ptr = ', ' -> 8888' ]) self.expect("expression $" + object_name + '.a', substrs=['7777']) self.expect("expression *$" + object_name + '.b.i_ptr', substrs=['8888']) self.expect("expression $" + object_name, substrs=[ '(foo) $', 'a = 121', 'a_ptr = ', ' -> 122', 'i = 242', 'i_ptr = ', ' -> 8888', 'h = 245', 'k = 247' ]) self.runCmd("type summary delete foo") self.runCmd( "type synthetic add --python-class foosynth.FooSyntheticProvider foo" ) self.expect("expression --show-types -- $" + object_name, substrs=['(foo) $', ' = {', '(int) *i_ptr = 8888']) self.runCmd("n") self.runCmd("type synthetic delete foo") self.runCmd("type summary add -F formatters.foo_SummaryProvider foo") self.expect("expression $" + object_name, substrs=[ '(foo) $', 'a = 121', 'a_ptr = ', ' -> 122', 'i = 242', 'i_ptr = ', ' -> 8888', 'k = 247' ]) process = self.dbg.GetSelectedTarget().GetProcess() thread = process.GetThreadAtIndex(0) frame = thread.GetSelectedFrame() frozen = frame.EvaluateExpression("$" + object_name + ".a_ptr") a_data = frozen.GetPointeeData() error = lldb.SBError() self.assertTrue( a_data.GetUnsignedInt32(error, 0) == 122, '*a_ptr = 122') ret = line_number("main.cpp", "Done initializing") self.runCmd("thread until " + str(ret)) self.expect("frame variable numbers", substrs=['1', '2', '3', '4', '5']) self.expect("expression numbers", substrs=['1', '2', '3', '4', '5']) frozen = frame.EvaluateExpression("&numbers") a_data = frozen.GetPointeeData(0, 1) self.assertTrue( a_data.GetUnsignedInt32(error, 0) == 1, 'numbers[0] == 1') self.assertTrue( a_data.GetUnsignedInt32(error, 4) == 2, 'numbers[1] == 2') self.assertTrue( a_data.GetUnsignedInt32(error, 8) == 3, 'numbers[2] == 3') self.assertTrue( a_data.GetUnsignedInt32(error, 12) == 4, 'numbers[3] == 4') self.assertTrue( a_data.GetUnsignedInt32(error, 16) == 5, 'numbers[4] == 5') frozen = frame.EvaluateExpression("numbers") a_data = frozen.GetData() self.assertTrue( a_data.GetUnsignedInt32(error, 0) == 1, 'numbers[0] == 1') self.assertTrue( a_data.GetUnsignedInt32(error, 4) == 2, 'numbers[1] == 2') self.assertTrue( a_data.GetUnsignedInt32(error, 8) == 3, 'numbers[2] == 3') self.assertTrue( a_data.GetUnsignedInt32(error, 12) == 4, 'numbers[3] == 4') self.assertTrue( a_data.GetUnsignedInt32(error, 16) == 5, 'numbers[4] == 5')
def simple_backtrace(debugger): target = debugger.GetSelectedTarget() process = target.GetProcess() cur_thread = process.GetSelectedThread() initial_fp = cur_thread.GetFrameAtIndex(0).GetFP() # If the pseudoreg "fp" isn't recognized, on arm hardcode to r7 which is # correct for Darwin programs. if initial_fp == lldb.LLDB_INVALID_ADDRESS and target.triple[0:3] == "arm": for reggroup in cur_thread.GetFrameAtIndex(1).registers: if reggroup.GetName() == "General Purpose Registers": for reg in reggroup: if reg.GetName() == "r7": initial_fp = int(reg.GetValue(), 16) module_list = [] address_list = [cur_thread.GetFrameAtIndex(0).GetPC()] this_module = backtrace_print_frame(target, 0, cur_thread.GetFrameAtIndex(0).GetPC(), initial_fp) print_stack_frame(process, initial_fp) print "" if this_module is not None: module_list.append(this_module) if cur_thread.GetNumFrames() < 2: return [module_list, address_list] cur_fp = process.ReadPointerFromMemory(initial_fp, lldb.SBError()) cur_pc = process.ReadPointerFromMemory( initial_fp + process.GetAddressByteSize(), lldb.SBError()) frame_num = 1 while cur_pc != 0 and cur_fp != 0 and cur_pc != lldb.LLDB_INVALID_ADDRESS and cur_fp != lldb.LLDB_INVALID_ADDRESS: address_list.append(cur_pc) this_module = backtrace_print_frame(target, frame_num, cur_pc, cur_fp) print_stack_frame(process, cur_fp) print "" if this_module is not None: module_list.append(this_module) frame_num = frame_num + 1 next_pc = 0 next_fp = 0 if target.triple[0:6] == "x86_64" or target.triple[ 0:4] == "i386" or target.triple[0:3] == "arm": error = lldb.SBError() next_pc = process.ReadPointerFromMemory( cur_fp + process.GetAddressByteSize(), error) if not error.Success(): next_pc = 0 next_fp = process.ReadPointerFromMemory(cur_fp, error) if not error.Success(): next_fp = 0 # Clear the 0th bit for arm frames - this indicates it is a thumb frame if target.triple[0:3] == "arm" and (next_pc & 1) == 1: next_pc = next_pc & ~1 cur_pc = next_pc cur_fp = next_fp this_module = backtrace_print_frame(target, frame_num, cur_pc, cur_fp) print_stack_frame(process, cur_fp) print "" if this_module is not None: module_list.append(this_module) return [module_list, address_list]