Мне нравится objdump
для этого, но наиболее полезные опции неочевидны - особенно если вы используете его в объектном файле, который содержит перемещения, а не конечный двоичный файл.
objdump -d some_binary
делает разумную работу.
objdump -d some_object.o
менее полезен, потому что вызовы внешних функций не разбираются услужливо:
...
00000005 <foo>:
5: 55 push %ebp
6: 89 e5 mov %esp,%ebp
8: 53 push %ebx
...
29: c7 04 24 00 00 00 00 movl $0x0,(%esp)
30: e8 fc ff ff ff call 31 <foo+0x2c>
35: 89 d8 mov %ebx,%eax
...
call
на самом деле printf()
... добавление флага -r
помогает в этом;это отмечает перемещения.objdump -dr some_object.o
дает:
...
29: c7 04 24 00 00 00 00 movl $0x0,(%esp)
2c: R_386_32 .rodata.str1.1
30: e8 fc ff ff ff call 31 <foo+0x2c>
31: R_386_PC32 printf
...
Затем я считаю полезным видеть каждую строку с пометкой <symbol+offset>
.У objdump
есть удобная опция для этого, но он имеет раздражающий побочный эффект отключения дампа реальных байтов - objdump --prefix-addresses -dr some_object.o
дает:
...
00000005 <foo> push %ebp
00000006 <foo+0x1> mov %esp,%ebp
00000008 <foo+0x3> push %ebx
...
Но оказывается, что вы можете отменить этопредоставив еще один неясный вариант, наконец-то дойдя до моего любимого objdump
заклинания:
objdump --prefix-addresses --show-raw-insn -dr file.o
, которое выдает следующий результат:
...
00000005 <foo> 55 push %ebp
00000006 <foo+0x1> 89 e5 mov %esp,%ebp
00000008 <foo+0x3> 53 push %ebx
...
00000029 <foo+0x24> c7 04 24 00 00 00 00 movl $0x0,(%esp)
2c: R_386_32 .rodata.str1.1
00000030 <foo+0x2b> e8 fc ff ff ff call 00000031 <foo+0x2c>
31: R_386_PC32 printf
00000035 <foo+0x30> 89 d8 mov %ebx,%eax
...
И если вы создали с помощью символов отладки (т. Е. Скомпилированы с -g
) и вы заменили -dr
на -Srl
, он попытается аннотировать вывод соответствующими строками-источниками.