#!/usr/bin/env python #---------------------------------------------------------------------- # Be sure to add the python path that points to the LLDB shared library. # On MacOSX csh, tcsh: # setenv PYTHONPATH /Developer/Library/PrivateFrameworks/LLDB.framework/Resources/Python # On MacOSX sh, bash: # export PYTHONPATH=/Developer/Library/PrivateFrameworks/LLDB.framework/Resources/Python #---------------------------------------------------------------------- import lldb import os import sys def disassemble_instructions(insts): for i in insts: print(i) def usage(): print("Usage: disasm.py [-n name] executable-image") print(" By default, it breaks at and disassembles the 'main' function.") sys.exit(0) if len(sys.argv) == 2: fname = 'main' exe = sys.argv[1] elif len(sys.argv) == 4: if sys.argv[1] != '-n': usage() else: fname = sys.argv[2] exe = sys.argv[3] else: usage() # 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'" % exe) target = debugger.CreateTargetWithFileAndArch(exe, lldb.LLDB_ARCH_DEFAULT) if target: # If the target is valid set a breakpoint at main main_bp = target.BreakpointCreateByName( fname, target.GetExecutable().GetFilename()) print(main_bp) # Launch the process. Since we specified synchronous mode, we won't return # from this function until we hit the breakpoint at main process = target.LaunchSimple(None, None, os.getcwd()) # Make sure the launch went ok if process: # Print some simple process info state = process.GetState() print(process) if state == lldb.eStateStopped: # Get the first thread thread = process.GetThreadAtIndex(0) if thread: # Print some simple thread info print(thread) # Get the first frame frame = thread.GetFrameAtIndex(0) if frame: # Print some simple frame info print(frame) function = frame.GetFunction() # See if we have debug info (a function) if function: # We do have a function, print some info for the # function print(function) # Now get all instructions for this function and print # them insts = function.GetInstructions(target) disassemble_instructions(insts) else: # See if we have a symbol in the symbol table for where # we stopped symbol = frame.GetSymbol() if symbol: # We do have a symbol, print some info for the # symbol print(symbol) # Now get all instructions for this symbol and # print them insts = symbol.GetInstructions(target) disassemble_instructions(insts) registerList = frame.GetRegisters() print("Frame registers (size of register set = %d):" % registerList.GetSize()) for value in registerList: # print value print("%s (number of children = %d):" % (value.GetName(), value.GetNumChildren())) for child in value: print("Name: ", child.GetName(), " Value: ", child.GetValue()) print("Hit the breakpoint at main, enter to continue and wait for program to exit or 'Ctrl-D'/'quit' to terminate the program") next = sys.stdin.readline() if not next or next.rstrip('\n') == 'quit': print("Terminating the inferior process...") process.Kill() else: # Now continue to the program exit process.Continue() # When we return from the above function we will hopefully be at the # program exit. Print out some process info print(process) elif state == lldb.eStateExited: print("Didn't hit the breakpoint at main, program has exited...") else: print("Unexpected process state: %s, killing process..." % debugger.StateAsCString(state)) process.Kill() lldb.SBDebugger.Terminate()