Unhandled Exception
Unhandled Exception

Reputation: 1513

How to associate assembly code to exact line in C program?

Here is an example found via an assembly website. This is the C code:

 int main()
 {
     int a = 5;
     int b = a + 6;
     return 0;
 }

Here is the associated assembly code:

    (gdb) disassemble
    Dump of assembler code for function main:
    0x0000000100000f50 <main+0>:    push   %rbp
    0x0000000100000f51 <main+1>:    mov    %rsp,%rbp
    0x0000000100000f54 <main+4>:    mov    $0x0,%eax
    0x0000000100000f59 <main+9>:    movl   $0x0,-0x4(%rbp)
    0x0000000100000f60 <main+16>:   movl   $0x5,-0x8(%rbp)
    0x0000000100000f67 <main+23>:   mov    -0x8(%rbp),%ecx
    0x0000000100000f6a <main+26>:   add    $0x6,%ecx
    0x0000000100000f70 <main+32>:   mov    %ecx,-0xc(%rbp)
    0x0000000100000f73 <main+35>:   pop    %rbp
    0x0000000100000f74 <main+36>:   retq   
    End of assembler dump.

I can safely assume that this line of assembly code:

  0x0000000100000f6a <main+26>:   add    $0x6,%ecx

correlates to this line of C:

     int b = a + 6;

But is there a way to extract which lines of assembly are associated to the specific line of C code?
In this small sample it's not too difficult, but in larger programs and when debugging a larger amount of code it gets a bit cumbersome.

Upvotes: 9

Views: 6000

Answers (4)

alinsoar
alinsoar

Reputation: 15793

First, you need to compile the program keeping inside its object file informations about the source code either via gdwarf or g flag or both. Next, if you want to debug it is important for the compiler to avoid optimizations, otherwise it is difficult to see a correspondence code<>assembly.

gcc -gdwarf -g3 -O0 prog.c -o out

Next, tell the disassembler to output the source code. The source flag involves the disassemble flag.

objdump --source out

Upvotes: 1

edmz
edmz

Reputation: 8494

@Useless is very right. Anyways, a trick to know where C has arrived in the machine code is to inject markers in it; for instance,

#define ASM_MARK do { asm __volatile__("nop; nop; nop;\n\t" :::); } while (0);

int main()
{
    int a = 5;
    ASM_MARK;
       int b = a + 6;
    ASM_MARK;
    return 0;
}

You will see:

main:
        pushq   %rbp
        movq    %rsp, %rbp
        movl    $5, -4(%rbp)
        nop; nop; nop;

        movl    -4(%rbp), %eax
        addl    $6, %eax
        movl    %eax, -8(%rbp)
        nop; nop; nop;

        movl    $0, %eax
        popq    %rbp
        ret

You need to use the __volatile__ keyword or equivalent in order to tell the compiler not to interfere and this is often compiler-specific (notice the __), as C does not provide this kind of syntax.

Upvotes: 0

lapinozz
lapinozz

Reputation: 310

One of the best tools I've found for this is Matthew Godbolt's Compiler Explorer.

It features multiple compiler toolchains, auto-recompiles, and it immediately shows the assembly output with colored lines to show the corresponding line of source code.

Upvotes: 3

Useless
Useless

Reputation: 67743

But is there a way to extract which lines of assembly are associated to the specific line of C code?

Yes, in principle - your compiler can probably do it (GCC option -fverbose-asm, for example). Alternatively, objdump -lSd or similar will disassemble a program or object file with source and line number annotations where available.

In general though, for a large optimized program, this can be very hard to follow.

Even with perfect annotation, you'll see the same source line mentioned multiple times as expressions and statements are split up, interleaved and reordered, and some instructions associated with multiple source expressions.

In this case, you just need to think about the relationship between your source and the assembly, but it takes some effort.

Upvotes: 7

Related Questions