disasm.py   [plain text]


#!/usr/bin/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()