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