【问题标题】:Where does the asm code during the debugging process in GDB come from?GDB中调试过程中的asm代码从哪里来?
【发布时间】:2013-12-23 23:16:28
【问题描述】:

据我所知,基本上,

如果我们使用 GDB 调试从 C 源代码编译的执行代码, 编译器会将源代码路径留在 ELF/PE 文件中,所以 GDB 将使用源代码来促进我们的调试过程。

但是GDB如何在上述过程中提供asm代码信息呢?我举一个在我的电脑上捕获的例子如下:

所以我的问题是:

  1. GDB如何提供asm代码?这个asm代码是反汇编生成的吗?
  2. 如果是这样,那么GDB如何保证反汇编的准确性? 据我所知,使用的像OBJDUMP这样的线性反汇编算法无法区分数据和代码,像IDA pro这样的商业工具也会时不时出错

谁能给我一些帮助?谢谢!

【问题讨论】:

标签: debugging assembly compiler-construction gdb disassembly


【解决方案1】:

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

  • 预处理(#includes、宏等)
  • 编译正确(将预处理的 c 转换为汇编)
  • 程序集(将程序集转换为目标代码)
  • 链接(适当地将对象打包到库/可执行文件中)

到目前为止,最复杂的部分是编译阶段。

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

所以,回答你的问题:

  1. GDB 读取您的库/可执行文件并简单地(相对地)提取机器指令,从而提取汇编代码。这是拆解过程。
  2. 同样,由于 GDB 是直接从库/可执行文件中获取机器指令/目标代码,只要它能够准确地将机器代码转换为汇编指令,提供准确的反汇编应该不会有太大问题。

换句话说,从源代码到汇编有一个 1:many 映射,这意味着对于给定的源代码,给定不同的编译器、编译器选项等,汇编代码有许多可能的排列。这意味着很难,如果不是不可能从纯目标代码派生源代码。因此,为了有效调试 c 源代码,源代码必须对 GDB 可用,无论是嵌入的还是原始的 .c 形式。

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

【讨论】:

  • 除了代码段、行号和异常数据之外,没有额外的元数据识别指令吗?如果编译器决定花哨,这似乎很容易造成麻烦(例如,HCS08/HCS12 的 CodeWarrior 喜欢通过将下一条指令嵌入到无操作的立即数中来跳过单个操作码)
  • 指令由它们的机器码操作码标识,这些操作码由给定架构的指令/汇编规范定义。还是我错过了什么?一般来说,建议使用您编译时使用的相同工具链进行调试。
  • 是的,但也有立即操作数字节。在非 RISC 架构上,可以将代码跳转到指令的操作数字节中。这种看似奇怪的代码通常用于(例如,由 CodeWarrior 使用)通过使用具有大立即数的伪指令跳过单指令 else 语句,在分支偏移量上节省一个字节左右
  • Err.. 在评论中清楚地描述这一点有点棘手。以下是关于 6502 上使用的优化的讨论:forum.6502.org/viewtopic.php?t=1614
  • @doynax - 是的,这种事情肯定会让拆卸过程变得更加困难。但是“反编译”的问题要困难几个数量级。
猜你喜欢
  • 2012-04-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-05-03
  • 2023-01-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多