GDB Python Disas - анализ выходных данных - PullRequest
0 голосов
/ 11 апреля 2019

Настройка: GDB запускает внутренний интерпретатор Python со скриптом. Содержимое скрипта запускает disas в некоторой памяти.

Мне нужен вывод этой команды в виде строки Python. Как я могу это сделать?

Думал о ведении журнала, но оказалось, что записывается только первая строка команды:

Dump of assembler code from 0x8000 to 0x8030:

Ожидаемый результат disas находится на экране, но НЕ в лог-файле.

0x00008000: fsw fa0,24(a5)
0x00008002: fsd fs6,16(sp)
0x00008004: addi    s1,sp,920
...

Можно ли перенаправить стандартный поток в поток или получить информацию каким-либо другим способом?

РЕДАКТИРОВАТЬ: Я подключил GDB к серверу openOCD. На моей цели команды ассемблера. Там нет эльфийского файла и так далее, откуда я беру исходный код. Это просто чистые машинные инструкции, хранящиеся в памяти программ контроллера, и мне нужно распечатать их.

1 Ответ

1 голос
/ 12 апреля 2019

Самый простой способ получить вывод disassemble в строку - это дать gdb.execute аргумент to_string=True.

(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')
>>> 

(я использую pprintвот так, чтобы он хорошо отображался в терминальной сессии.)

Вы можете записать это в файл:

>>> with open("logfile","w") as log:
...   log.write(gdb.execute("disassemble main",to_string=True))
... 
335

Это не слишком сложно для анализа, но пока выиспользуя расширения Python для GDB, вы можете использовать метод gdb.Architecture.disassemble, который выполняет большую часть работы за вас:

>>> 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}]
>>>

Если для вашей программы нет информации отладки, frame.block() потерпит неудачу с RuntimeError: Cannot locate block for frame..Вы все еще можете успешно вызвать arch.disassemble или команду gdb disassemble;просто используйте числовые аргументы.

...