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