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.
6 Answers
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.
 
    
    - 19,129
- 5
- 61
- 68
- 
                    8If you want to watch a member of a C++ method, I found this variant immensely useful: `watch -location mTextFormatted`. – Ivan Vučica May 17 '11 at 12:10
- 
                    1What if I don't have the address of a variable? Can I just use its name? – Raffi Khatchadourian May 25 '11 at 19:07
- 
                    6You can have GDB print the address of the variable with the address-of operator. `print &variable` – Loduwijk Jun 28 '11 at 19:21
- 
                    How to differ when using awatch between break due to read or write? – Mar 13 '14 at 09:59
- 
                    3This answer does not say anything about the *size* of memory location that's being watched by `watch` commands. Meanwhile, this is the fist question that pops to mind after reading the above. How many bytes `rwatch *0xfeedface` will actually watch? – AnT stands with Russia Nov 06 '15 at 20:52
- 
                    8@AnT, I was assuming it would watch a single byte, which seems to be the case, but you can cast it to a specific type e.g. `rwatch *(int *)0xfeedface` and it will watch `sizeof(int)` bytes: https://sourceware.org/gdb/onlinedocs/gdb/Set-Watchpoints.html – asksol Dec 10 '15 at 05:46
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.
 
    
    - 38,402
- 17
- 102
- 126
 
    
    - 12,403
- 6
- 52
- 73
- 
                    6I wrote **another** answer because existing ones didn't seem very straightforward to me... – Paolo M Jul 03 '15 at 08:54
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.
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.
 
    
    - 13,619
- 5
- 32
- 32
- 
                    If your platform doesn't support hardware watchpoints the gdb should fall back to a software watch point. – Tod Oct 23 '13 at 22:22
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.
 
    
    - 589
- 6
- 20
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.
 
    
    - 55
- 1
- 6
 
     
     
    