【问题标题】:Why the mov instruction isn't executed correctly?为什么 mov 指令没有正确执行?
【发布时间】:2017-11-25 13:16:26
【问题描述】:

我在调试我的程序时遇到了一个错误,即使阅读了asm代码也无法解决

这是来自 GDB 的图像,在 0x4070a1 之前,%rdx 是 0x61b130,这个数字应该移动到 -0x18(%rbp)。但是,经过这条指令后,我发现-0x18(%rbp)变成了0x61b7d0,这让我感到很困惑。

由于这个问题,我的程序无法正常运行,谁能告诉我原因?谢谢!

C 代码:

E_enventry t = E_FunEntry(level,label,NULL,NULL); //t here is 0x61b130
S_enter(venv,S_Symbol("flush"), t);
......
void S_enter(S_table t, S_symbol sym, void *value) {
    //while value here is 0x61b7d0
    TAB_enter(t,sym,value);
}

【问题讨论】:

标签: c assembly x86 gdb x86-64


【解决方案1】:

p/x $rdx 显示 0x61b130 毫无意义。显示value 的函数入口值的堆栈帧与您在内存中看到的内容与存储后的x 相匹配。

我认为您的 GDB 有问题,但它显示的错误可能是 $rdx 的值,因为这与其他两个来源不一致。 (并且根据您的评论,在溢出/重新加载后也与p/x $rdx 不一致)。

尝试不同版本的 gdb,或尝试使用不同的调试器(它也不是 GDB 的前端)。例如试试lldb


在将所有 3 个 args 溢出/重新加载到堆栈中/从堆栈中重新加载后,它最终对 TAB_enter 进行函数调用,前 3 个 args 相同,第 4 个 arg = 2rd arg (sym 在你的 C 源代码中)

或者可能没有第四个参数,它只是使用%rcx作为临时而不是直接加载到%rsi,就像它使用%rax一样。

gcc -O0 非常脑残,其中只有一部分是故意的(溢出/重新加载 C 语句之间的所有内容以支持使用调试器修改内存中的变量,甚至在源代码行之间跳转。 )

TL:DR:不出所料,您展示的 asm 完全实现了您为 void S_enter(S_table t, S_symbol sym, void *value) 展示的源代码,不多也不少。

【讨论】:

  • @T.Chen: 你有安装信号处理器吗?或者任何其他会异步修改进程的寄存器或内存的东西?我一直在查看您的 gdb 会话,但没有任何意义。你能在不同的运行中重现这个吗?什么值被重新加载回%rdx
  • 不,只有一个线程,我没有添加任何信号处理程序。结果每次都是一样的。
  • @T.Chen: 你的gdb 有可能有问题吗?也许尝试不同的调试器,比如lldb。请注意,堆栈帧信息甚至在存储到堆栈之前就有value = 0x61b7d0,因此它的正确值是%rdx
  • 在重新加载指令后gdb 是否在%rdx 中显示预期值?
  • 你是对的!当我检查 printf 时,该值似乎是正确的。也许我应该使用另一个调试器。谢谢!
猜你喜欢
  • 2015-10-03
  • 2020-06-17
  • 1970-01-01
  • 2014-04-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-05-27
相关资源
最近更新 更多