简体   繁体   English

如何将汇编代码与C程序中的确切行关联?

[英]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: 这是C代码:

 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: 与此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? 但有没有办法提取哪些程序集与特定的C代码行相关联?
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. 在这个小样本中,它并不太难,但在较大的程序中,当调试大量代码时,它会变得有点麻烦。

But is there a way to extract which lines of assembly are associated to the specific line of C code? 但有没有办法提取哪些程序集与特定的C代码行相关联?

Yes, in principle - your compiler can probably do it (GCC option -fverbose-asm , for example). 是的,原则上 - 您的编译器可能会这样做(例如GCC选项-fverbose-asm )。 Alternatively, objdump -lSd or similar will disassemble a program or object file with source and line number annotations where available. 或者, objdump -lSd或类似程序将使用可用的源和行号注释来反汇编程序或目标文件。

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. 在这种情况下,您只需要考虑源和程序集之间的关系,但需要花费一些精力。

One of the best tools I've found for this is Matthew Godbolt's Compiler Explorer . 我发现的最好的工具之一是Matthew Godbolt的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. 它具有多个编译器工具链,自动重新编译,并立即显示带有彩色线条的程序集输出,以显示相应的源代码行。

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. 首先,您需要通过gdwarfg标志或两者来编译程序,在其目标文件中保留有关源代码的信息。 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. source标志涉及disassemble标志。

objdump --source out

@Useless is very right. @Useless是非常正确的。 Anyways, a trick to know where C has arrived in the machine code is to inject markers in it; 无论如何,知道C在机器代码中的位置的技巧是在其中注入标记; 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. 您需要使用__volatile__关键字或等效项来告诉编译器不要干扰,这通常是编译器特定的(注意__ ),因为C不提供这种语法。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM