gdb:获取值的最后更改
我有一个有错误的 C 应用程序:有一个值(在静态数组中的特定位置;因此地址是众所周知的)在某些时候具有意外值。我已经尝试过这些事情:
- 使用地址清理程序:它没有检测到任何内容
- 使用观察点:不幸的是,该值可以以有效的方式多次更改,直到更改无效。即使最终值也可能会出现多次(这是有效的)。因此不可能检查特定值。
一旦该值是“意外”,应用程序就会挂起(基本上自旋锁将永远循环)。如果发生这种情况,我想获取特定地址的最新更改。
是否有可能用 gdb 来做到这一点?
非常感谢
-编辑-
当值更改并自动继续时始终转储堆栈跟踪就已经足够了。我不确定 gdb 是否可以轻松实现这一点。
I have a C-application which has a bug: There's a value (at a specific location in an static array; so the address is well-known) which has at some point an unexpected value. I've tried these things:
- Using address sanitizer: It did not detect anything
- Using watch-point: Unfortunately the value can change many many times in a valid way until the change is invalid. Even the final value might an will appear many times (which is valid). So it's not possible to check for a specific value.
As soon as the value is "unexpected", the application will hang (basically a spin-lock will loop forever). If this happens I would like to get the last changes for the specific address.
Is it somehow possible to do this with gdb?
Thank you very much
-edit-
It would already be sufficient to always dump the stacktrace when the value changes and automatically continue. I'm not sure if that's easily possible with gdb.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
在 Linux 上,调试此类问题的最佳方法是使用可逆调试器,例如 rr。
例如,它允许您运行直到崩溃或损坏,然后设置观察点并执行“reverse-cont”以返回到上次更新值的位置。
这适用于您的情况 - 损坏是可重复的,也在随机内存损坏的情况下 - 因为
rr
准确地重播运行 >,反向执行期间没有变化。On Linux, the best way to debug a problem like this is by using reversible debugger, such as rr.
It allows you to e.g. run until crash or corruption, then set watch point and do
reverse-cont
to go back to where the value was last updated.This works in your case -- where corruption is repeatable, and also in the case where random memory is corrupted -- since
rr
replays the run exactly, there is no variability during reverse execution.GDB 观察点不仅在特定内存地址处的值更改为特定值时支持中断。它还支持更复杂的条件表达式,例如:
在注释部分,您声明预期的更改是微不足道的,并且您确定该值是从非预期来源修改的。因此,如果
actual_value
是从非预期来源修改的值,那么您可以引入一个具有static
生命周期的新变量,称为intended_value
,每当您有意更改此变量的值时,您都将其设置为与actual_value
相同的值。然而,单独使用表达式
会存在一个问题,即无法同时为两个变量设置新值,并且依次修改变量会触发观察点。
为了防止每当更改这些变量的值时触发观察点,您可以将表达式更改为以下内容:
变量
enable_break
应该是bool
,其中>static
生命周期,指定观察点是否应处于活动状态。每当您想要为
intended_value
和actual_value
分配新值时,您可以将enable_break
设置为false
,同时设置变量更改为新值,然后通过将enable_break
设置为true
来重新启用观察点。这样,当您有意为这些变量分配新值时,观察点将永远不会触发。但请注意,根据有关观察点的 GDB 文档,软件观察点可能无法检测另一个线程是否更改了观察点的表达式。
A GDB watchpoint does not only support breaks if the value at a particular memory address changes to a particular value. It also supports more complex conditional expressions, such as:
In the comments section, you stated that the intended changes are trivial and that you are sure that the value is being modified from an unintended source. Therefore, if
actual_value
is the value that is being modified from an unintended source, then you could introduce a new variable withstatic
lifetime calledintended_value
, which you set to the same value asactual_value
whenever you intentionally change the value of this variable.However, using the expression
by itself would have the problem that you cannot set a new value for both variables at the same time, and modifying the variables one after the other would trigger the watchpoint.
In order to prevent the watchpoint from triggering whenever you change the value of these variables, you can change the expression to the following:
The variable
enable_break
should be abool
withstatic
lifetime, which specifies whether the watchpoint should be active or not.Whenever you want to assign a new value to
intended_value
andactual_value
, you can setenable_break
tofalse
, set both variables to the new values, and then reenable the watchpoint by settingenable_break
totrue
. That way, the watchpoint will never trigger when you intentionally assign a new value to these variables.Note however that according to the GDB documentation on watchpoints, software watchpoints may not detect if another thread changes the expression of the watchpoint.