gdb 不会在 x86 的给定硬件观察点处停止 cpu
gdb does not stop at given hardware watchpoint with x86 cpu
我已经用 gdb 调试了 QEMU。
为了跟踪意外的内存访问,我在特定地址设置了硬件观察点。但是,当地址中的值更改时,gdb 不会停止。这是我第一次在gdb中使用硬件观察点功能。
我不知道为什么会这样,想解决这个问题。
以下是 gdb 控制台输出。
$ gdb --args ./qemu-system-x86_64 -m 512 -hda linux-0.2.img
...
(gdb) x 0x7fffbbe8e000
0x7fffbbe8e000: 0x00000000
(gdb) watch *(int *)0x7fffbbe8e000
Hardware watchpoint 1: *(int *)0x7fffbbe8e000
(gdb) c
Continuing.
[Thread 0x7fffc2dad700 (LWP 3162) exited]
[New Thread 0x7fffc2dad700 (LWP 3169)]
[Thread 0x7fffc2dad700 (LWP 3169) exited]
[New Thread 0x7fffc2dad700 (LWP 3173)]
qemu: /home/nutsman/git_repo/M-QEMU/qemu-2.3.1/exec.c:3007: ldl_phys_internal: Assertion `val1 == val' failed.
Program received signal SIGABRT, Aborted.
[Switching to Thread 0x7fffc23ca700 (LWP 3163)]
0x00007ffff61f4cc9 in __GI_raise (sig=sig@entry=6)
at ../nptl/sysdeps/unix/sysv/linux/raise.c:56
56 ../nptl/sysdeps/unix/sysv/linux/raise.c: no such a file or directory
(gdb) x 0x7fffbbe8e000
0x7fffbbe8e000: 0x6c7cebfa
谢谢你,受雇的俄罗斯人。内存是user-space,分配的是MAP_PRIVATE,所以任何其他程序都不能改变它的内容。
你能告诉我替代工具来找到 QEMU 中改变值的部分,或者可以写入用户-space 内存的系统调用吗?
However, gdb does not stop while the value in the address is changed
当程序在用户空间运行中时,GDB 可以检测到值何时更改。它不能(也不会)检测内核所做的更改(例如,作为 read(2)
或 mremap(2)
系统调用的结果)。如果有问题的地址是 MAP_SHARED
映射的一部分,并且其他一些进程修改了内存,GDB 也不会停止。
尝试使用软件观察点。在设置观察点之前,请在 GDB 中设置 can-use-hw-watchpoints 0。这将使 GDB 在每一步之后检查该内存地址的值。这将非常缓慢,但至少您可能会发现意外修改。
可以将多个虚拟内存地址(可能跨越不同的 processes/paging 结构)映射到相同的物理内存地址。根据 Employed Russian 所说的内容,我猜测观察点寻找对指定虚拟内存地址的写入,而不是物理内存地址。如果这是真的,它就不会捕获到映射到同一物理地址的不同虚拟内存地址的写入。
我已经用 gdb 调试了 QEMU。
为了跟踪意外的内存访问,我在特定地址设置了硬件观察点。但是,当地址中的值更改时,gdb 不会停止。这是我第一次在gdb中使用硬件观察点功能。
我不知道为什么会这样,想解决这个问题。
以下是 gdb 控制台输出。
$ gdb --args ./qemu-system-x86_64 -m 512 -hda linux-0.2.img
...
(gdb) x 0x7fffbbe8e000
0x7fffbbe8e000: 0x00000000
(gdb) watch *(int *)0x7fffbbe8e000
Hardware watchpoint 1: *(int *)0x7fffbbe8e000
(gdb) c
Continuing.
[Thread 0x7fffc2dad700 (LWP 3162) exited]
[New Thread 0x7fffc2dad700 (LWP 3169)]
[Thread 0x7fffc2dad700 (LWP 3169) exited]
[New Thread 0x7fffc2dad700 (LWP 3173)]
qemu: /home/nutsman/git_repo/M-QEMU/qemu-2.3.1/exec.c:3007: ldl_phys_internal: Assertion `val1 == val' failed.
Program received signal SIGABRT, Aborted.
[Switching to Thread 0x7fffc23ca700 (LWP 3163)]
0x00007ffff61f4cc9 in __GI_raise (sig=sig@entry=6)
at ../nptl/sysdeps/unix/sysv/linux/raise.c:56
56 ../nptl/sysdeps/unix/sysv/linux/raise.c: no such a file or directory
(gdb) x 0x7fffbbe8e000
0x7fffbbe8e000: 0x6c7cebfa
谢谢你,受雇的俄罗斯人。内存是user-space,分配的是MAP_PRIVATE,所以任何其他程序都不能改变它的内容。 你能告诉我替代工具来找到 QEMU 中改变值的部分,或者可以写入用户-space 内存的系统调用吗?
However, gdb does not stop while the value in the address is changed
当程序在用户空间运行中时,GDB 可以检测到值何时更改。它不能(也不会)检测内核所做的更改(例如,作为 read(2)
或 mremap(2)
系统调用的结果)。如果有问题的地址是 MAP_SHARED
映射的一部分,并且其他一些进程修改了内存,GDB 也不会停止。
尝试使用软件观察点。在设置观察点之前,请在 GDB 中设置 can-use-hw-watchpoints 0。这将使 GDB 在每一步之后检查该内存地址的值。这将非常缓慢,但至少您可能会发现意外修改。
可以将多个虚拟内存地址(可能跨越不同的 processes/paging 结构)映射到相同的物理内存地址。根据 Employed Russian 所说的内容,我猜测观察点寻找对指定虚拟内存地址的写入,而不是物理内存地址。如果这是真的,它就不会捕获到映射到同一物理地址的不同虚拟内存地址的写入。