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