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