The simplest way to get the output of disassemble
into a string is to give gdb.execute
a to_string=True
argument.
(gdb) start
...
(gdb) pi
>>> import pprint
>>> pp=pprint.PrettyPrinter()
>>> pp.pprint(gdb.execute("disassemble main",to_string=True))
('Dump of assembler code for function main:\n'
' 0x00005555555546a4 <+0>:\tpush %rbp\n'
' 0x00005555555546a5 <+1>:\tmov %rsp,%rbp\n'
'=> 0x00005555555546a8 <+4>:\tcallq 0x555555554560 <pause@plt>\n'
' 0x00005555555546ad <+9>:\tmov $0x0,%eax\n'
' 0x00005555555546b2 <+14>:\tpop %rbp\n'
' 0x00005555555546b3 <+15>:\tretq \n'
'End of assembler dump.\n')
>>>
(I'm using pprint here so that it displays nicely in a terminal session.)
You can write this to a file:
>>> with open("logfile","w") as log:
... log.write(gdb.execute("disassemble main",to_string=True))
...
335
It's not too hard to parse this, but as long as you're using gdb's python extensions, you might want to use the gdb.Architecture.disassemble
method, which does most of the work for you:
>>> frame=gdb.selected_frame()
>>> hex(frame.block().start)
'0x5555555546a4'
>>> hex(frame.block().end) # doc says this is "one past the last address that appears in the block"
'0x5555555546b4'
>>> arch=frame.architecture()
>>> arch.name()
'i386:x86-64'
>>> pp.pprint(arch.disassemble(frame.block().start, frame.block().end - 1))
[{'addr': 93824992233124, 'asm': 'push %rbp', 'length': 1},
{'addr': 93824992233125, 'asm': 'mov %rsp,%rbp', 'length': 3},
{'addr': 93824992233128, 'asm': 'callq 0x555555554560 <pause@plt>', 'length': 5},
{'addr': 93824992233133, 'asm': 'mov $0x0,%eax', 'length': 5},
{'addr': 93824992233138, 'asm': 'pop %rbp', 'length': 1},
{'addr': 93824992233139, 'asm': 'retq ', 'length': 1}]
>>>
If there's no debug info for your program, frame.block()
will fail with RuntimeError: Cannot locate block for frame.
. You can still successfully call arch.disassemble
or the gdb disassemble
command; just use numeric arguments.