如何使用 Valgrind 调试堆栈覆盖错误? [英] How to debug stack-overwriting errors with Valgrind?

查看:22
本文介绍了如何使用 Valgrind 调试堆栈覆盖错误?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我只是花了一些时间来追查一个错误,归结为以下问题.代码错误地覆盖了堆栈,我认为它覆盖了函数调用的返回地址.返回后,程序将崩溃并且堆栈将被破坏.在 valgrind 中运行程序会返回一个错误,例如:

I just spent some time chasing down a bug that boiled down to the following. Code was erroneously overwriting the stack, and I think it wrote over the return address of the function call. Following the return, the program would crash and stack would be corrupted. Running the program in valgrind would return an error such as:

vex x86->IR: unhandled instruction bytes: 0xEA 0x3 0x0 0x0
==9222== valgrind: Unrecognised instruction at address 0x4e925a8.

我认为这是因为返回跳转到一个随机位置,其中包含无效的 x86 操作码的内容.(虽然我有点怀疑这个地址 0x4e925a8 碰巧在一个可执行页面中.我想如果不是这种情况,valgrind 会抛出一个不同的错误.)

I figure this is because the return jumped to a random location, containing stuff that were not valid x86 opcodes. (Though I am somehow suspicious that this address 0x4e925a8 happened to be in an executable page. I imagine valgrind would throw a different error if this wasn't the case.)

我确定问题出在堆栈覆盖类型上,并且我已经修复了它.现在我正在考虑如何更有效地捕捉这样的错误.显然,如果我在堆栈上重写 data ,valgrind 不会警告我,但也许当有人写入堆栈上的返回地址时它可以捕获.原则上,它可以检测诸如push EIP"之类的事情何时发生(因此它可以标记返回地址在堆栈中的位置).

I am certain that the problem was of the stack-overwriting type, and I've since fixed it. Now I am trying to think how I could catch errors like this more effectively. Obviously, valgrind can't warn me if I rewrite data on the stack, but maybe it can catch when someone writes over a return address on the stack. In principle, it can detect when something like 'push EIP' happens (so it can flag where the return addresses are on the stack).

我想知道是否有人知道 Valgrind 或其他任何东西是否可以做到这一点?如果没有,您能否评论有关有效调试此类错误的其他建议.

I was wondering if anyone knows if Valgrind, or anything else can do that? If not, can you comment on other suggestions regarding debugging errors of this type efficiently.

推荐答案

如果问题足够确定地发生,您可以指出堆栈被破坏的特定函数(在一个可重复的测试用例中),您可以在 gdb 中:

If the problem happens deterministically enough that you can point out particular function that has it's stack smashed (in one repeatable test case), you could, in gdb:

  1. 在该函数入口处中断
  2. 查找返回地址的存储位置(它相对于 %ebp(在 x86 上)(在函数入口处保留 %esp 的值),我是不确定是否有任何偏移).
  3. 向该地址添加观察点.您必须使用计算出的数字而不是表达式发出 watch 命令,因为使用表达式 gdb 会尝试在每条指令后重新评估它,而不是设置陷阱,这会非常慢.
  4. 让函数运行完成.
  1. Break at entry to that function
  2. Find where the return address is stored (it's relative to %ebp (on x86) (which keeps the value of %esp at the function entry), I am not sure whether there is any offset).
  3. Add watchpoint to that address. You have to issue the watch command with calculated number, not an expression, because with an expression gdb would try to re-evaluate it after each instruction instead of setting up a trap and that would be extremely slow.
  4. Let the function run to completion.

我还没有使用 gdb7 中可用的 python 支持,但它应该允许自动化.

I have not yet worked with the python support available in gdb7, but it should allow automating this.

这篇关于如何使用 Valgrind 调试堆栈覆盖错误?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆