4 Run gdb to disassemble a function, feed the bytes to 'llvm-mc -disassemble' command,
5 and display the disassembly result.
11 from optparse import OptionParser
15 """Check whether fpath is an executable."""
16 return os.path.isfile(fpath) and os.access(fpath, os.X_OK)
20 """Find the full path to a program, or return None."""
21 fpath, fname = os.path.split(program)
26 for path in os.environ["PATH"].split(os.pathsep):
27 exe_file = os.path.join(path, program)
33 def do_llvm_mc_disassembly(
40 from cStringIO import StringIO
43 gdb_prompt = "\r\n\(gdb\) "
44 gdb = pexpect.spawn(('gdb %s' % gdb_options) if gdb_options else 'gdb')
45 # Turn on logging for what gdb sends back.
46 gdb.logfile_read = sys.stdout
47 gdb.expect(gdb_prompt)
49 # See if there any extra command(s) to execute before we issue the file
51 for cmd in gdb_commands:
53 gdb.expect(gdb_prompt)
55 # Now issue the file command.
56 gdb.sendline('file %s' % exe)
57 gdb.expect(gdb_prompt)
59 # Send the disassemble command.
60 gdb.sendline('disassemble %s' % func)
61 gdb.expect(gdb_prompt)
63 # Get the output from gdb.
64 gdb_output = gdb.before
66 # Use StringIO to record the memory dump as well as the gdb assembler code.
69 # These keep track of the states of our simple gdb_output parser.
75 for line in gdb_output.split(os.linesep):
76 if line.startswith('Dump of assembler code'):
80 if line.startswith('End of assembler dump.'):
83 if mc_options and mc_options.find('arm') != -1:
85 if mc_options and mc_options.find('thumb') != -1:
86 # It is obviously wrong to assume the last instruction of the
87 # function has two bytes.
91 if looking and line.startswith('0x'):
92 # It's an assembler code dump.
94 curr_addr = line.split(None, 1)[0]
95 if prev_addr and curr_addr:
96 addr_diff = int(curr_addr, 16) - int(prev_addr, 16)
98 if prev_addr and addr_diff > 0:
99 # Feed the examining memory command to gdb.
100 gdb.sendline('x /%db %s' % (addr_diff, prev_addr))
101 gdb.expect(gdb_prompt)
102 x_output = gdb.before
103 # Get the last output line from the gdb examine memory command,
104 # split the string into a 3-tuple with separator '>:' to handle
106 memory_dump = x_output.split(
107 os.linesep)[-1].partition('>:')[2].strip()
108 # print "\nbytes:", memory_dump
109 disasm_str = prev_line.partition('>:')[2]
110 print >> mc_input, '%s # %s' % (memory_dump, disasm_str)
112 # We're done with the processing. Assign the current line to be
116 # Close the gdb session now that we are done with it.
118 gdb.expect(pexpect.EOF)
121 # Write the memory dump into a file.
122 with open('disasm-input.txt', 'w') as f:
123 f.write(mc_input.getvalue())
125 mc_cmd = '%s -disassemble %s disasm-input.txt' % (mc, mc_options)
126 print "\nExecuting command:", mc_cmd
129 # And invoke llvm-mc with the just recorded file.
130 #mc = pexpect.spawn('%s -disassemble %s disasm-input.txt' % (mc, mc_options))
131 #mc.logfile_read = sys.stdout
137 # This is to set up the Python path to include the pexpect-2.4 dir.
138 # Remember to update this when/if things change.
139 scriptPath = sys.path[0]
148 parser = OptionParser(usage="""\
149 Run gdb to disassemble a function, feed the bytes to 'llvm-mc -disassemble' command,
150 and display the disassembly result.
152 Usage: %prog [options]
162 help='Command(s) gdb executes after starting up (can be empty)')
169 help="""The options passed to 'gdb' command if specified.""")
170 parser.add_option('-e', '--executable',
171 type='string', action='store',
173 help="""The executable to do disassembly on.""")
180 help="""The function name (could be an address to gdb) for disassembly.""")
181 parser.add_option('-m', '--llvm-mc',
182 type='string', action='store',
184 help="""The llvm-mc executable full path, if specified.
185 Otherwise, it must be present in your PATH environment.""")
192 dest='llvm_mc_options',
193 help="""The options passed to 'llvm-mc -disassemble' command if specified.""")
195 opts, args = parser.parse_args()
197 gdb_commands = opts.gdb_commands
198 gdb_options = opts.gdb_options
200 if not opts.executable:
203 executable = opts.executable
205 if not opts.function:
208 function = opts.function
210 llvm_mc = opts.llvm_mc if opts.llvm_mc else which('llvm-mc')
215 # This is optional. For example:
216 # --options='-triple=arm-apple-darwin -debug-only=arm-disassembler'
217 llvm_mc_options = opts.llvm_mc_options
219 # We have parsed the options.
220 print "gdb commands:", gdb_commands
221 print "gdb options:", gdb_options
222 print "executable:", executable
223 print "function:", function
224 print "llvm-mc:", llvm_mc
225 print "llvm-mc options:", llvm_mc_options
227 do_llvm_mc_disassembly(
235 if __name__ == '__main__':