可能陷入写地址(x86 – linux)

我希望能够检测到写入内存地址的时间,例如通过设置一个附加到中断的callback函数。 有谁知道如何?

我希望能够在运行时做到这一点(可能gdb有这个function,但我的特定应用程序导致gdb崩溃)。

Solutions Collecting From Web of "可能陷入写地址(x86 – linux)"

如果你想拦截写入的地址范围,你可以使用mprotect()标记为不可写的内存,并安装一个信号处理程序使用sigaction()来捕获结果SIGSEGV,做你的日志或任何和将页面标记为可重写。

你需要的是访问X86调试寄存器: http : //en.wikipedia.org/wiki/Debug_register

您需要在DR0到DR3之一中设置断点地址,然后在DR7中设置条件(数据写入)。 中断将会发生,您可以运行您的调试代码来读取DR6并查找是什么导致了断点。

如果GDB不工作,你可以尝试一个更简单/更小的调试器,例如http://sourceforge.net/projects/minibug/ – 如果这不起作用,你至少可以通过代码并了解如何使用在处理器上自己调试硬件。

而且,掌握linux调试技术的IBM开发人员资源非常丰富,应该提供一些额外的选项:

http://www.ibm.com/developerworks/linux/library/l-debug/

一个相当好的文章是这样的Windows是在这里(我知道你在Linux上运行,但其他人可能会来到这个问题想要在Windows中):

http://www.codeproject.com/KB/debug/hardwarebreakpoint.aspx

-亚当

GDB确实有这样的功能:它被称为硬件观察点,在Linux / x86上得到很好的支持:

 (gdb) watch *(int *)0x12345678 

如果您的应用程序崩溃GDB,从CVS头建立当前的GDB。

如果该GDB仍然失败,请提交GDB 错误 。

很有可能我们可以修复GDB的速度比在SIGSEGV处理程序(可以提供一个很好的测试用例)方面快得多,修复GDB也可以帮助您解决将来的问题。

mprotect确实有一个缺点:你的内存必须是页面边界对齐的。 我在堆栈中遇到了问题的内存,无法使用mprotect()。

正如亚当所说,你想要的是操纵调试寄存器。 在Windows上,我使用这个: http : //www.morearty.com/code/breakpoint/ ,它工作得很好。 我也把它移植到Mach-O(Mac OS X)上,它也运行得很好。 这也很容易,因为Mach-O具有thread_set_state(),这相当于SetThreadContext()。

Linux的问题是它没有这样的等价物。 我找到了ptrace,但是我认为,这不可能,必须有一些简单的东西。 但是没有。 然而。 我认为他们正在为内核和用户空间使用hw_breakpoint API。 (见http://lwn.net/Articles/317153/

但是,当我发现这个: http : //blogs.oracle.com/nike/entry/memory_debugger_for_linux我试了一下,并没有那么糟糕。 ptrace方法通过一些“外部进程”充当“调试器”,附加到你的程序,为调试寄存器注入新的值,并终止你的程序继续设置一个新的硬件断点。 事情是,你可以使用fork()来创建这个“外部进程”,(我没有pthread的成功),并且在你的代码中执行这些简单的步骤。

addwatchpoint代码必须适应64位的linux,但是这只是改变USER_DR7等offsetof(结构用户,u_debugreg [7])。 另一件事是,在PTRACE_ATTACH之后,你必须等待调试对象实际停止。 但是,不要在繁忙的循环中重试一个POKEUSER,正确的做法是在您的pid上使用waitpid()。

ptrace方法唯一的缺点就是你的程序一次只能附加一个“调试器”。 所以如果您的程序已经在gdb控制下运行,那么ptrace附件将会失败。 但就像示例代码一样,您可以注册一个SIGTRAP的信号处理程序,在没有gdb的情况下运行,当您捕获信号时,输入一个繁忙的循环,等待gdb连接。 从那里你可以看到谁试图写你的记忆。