【问题标题】:gdb watchpoint not triggering on memory addressgdb 观察点未在内存地址上触发
【发布时间】:2019-01-07 16:15:13
【问题描述】:

最近,我尝试在内存地址上使用gdbwatchpoint 功能调试内存损坏错误,该内存地址错误地被某些代码覆盖。

令人惊讶的是,这不起作用。我最终解决了我的问题,但没有gdb 的帮助。这是一个小代码示例,它演示了watchpoint 如何不触发:

void main() {
    unsigned char data[] = {
        0x12, 0x34, 0x56, 0x78
    };

    data[4] = 0x89;
}

此代码声明一个大小为 4 的数组并写入第 4 个索引。糟糕,我们损坏了一个字节的内存。

使用gdb,我在赋值执行前获取了data[4]的地址,并在地址上设置了watchpoint

(gdb) p/x &data[4]
$1 = 0x7ffffffee950
(gdb) watch *0x7ffffffee950
Hardware watchpoint 2: *0x7ffffffee950
(gdb) continue
Continuing.
[Inferior 1 (process 14543) exited normally]

如您所见,应用程序正常运行并退出。 gdb 没有任何反应。这是一个错误还是我在这里做错了什么?如果地址被修改但没有任何反应,我希望从gdb 得到一些东西。

我的 gdb 版本是:

GNU gdb (Ubuntu 8.1-0ubuntu3)

【问题讨论】:

  • 我在这里有点困惑。数组大小是 4。所以最后一个索引是 3。你想改变 data[3] 的值吗?
  • 嗯,你为什么要在数组边界之外设置观察点?当您有此类请求时,我不确定gdb 的行为。而且,memcheck (valgrind) 可能对跟踪这种错误更有意义。
  • @perror 这是堆栈粉碎的部分。
  • 你在未定义时有未定义的行为。是什么让你认为它会做那样的事情?
  • @BullyWiiPlaza 检查Valgrind says about that 的内容。请参阅 - TESTED 代码。

标签: c linux ubuntu gdb windows-subsystem-for-linux


【解决方案1】:

奇怪的是,这似乎与您的示例位于main() 函数中的事实有关。我尝试了以下示例:

void foo() {
    unsigned char data[] = {
        0x12, 0x34, 0x56, 0x78
    };
    data[4] = 0x89;
}

void main() {
  foo();
}

我编译它并在上面运行gdb

$> gcc -g3 -fno-stack-protector -o sample sample.c
$> gdb -q ./sample
Reading symbols from ./sample...done.
(gdb) b foo
Breakpoint 1 at 0x1129: file sample.c, line 2.
(gdb) r
Starting program: /tmp/sample 

Breakpoint 1, foo () at sample.c:2
2       unsigned char data[] = {
(gdb) p /x &data[4]
$1 = 0x7fffffffe150
(gdb) watch *0x7fffffffe150
Hardware watchpoint 2: *0x7fffffffe150
(gdb) c
Continuing.

Hardware watchpoint 2: *0x7fffffffe150

Old value = -7840
New value = -7799
foo () at sample.c:7
7   

所以,它似乎在foo() 中运行良好(但是,我也可以说它在main() 中不起作用)。我来看看为什么...

编辑

似乎我出了点问题(或者我做了一些不同的事情,但我不记得是什么了)。它在我的系统上完美运行(Debian 不稳定,gdb 8.1)。这是我使用的代码:

void main() {
    unsigned char data[] = {
        0x12, 0x34, 0x56, 0x78
    };
    data[4] = 0x89;
}

编译运行gdb就可以了:

$> gcc -Wall -Wextra -fno-stack-protector -g3 -o sample sample.c
$> gdb -q ./sample
Reading symbols from ./sample...done.
(gdb) start
Temporary breakpoint 1 at 0x1129: file sample.c, line 2.
Starting program: /tmp/sample 

Temporary breakpoint 1, main () at sample.c:2
2       unsigned char data[] = {
(gdb) p /x &data[4]
$1 = 0x7fffffffe160
(gdb) watch *0x7fffffffe160
Hardware watchpoint 2: *0x7fffffffe160
(gdb) c
Continuing.

Hardware watchpoint 2: *0x7fffffffe160

Old value = 1431654720
New value = 1431654793
main () at sample.c:6
6   }

没什么奇怪的...观察点按预期工作。但是,这很奇怪,因为一开始它不起作用......我可能做了一些稍微不同的事情......也许,我确实在启动程序之前放置了观察点。它可能在其中发挥了一些作用。

【讨论】:

  • 这段代码用*** stack smashing detected ***: <unknown> terminated编译。为什么seems to work fine
  • 使用选项-fno-stack-protector 删除堆栈粉碎保护(这不是我系统上的默认设置)。
  • 访问不属于你或你的程序的内存应该是valgrind的工作,不是吗?
  • 无论如何,所有这些内存都属于你的程序。它不会出现段错误。
  • UB 表示程序可以按预期运行,并且您的系统可能授予您访问/写入该内存位置的权限。
猜你喜欢
  • 2014-01-30
  • 1970-01-01
  • 1970-01-01
  • 2011-04-08
  • 1970-01-01
  • 1970-01-01
  • 2011-11-15
  • 2023-03-12
相关资源
最近更新 更多