我可以在“内存访问”上设置断点吗? 在GDB?

发布于 2024-07-04 08:36:18 字数 104 浏览 12 评论 0原文

我正在通过 gdb 运行应用程序,并且我想在访问/更改特定变量的任何时间设置断点。 有没有好的方法来做到这一点? 我也对监视 C/C++ 中的变量以查看它是否/何时发生变化的其他方法感兴趣。

I am running an application through gdb and I want to set a breakpoint for any time a specific variable is accessed / changed. Is there a good method for doing this? I would also be interested in other ways to monitor a variable in C/C++ to see if/when it changes.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

我爱人 2024-07-11 08:36:18

watch 仅在写入时中断,rwatch 让您在读取时中断,awatch 让您在读/写时中断。

您可以在内存位置设置读取观察点:

gdb$ rwatch *0xfeedface
Hardware read watchpoint 2: *0xfeedface

但 rwatch 和 awatch 命令存在一个限制; 你不能使用 gdb 变量
在表达式中:

gdb$ rwatch $ebx+0xec1a04f
Expression cannot be implemented with read/access watchpoint.

所以你必须自己扩展它们:

gdb$ print $ebx 
$13 = 0x135700
gdb$ rwatch *0x135700+0xec1a04f
Hardware read watchpoint 3: *0x135700 + 0xec1a04f
gdb$ c
Hardware read watchpoint 3: *0x135700 + 0xec1a04f

Value = 0xec34daf
0x9527d6e7 in objc_msgSend ()

编辑:哦,顺便说一句。 您需要硬件或软件支持。 软件显然要慢得多。 要了解您的操作系统是否支持硬件观察点,您可以查看 can-use-hw-watchpoints 环境设置。

gdb$ show can-use-hw-watchpoints
Debugger's willingness to use watchpoint hardware is 1.

watch only breaks on write, rwatch let you break on read, and awatch let you break on read/write.

You can set read watchpoints on memory locations:

gdb$ rwatch *0xfeedface
Hardware read watchpoint 2: *0xfeedface

but one limitation applies to the rwatch and awatch commands; you can't use gdb variables
in expressions:

gdb$ rwatch $ebx+0xec1a04f
Expression cannot be implemented with read/access watchpoint.

So you have to expand them yourself:

gdb$ print $ebx 
$13 = 0x135700
gdb$ rwatch *0x135700+0xec1a04f
Hardware read watchpoint 3: *0x135700 + 0xec1a04f
gdb$ c
Hardware read watchpoint 3: *0x135700 + 0xec1a04f

Value = 0xec34daf
0x9527d6e7 in objc_msgSend ()

Edit: Oh, and by the way. You need either hardware or software support. Software is obviously much slower. To find out if your OS supports hardware watchpoints you can see the can-use-hw-watchpoints environment setting.

gdb$ show can-use-hw-watchpoints
Debugger's willingness to use watchpoint hardware is 1.
酒绊 2024-07-11 08:36:18

您正在寻找的内容称为观察点

用法

(gdb) watch foo:观察变量 foo

(gdb) watch *( int*)0x12345678:监视地址指向的值,转换为您想要的任何类型

(gdb) watch a*b + c/d:watch任意复杂表达式,在程序的本地语言中有效

观察点分为三种:

  • 观察:当发生写入时,gdb 将中断
  • rwatch:gdb 将在读取发生时中断
  • awatch:gdb 将在两种情况下中断

您可以选择更适合您的情况需要。

有关更多信息,请查看

What you're looking for is called a watchpoint.

Usage

(gdb) watch foo: watch the value of variable foo

(gdb) watch *(int*)0x12345678: watch the value pointed by an address, casted to whatever type you want

(gdb) watch a*b + c/d: watch an arbitrarily complex expression, valid in the program's native language

Watchpoints are of three kinds:

  • watch: gdb will break when a write occurs
  • rwatch: gdb will break wnen a read occurs
  • awatch: gdb will break in both cases

You may choose the more appropriate for your needs.

For more information, check this out.

烟雨凡馨 2024-07-11 08:36:18

我刚刚尝试了以下操作:

 $ cat gdbtest.c
 int abc = 43;

 int main()
 {
   abc = 10;
 }
 $ gcc -g -o gdbtest gdbtest.c
 $ gdb gdbtest
 ...
 (gdb) watch abc
 Hardware watchpoint 1: abc
 (gdb) r
 Starting program: /home/mweerden/gdbtest 
 ...

 Old value = 43
 New value = 10
 main () at gdbtest.c:6
 6       }
 (gdb) quit

所以这似乎是可能的,但您似乎确实需要一些硬件支持。

I just tried the following:

 $ cat gdbtest.c
 int abc = 43;

 int main()
 {
   abc = 10;
 }
 $ gcc -g -o gdbtest gdbtest.c
 $ gdb gdbtest
 ...
 (gdb) watch abc
 Hardware watchpoint 1: abc
 (gdb) r
 Starting program: /home/mweerden/gdbtest 
 ...

 Old value = 43
 New value = 10
 main () at gdbtest.c:6
 6       }
 (gdb) quit

So it seems possible, but you do appear to need some hardware support.

风吹过旳痕迹 2024-07-11 08:36:18

假设第一个答案是指类似 C 的语法 (char *)(0x135700 +0xec1a04f) ,那么 do rwatch *0x135700+0xec1a04f 的答案是不正确的。 正确的语法是rwatch *(0x135700+0xec1a04f)

那里缺少 () 给我自己尝试使用观察点带来了很大的痛苦。

Assuming the first answer is referring to the C-like syntax (char *)(0x135700 +0xec1a04f) then the answer to do rwatch *0x135700+0xec1a04f is incorrect. The correct syntax is rwatch *(0x135700+0xec1a04f).

The lack of ()s there caused me a great deal of pain trying to use watchpoints myself.

迷荒 2024-07-11 08:36:18

使用 watch 来查看变量何时被写入,rwatch 何时被读取,awatch 何时被读取/写入,如上所述。 但是,请注意,要使用此命令,您必须中断程序,并且当您中断程序时变量必须在范围内:

使用监视命令。 watch 命令的参数是
被求值的表达式。 这意味着您想要的变量
要设置的观察点必须在当前范围内。 所以,要设置一个
非全局变量上的观察点,您必须设置断点
当变量在范围内时,这将停止你的程序。 您设置了
程序中断后的观察点。

Use watch to see when a variable is written to, rwatch when it is read and awatch when it is read/written from/to, as noted above. However, please note that to use this command, you must break the program, and the variable must be in scope when you've broken the program:

Use the watch command. The argument to the watch command is an
expression that is evaluated. This implies that the variabel you want
to set a watchpoint on must be in the current scope. So, to set a
watchpoint on a non-global variable, you must have set a breakpoint
that will stop your program when the variable is in scope. You set the
watchpoint after the program breaks.

我的奇迹 2024-07-11 08:36:18

除了 asksolPaolo M

我一开始没明白,为什么我们需要投射结果。 虽然我读到了这个: https://sourceware.org/gdb/onlinedocs/gdb /Set-Watchpoints.html,但这对我来说并不直观。

所以我做了一个实验以使结果更清晰:
代码:(假设 int main() 位于第 3 行;int i=0 位于第 5 行,其他代码来自第 10 行)

int main()
{
int i = 0;
int j;
i = 3840 // binary 1100 0000 0000 to take into account endianness
other code..
}

然后我使用可执行文件启动 gdb
在我的第一次尝试中,我在变量的位置设置了断点而不进行强制转换,以下是显示的结果

Thread 1 "testing2" h
Breakpoint 2 at 0x10040109b: file testing2.c, line 10.
(gdb) s
7           i = 3840;
(gdb) p i
$1 = 0
(gdb) p &i
$2 = (int *) 0xffffcbfc
(gdb) watch *0xffffcbfc
Hardware watchpoint 3: *0xffffcbfc
(gdb) s
[New Thread 13168.0xa74]

Thread 1 "testing2" hit Breakpoint 2, main () at testing2.c:10
10          b = a;
(gdb) p i
$3 = 3840
(gdb) p *0xffffcbfc
$4 = 3840
(gdb) p/t *0xffffcbfc
$5 = 111100000000

,我们可以看到我设置的第 10 行断点被击中。 gdb 没有中断,因为虽然变量我经历了更改,但正在监视的位置

在我的第二次尝试中没有更改(由于字节顺序,因为它继续保持全 0),我对要监视的变量的地址进行了转换对于所有 sizeof(int) 字节。 这次:

(gdb) p &i
$6 = (int *) 0xffffcbfc
(gdb) p i
$7 = 0
(gdb) watch *(int *) 0xffffcbfc
Hardware watchpoint 6: *(int *) 0xffffcbfc
(gdb) b 10
Breakpoint 7 at 0x10040109b: file testing2.c, line 10.
(gdb) i b
Num     Type           Disp Enb Address            What
6       hw watchpoint  keep y                      *(int *) 0xffffcbfc
7       breakpoint     keep y   0x000000010040109b in main at testing2.c:10
(gdb) n
[New Thread 21508.0x3c30]

Thread 1 "testing2" hit Hardware watchpoint 6: *(int *) 0xffffcbfc

Old value = 0
New value = 3840

Thread 1 "testing2" hit Breakpoint 7, main () at testing2.c:10
10          b = a;

gdb 中断,因为它检测到值已更改。

In addition to what has already been answered/commented by asksol and Paolo M

I didn't at first read understand, why do we need to cast the results. Though I read this: https://sourceware.org/gdb/onlinedocs/gdb/Set-Watchpoints.html, yet it wasn't intuitive to me..

So I did an experiment to make the result clearer:
Code: (Let's say that int main() is at Line 3; int i=0 is at Line 5 and other code.. is from Line 10)

int main()
{
int i = 0;
int j;
i = 3840 // binary 1100 0000 0000 to take into account endianness
other code..
}

then i started gdb with the executable file
in my first attempt, i set the breakpoint on the location of variable without casting, following were the results displayed

Thread 1 "testing2" h
Breakpoint 2 at 0x10040109b: file testing2.c, line 10.
(gdb) s
7           i = 3840;
(gdb) p i
$1 = 0
(gdb) p &i
$2 = (int *) 0xffffcbfc
(gdb) watch *0xffffcbfc
Hardware watchpoint 3: *0xffffcbfc
(gdb) s
[New Thread 13168.0xa74]

Thread 1 "testing2" hit Breakpoint 2, main () at testing2.c:10
10          b = a;
(gdb) p i
$3 = 3840
(gdb) p *0xffffcbfc
$4 = 3840
(gdb) p/t *0xffffcbfc
$5 = 111100000000

as we could see breakpoint was hit for line 10 which was set by me. gdb didn't break because although variable i underwent change yet the location being watched didn't change (due to endianness, since it continued to remain all 0's)

in my second attempt, i did the casting on the address of the variable to watch for all the sizeof(int) bytes. this time:

(gdb) p &i
$6 = (int *) 0xffffcbfc
(gdb) p i
$7 = 0
(gdb) watch *(int *) 0xffffcbfc
Hardware watchpoint 6: *(int *) 0xffffcbfc
(gdb) b 10
Breakpoint 7 at 0x10040109b: file testing2.c, line 10.
(gdb) i b
Num     Type           Disp Enb Address            What
6       hw watchpoint  keep y                      *(int *) 0xffffcbfc
7       breakpoint     keep y   0x000000010040109b in main at testing2.c:10
(gdb) n
[New Thread 21508.0x3c30]

Thread 1 "testing2" hit Hardware watchpoint 6: *(int *) 0xffffcbfc

Old value = 0
New value = 3840

Thread 1 "testing2" hit Breakpoint 7, main () at testing2.c:10
10          b = a;

gdb break since it detected the value has changed.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文