Debugging GDB中调试过程中的asm代码来自哪里?

Debugging GDB中调试过程中的asm代码来自哪里?,debugging,assembly,compiler-construction,gdb,disassembly,gcc,Debugging,Assembly,Compiler Construction,Gdb,Disassembly,Gcc,基本上,据我所知 如果我们使用GDB调试执行从C源代码编译的代码, 编译器将在ELF/PE文件中保留源代码路径,因此 GDB将使用源代码来简化调试过程 但GDB如何在上述过程中提供asm代码信息?我给出了一个在我的计算机上捕获的示例,如下所示: 因此,我的问题是: GDB如何提供asm代码?这是反汇编生成的asm代码吗 如果是这样,那么GDB如何保证拆卸精度? 正如我所知,像OBJDUMP这样使用的线性反汇编算法无法区分数据和代码,像idapro这样的商业工具也会不时出错 谁能给我一些帮助吗?

基本上,据我所知

如果我们使用GDB调试执行从C源代码编译的代码, 编译器将在ELF/PE文件中保留源代码路径,因此 GDB将使用源代码来简化调试过程

但GDB如何在上述过程中提供asm代码信息?我给出了一个在我的计算机上捕获的示例,如下所示:

因此,我的问题是:

  • GDB如何提供asm代码?这是反汇编生成的asm代码吗
  • 如果是这样,那么GDB如何保证拆卸精度? 正如我所知,像OBJDUMP这样使用的线性反汇编算法无法区分数据和代码,像idapro这样的商业工具也会不时出错
  • 谁能给我一些帮助吗?谢谢大家!

    请记住,“编译器”(例如)做了几件事:

    • 预处理(包括、宏等)
    • 正确编译(将预处理的c转换为汇编)
    • 程序集(将程序集转换为目标代码)
    • 链接(适当地将对象打包到库/可执行文件中)
    到目前为止,最复杂的部分是编译阶段

    还要记住,汇编或多或少是目标代码中包含的机器指令的直接表示

    因此,要回答您的问题:

  • GDB读取您的库/可执行文件,并简单地(相对地)提取机器指令,从而提取汇编代码。这就是拆卸过程
  • 同样,由于GDB直接从库/可执行文件获取机器指令/目标代码,只要它能够准确地将机器代码转换为汇编指令,提供准确的反汇编应该不会有太大问题
  • 换句话说,从源代码到程序集有一个1:many映射,这意味着对于给定的源代码、给定的不同编译器、编译器选项等,有许多可能的程序集代码排列。这意味着从纯目标代码派生源代码是困难的,如果不是不可能的话。因此,为了有效地调试c源代码,源代码必须可供GDB使用,无论是嵌入的还是原始的.c形式


    相反,从汇编代码到目标代码的映射更接近于1:1,因为两者或多或少都代表着相同的东西——创建给定程序所必需的内存中的指令布局。因此,反汇编过程比任何潜在的“反编译”过程都要简单得多。

    除了代码段、行号和异常数据之外,没有其他元数据标识说明,那么我接受它了吗?如果编译器决定变得花哨(例如,HCS08/HCS12的CodeWarrior喜欢通过将下一条指令嵌入no op的一个立即数来跳过单个操作码),则这可能会导致麻烦。这些指令由其机器代码操作码标识,由给定体系结构的说明/组装规范定义。还是我遗漏了什么?通常,建议使用编译时使用的同一工具链进行调试。是的,但也有立即操作数字节。在非RISC体系结构上,可以将代码跳转到指令的操作数字节中。这种看似奇怪的代码通常(例如,CodeWarrior)通过使用具有大立即数的伪指令跳过单个指令else语句,在分支偏移器上保存一个字节左右。。在评论中清楚地描述这一点有点棘手。下面是关于6502上使用的优化的讨论:@doynax-是的,这种事情肯定会让拆卸过程更加困难。但“反编译”的问题要困难好几个数量级。似乎涵盖了基本知识。您是否使用过
    objdump
    ?它通常能很好地从代码中辨别数据。@KerrekSB嗨,我写了一个简单的例子: