The simplest way to get the output of disassemble into a string is to give gdb.execute a to_string=Trueargument.
(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.