Using GCC to produce readable assembly?
If you compile with debug symbols (add -g
to your GCC command line, even if you're also using -O3
1),
you can use objdump -S
to produce a more readable disassembly interleaved with C source.
>objdump --help
[...]
-S, --source Intermix source code with disassembly
-l, --line-numbers Include line numbers and filenames in output
objdump -drwC -Mintel
is nice:
-r
shows symbol names on relocations (so you'd seeputs
in thecall
instruction below)-R
shows dynamic-linking relocations / symbol names (useful on shared libraries)-C
demangles C++ symbol names-w
is "wide" mode: it doesn't line-wrap the machine-code bytes-Mintel
: use GAS/binutils MASM-like.intel_syntax noprefix
syntax instead of AT&T-S
: interleave source lines with disassembly.
You could put something like alias disas="objdump -drwCS -Mintel"
in your ~/.bashrc
. If not on x86, or if you like AT&T syntax, omit -Mintel
.
Example:
> gcc -g -c test.c
> objdump -d -M intel -S test.o
test.o: file format elf32-i386
Disassembly of section .text:
00000000 <main>:
#include <stdio.h>
int main(void)
{
0: 55 push ebp
1: 89 e5 mov ebp,esp
3: 83 e4 f0 and esp,0xfffffff0
6: 83 ec 10 sub esp,0x10
puts("test");
9: c7 04 24 00 00 00 00 mov DWORD PTR [esp],0x0
10: e8 fc ff ff ff call 11 <main+0x11>
return 0;
15: b8 00 00 00 00 mov eax,0x0
}
1a: c9 leave
1b: c3 ret
Note that this isn't using -r
so the call rel32=-4
isn't annotated with the puts
symbol name. And looks like a broken call
that jumps into the middle of the call instruction in main. Remember that the rel32
displacement in the call encoding is just a placeholder until the linker fills in a real offset (to a PLT stub in this case, unless you statically link libc).
Footnote 1: Interleaving source can be messy and not very helpful in optimized builds; for that, consider https://godbolt.org/ or other ways of visualizing which instructions go with which source lines. In optimized code there's not always a single source line that accounts for an instruction but the debug info will pick one source line for each asm instruction.
If you give GCC the flag -fverbose-asm
, it will
Put extra commentary information in the generated assembly code to make it more readable.
[...] The added comments include:
- information on the compiler version and command-line options,
- the source code lines associated with the assembly instructions, in the form FILENAME:LINENUMBER:CONTENT OF LINE,
- hints on which high-level expressions correspond to the various assembly instruction operands.
Use the -S (note: capital S) switch to GCC, and it will emit the assembly code to a file with a .s extension. For example, the following command:
gcc -O2 -S foo.c
will leave the generated assembly code on the file foo.s.
Ripped straight from http://www.delorie.com/djgpp/v2faq/faq8_20.html (but removing erroneous -c
)