Home > Enterprise >  gdb: Get last changes of value
gdb: Get last changes of value

Time:03-27

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.

CodePudding user response:

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.

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:

enable_break && intended_value != actual_value

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 with static lifetime called intended_value, which you set to the same value as actual_value whenever you intentionally change the value of this variable.

However, using the expression

intended_value != actual_value

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:

enable_break && intended_value != actual_value

The variable enable_break should be a bool with static lifetime, which specifies whether the watchpoint should be active or not.

Whenever you want to assign a new value to intended_value and actual_value, you can set enable_break to false, set both variables to the new values, and then reenable the watchpoint by setting enable_break to true. 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.

CodePudding user response:

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.

  • Related