1#!/usr/bin/env python
2
3#----------------------------------------------------------------------
4# Be sure to add the python path that points to the LLDB shared library.
5# On MacOSX csh, tcsh:
6#   setenv PYTHONPATH /Developer/Library/PrivateFrameworks/LLDB.framework/Resources/Python
7# On MacOSX sh, bash:
8#   export PYTHONPATH=/Developer/Library/PrivateFrameworks/LLDB.framework/Resources/Python
9#----------------------------------------------------------------------
10
11import lldb
12import os
13import sys
14
15
16def disassemble_instructions(insts):
17    for i in insts:
18        print(i)
19
20
21def usage():
22    print("Usage: disasm.py [-n name] executable-image")
23    print("       By default, it breaks at and disassembles the 'main' function.")
24    sys.exit(0)
25
26if len(sys.argv) == 2:
27    fname = 'main'
28    exe = sys.argv[1]
29elif len(sys.argv) == 4:
30    if sys.argv[1] != '-n':
31        usage()
32    else:
33        fname = sys.argv[2]
34        exe = sys.argv[3]
35else:
36    usage()
37
38# Create a new debugger instance
39debugger = lldb.SBDebugger.Create()
40
41# When we step or continue, don't return from the function until the process
42# stops. We do this by setting the async mode to false.
43debugger.SetAsync(False)
44
45# Create a target from a file and arch
46print("Creating a target for '%s'" % exe)
47
48target = debugger.CreateTargetWithFileAndArch(exe, lldb.LLDB_ARCH_DEFAULT)
49
50if target:
51    # If the target is valid set a breakpoint at main
52    main_bp = target.BreakpointCreateByName(
53        fname, target.GetExecutable().GetFilename())
54
55    print(main_bp)
56
57    # Launch the process. Since we specified synchronous mode, we won't return
58    # from this function until we hit the breakpoint at main
59    process = target.LaunchSimple(None, None, os.getcwd())
60
61    # Make sure the launch went ok
62    if process:
63        # Print some simple process info
64        state = process.GetState()
65        print(process)
66        if state == lldb.eStateStopped:
67            # Get the first thread
68            thread = process.GetThreadAtIndex(0)
69            if thread:
70                # Print some simple thread info
71                print(thread)
72                # Get the first frame
73                frame = thread.GetFrameAtIndex(0)
74                if frame:
75                    # Print some simple frame info
76                    print(frame)
77                    function = frame.GetFunction()
78                    # See if we have debug info (a function)
79                    if function:
80                        # We do have a function, print some info for the
81                        # function
82                        print(function)
83                        # Now get all instructions for this function and print
84                        # them
85                        insts = function.GetInstructions(target)
86                        disassemble_instructions(insts)
87                    else:
88                        # See if we have a symbol in the symbol table for where
89                        # we stopped
90                        symbol = frame.GetSymbol()
91                        if symbol:
92                            # We do have a symbol, print some info for the
93                            # symbol
94                            print(symbol)
95                            # Now get all instructions for this symbol and
96                            # print them
97                            insts = symbol.GetInstructions(target)
98                            disassemble_instructions(insts)
99
100                    registerList = frame.GetRegisters()
101                    print("Frame registers (size of register set = %d):" % registerList.GetSize())
102                    for value in registerList:
103                        # print value
104                        print("%s (number of children = %d):" % (value.GetName(), value.GetNumChildren()))
105                        for child in value:
106                            print("Name: ", child.GetName(), " Value: ", child.GetValue())
107
108            print("Hit the breakpoint at main, enter to continue and wait for program to exit or 'Ctrl-D'/'quit' to terminate the program")
109            next = sys.stdin.readline()
110            if not next or next.rstrip('\n') == 'quit':
111                print("Terminating the inferior process...")
112                process.Kill()
113            else:
114                # Now continue to the program exit
115                process.Continue()
116                # When we return from the above function we will hopefully be at the
117                # program exit. Print out some process info
118                print(process)
119        elif state == lldb.eStateExited:
120            print("Didn't hit the breakpoint at main, program has exited...")
121        else:
122            print("Unexpected process state: %s, killing process..." % debugger.StateAsCString(state))
123            process.Kill()
124
125
126lldb.SBDebugger.Terminate()
127