1*be691f3bSpatrick#!/usr/bin/env python 2061da546Spatrick 3061da546Spatrick#---------------------------------------------------------------------- 4061da546Spatrick# Be sure to add the python path that points to the LLDB shared library. 5061da546Spatrick# On MacOSX csh, tcsh: 6061da546Spatrick# setenv PYTHONPATH /Developer/Library/PrivateFrameworks/LLDB.framework/Resources/Python 7061da546Spatrick# On MacOSX sh, bash: 8061da546Spatrick# export PYTHONPATH=/Developer/Library/PrivateFrameworks/LLDB.framework/Resources/Python 9061da546Spatrick#---------------------------------------------------------------------- 10061da546Spatrick 11061da546Spatrickimport lldb 12061da546Spatrickimport os 13061da546Spatrickimport sys 14061da546Spatrick 15061da546Spatrick 16061da546Spatrickdef disassemble_instructions(insts): 17061da546Spatrick for i in insts: 18061da546Spatrick print(i) 19061da546Spatrick 20061da546Spatrick 21061da546Spatrickdef usage(): 22061da546Spatrick print("Usage: disasm.py [-n name] executable-image") 23061da546Spatrick print(" By default, it breaks at and disassembles the 'main' function.") 24061da546Spatrick sys.exit(0) 25061da546Spatrick 26061da546Spatrickif len(sys.argv) == 2: 27061da546Spatrick fname = 'main' 28061da546Spatrick exe = sys.argv[1] 29061da546Spatrickelif len(sys.argv) == 4: 30061da546Spatrick if sys.argv[1] != '-n': 31061da546Spatrick usage() 32061da546Spatrick else: 33061da546Spatrick fname = sys.argv[2] 34061da546Spatrick exe = sys.argv[3] 35061da546Spatrickelse: 36061da546Spatrick usage() 37061da546Spatrick 38061da546Spatrick# Create a new debugger instance 39061da546Spatrickdebugger = lldb.SBDebugger.Create() 40061da546Spatrick 41061da546Spatrick# When we step or continue, don't return from the function until the process 42061da546Spatrick# stops. We do this by setting the async mode to false. 43061da546Spatrickdebugger.SetAsync(False) 44061da546Spatrick 45061da546Spatrick# Create a target from a file and arch 46061da546Spatrickprint("Creating a target for '%s'" % exe) 47061da546Spatrick 48061da546Spatricktarget = debugger.CreateTargetWithFileAndArch(exe, lldb.LLDB_ARCH_DEFAULT) 49061da546Spatrick 50061da546Spatrickif target: 51061da546Spatrick # If the target is valid set a breakpoint at main 52061da546Spatrick main_bp = target.BreakpointCreateByName( 53061da546Spatrick fname, target.GetExecutable().GetFilename()) 54061da546Spatrick 55061da546Spatrick print(main_bp) 56061da546Spatrick 57061da546Spatrick # Launch the process. Since we specified synchronous mode, we won't return 58061da546Spatrick # from this function until we hit the breakpoint at main 59061da546Spatrick process = target.LaunchSimple(None, None, os.getcwd()) 60061da546Spatrick 61061da546Spatrick # Make sure the launch went ok 62061da546Spatrick if process: 63061da546Spatrick # Print some simple process info 64061da546Spatrick state = process.GetState() 65061da546Spatrick print(process) 66061da546Spatrick if state == lldb.eStateStopped: 67061da546Spatrick # Get the first thread 68061da546Spatrick thread = process.GetThreadAtIndex(0) 69061da546Spatrick if thread: 70061da546Spatrick # Print some simple thread info 71061da546Spatrick print(thread) 72061da546Spatrick # Get the first frame 73061da546Spatrick frame = thread.GetFrameAtIndex(0) 74061da546Spatrick if frame: 75061da546Spatrick # Print some simple frame info 76061da546Spatrick print(frame) 77061da546Spatrick function = frame.GetFunction() 78061da546Spatrick # See if we have debug info (a function) 79061da546Spatrick if function: 80061da546Spatrick # We do have a function, print some info for the 81061da546Spatrick # function 82061da546Spatrick print(function) 83061da546Spatrick # Now get all instructions for this function and print 84061da546Spatrick # them 85061da546Spatrick insts = function.GetInstructions(target) 86061da546Spatrick disassemble_instructions(insts) 87061da546Spatrick else: 88061da546Spatrick # See if we have a symbol in the symbol table for where 89061da546Spatrick # we stopped 90061da546Spatrick symbol = frame.GetSymbol() 91061da546Spatrick if symbol: 92061da546Spatrick # We do have a symbol, print some info for the 93061da546Spatrick # symbol 94061da546Spatrick print(symbol) 95061da546Spatrick # Now get all instructions for this symbol and 96061da546Spatrick # print them 97061da546Spatrick insts = symbol.GetInstructions(target) 98061da546Spatrick disassemble_instructions(insts) 99061da546Spatrick 100061da546Spatrick registerList = frame.GetRegisters() 101061da546Spatrick print("Frame registers (size of register set = %d):" % registerList.GetSize()) 102061da546Spatrick for value in registerList: 103061da546Spatrick # print value 104061da546Spatrick print("%s (number of children = %d):" % (value.GetName(), value.GetNumChildren())) 105061da546Spatrick for child in value: 106061da546Spatrick print("Name: ", child.GetName(), " Value: ", child.GetValue()) 107061da546Spatrick 108061da546Spatrick print("Hit the breakpoint at main, enter to continue and wait for program to exit or 'Ctrl-D'/'quit' to terminate the program") 109061da546Spatrick next = sys.stdin.readline() 110061da546Spatrick if not next or next.rstrip('\n') == 'quit': 111061da546Spatrick print("Terminating the inferior process...") 112061da546Spatrick process.Kill() 113061da546Spatrick else: 114061da546Spatrick # Now continue to the program exit 115061da546Spatrick process.Continue() 116061da546Spatrick # When we return from the above function we will hopefully be at the 117061da546Spatrick # program exit. Print out some process info 118061da546Spatrick print(process) 119061da546Spatrick elif state == lldb.eStateExited: 120061da546Spatrick print("Didn't hit the breakpoint at main, program has exited...") 121061da546Spatrick else: 122061da546Spatrick print("Unexpected process state: %s, killing process..." % debugger.StateAsCString(state)) 123061da546Spatrick process.Kill() 124061da546Spatrick 125061da546Spatrick 126061da546Spatricklldb.SBDebugger.Terminate() 127