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 26 27if len(sys.argv) == 2: 28 fname = "main" 29 exe = sys.argv[1] 30elif len(sys.argv) == 4: 31 if sys.argv[1] != "-n": 32 usage() 33 else: 34 fname = sys.argv[2] 35 exe = sys.argv[3] 36else: 37 usage() 38 39# Create a new debugger instance 40debugger = lldb.SBDebugger.Create() 41 42# When we step or continue, don't return from the function until the process 43# stops. We do this by setting the async mode to false. 44debugger.SetAsync(False) 45 46# Create a target from a file and arch 47print("Creating a target for '%s'" % exe) 48 49target = debugger.CreateTargetWithFileAndArch(exe, lldb.LLDB_ARCH_DEFAULT) 50 51if target: 52 # If the target is valid set a breakpoint at main 53 main_bp = target.BreakpointCreateByName(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( 102 "Frame registers (size of register set = %d):" 103 % registerList.GetSize() 104 ) 105 for value in registerList: 106 # print value 107 print( 108 "%s (number of children = %d):" 109 % (value.GetName(), value.GetNumChildren()) 110 ) 111 for child in value: 112 print( 113 "Name: ", child.GetName(), " Value: ", child.GetValue() 114 ) 115 116 print( 117 "Hit the breakpoint at main, enter to continue and wait for program to exit or 'Ctrl-D'/'quit' to terminate the program" 118 ) 119 next = sys.stdin.readline() 120 if not next or next.rstrip("\n") == "quit": 121 print("Terminating the inferior process...") 122 process.Kill() 123 else: 124 # Now continue to the program exit 125 process.Continue() 126 # When we return from the above function we will hopefully be at the 127 # program exit. Print out some process info 128 print(process) 129 elif state == lldb.eStateExited: 130 print("Didn't hit the breakpoint at main, program has exited...") 131 else: 132 print( 133 "Unexpected process state: %s, killing process..." 134 % debugger.StateAsCString(state) 135 ) 136 process.Kill() 137 138 139lldb.SBDebugger.Terminate() 140