25

An earlier question explained that on x86 the size of objects being watched is limited by debug registers. As expected, I can "watch" a double variable. But I can't watch a double datamember, for example,

watch pObject->dPrice

produces

Hardware watchpoint 1: pObject->dPrice

But when you try to continue execution, it says

Could not insert hardware breakpoints: You may have requested too many hardware breakpoints/watchpoints.

even though this is the only breakpoint/watchpoint.

I'm curious why this is so, but more importantly is there a way around it? According to GDB documentation it may use software watchpoints if it can't use hardware. In this case it makes no attempt to use a software watchpoint -- is there a way to force it to do so?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
c-urchin
  • 4,344
  • 6
  • 28
  • 30
  • Are you able to print address of that member variable? My suspicion would be it's optimized into a register. If not that, is it aligned properly? – Nikolai Fetissov Aug 12 '10 at 20:22

3 Answers3

23

Yes, you can:

set can-use-hw-watchpoints 0

From 5.1.2 Setting Watchpoints:

You can force GDB to use only software watchpoints with the set can-use-hw-watchpoints 0 command. With this variable set to zero, GDB will never try to use hardware watchpoints, even if the underlying system supports them. (Note that hardware-assisted watchpoints that were set before setting can-use-hw-watchpoints to zero will still use the hardware mechanism of watching expression values.)

set can-use-hw-watchpoints

    Set whether or not to use hardware watchpoints.

show can-use-hw-watchpoints

    Show the current mode of using hardware watchpoints.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
karlphillip
  • 92,053
  • 36
  • 243
  • 426
  • Thanks! I was just reading that section, but obviously I didn't read very carefully. – c-urchin Aug 12 '10 at 18:56
  • 2
    It works, but it is a fair bit slower than hardware. In my case, about 1/5000 of the speed. – wallyk Jun 23 '15 at 22:05
  • which results in `Can't set read/access watchpoint when hardware watchpoints are disabled.`. – phil294 Jun 05 '18 at 06:04
  • @Blauhirn This is an 8 year old answer. The change you mentioned was [incorporated 5 years ago](https://github.com/espressif/binutils-esp32ulp/blame/master/gdb/testsuite/gdb.base/watchpoint.exp). Let us know if you are able to solve it. – karlphillip Jun 05 '18 at 13:59
  • @wallyk yes, GDB manual says "GDB does software watchpointing by single-stepping your program and testing the variable’s value each time, which is hundreds of times slower than normal execution", so this will not be useful in most debugging scenarios. – Ciro Santilli OurBigBook.com Jan 03 '20 at 16:22
10

Short answer: Use watch -location pObject->dPrice, or the short form watch -l.

Long answer: Quoting the GDB manual:

Watching complex expressions that reference many variables can also exhaust the resources available for hardware-assisted watchpoints. That's because GDB needs to watch every variable in the expression with separately allocated resources.

GDB quite literally watches the expression itself, not whatever address it points to. In this case, it means that the breakpoint will hit if pObject itself is changed to point to a new dPrice; there's not just a watchpoint for pObject->dPrice, but also one for pObject itself. This may be more than what's available.

A more comprehensive example:

// Set a watchpoint on '*p' before running
#include <stdio.h>

int a = 0;
int b = 0;
int c = 0;
int* p = &a;

int main()
{
    puts("Hi"); // Dummy lines to make the results clearer, watchpoints stop at the line after the change
    *p = 1; // Breaks: *p was changed from 0 to 1
    puts("Hi");
    a = 2; // Breaks: a is *p, which changed from 1 to 2
    puts("Hi");
    p = &b; // Breaks: p is now b, changing *p from 2 to 0
    puts("Hi");
    p = &c; // Doesn't break: while p changed, *p is still 0
    puts("Hi");
    p = NULL; // Breaks: *p is now unreadable
    puts("Hi");
    return 0;
}

In theory, this is a useful feature; you can watch a complex expression, breaking as soon as it's false, somewhat like a constantly-tested assertion. For example, you can watch a==b in the above program.

In practice, it's unexpected, often triggers this issue, and usually isn't what you want.

To watch only the target address, use watch -location pObject->dPrice. (This is available as of GDB 7.3, released in July 2011; if you're using anything older, use print &pObject->dPrice and watch *(double*)0x12345678, or whichever address it prints.)

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Alcaro
  • 1,664
  • 16
  • 21
  • Cross-posting this answer to [this question](http://stackoverflow.com/questions/3206332/gdb-stops-with-too-many-watchpoints-when-there-is-only-one), it answers both. – Alcaro Feb 15 '17 at 13:49
  • Oh, OK, so `watch pObject->dPrice` must be attempting to watch both "all fields of `pObject`" and `pObject->dPrice` or something like that. – Ciro Santilli OurBigBook.com Jan 03 '20 at 18:00
7

I'm not 100% sure, but my understanding is that when you watch pObject->dPrice, GDB tries to watch anything that can change the watched value.

Using software watchpoints, after each step GDB checks if the expression has changed. Using hardware watchpoints, GDB has to set a watchpoint for dprice, as you expect, but also for pObject.

Now, you tagged the question 'x86'. On x86 you can set breakpoints for up to four bytes. A double is eight bytes. If you want to watch a double, I would guess that GDB would need two hardware watchpoints. You need an additional watchpoint for pObject as well. I'm guessing that GDB tries to watch all of pObject, which goes back to the problem in the question you linked in the question.

When I want to do something similar, if I'm certain that the pointer pObject will not change, I usually do:

p &pObject->dprice

Let's say GDB says the address is (double *) 0xabcdef10, now I do:

watch (double *) *0xabcdef10

and watch only what I want to.

Note: I don't have GDB open in front of me, so I may have the exact syntax for the watch command wrong (regarding the placement of the *), so check it out first.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Nathan Fellman
  • 122,701
  • 101
  • 260
  • 319
  • 2
    It'd be nice if gdb offered a shortcut for "watch just the final target" – Craig Ringer Nov 18 '14 at 07:31
  • 3
    @CraigRinger: [It does.](http://stackoverflow.com/questions/25938830/gdb-how-to-force-a-watchpoint-to-not-be-deleted-after-a-function-returned) `watch -location pObject->dprice` – Alcaro Feb 12 '17 at 19:55
  • 1
    @Alcaro: 1. is this supported in any version of gdb? 2. this is a good enough answer that it should be in a standalone answer, and not as the comment to my answer. – Nathan Fellman Feb 14 '17 at 09:10
  • (1) Tested to work on GDB 7.7.1, Ubuntu 14.04. I'll download some tarballs and check exactly when it appeared. (And I suspect -location was the default prior to it being an explicit flag. Pretty surprising behavior.) (2) Can do. – Alcaro Feb 15 '17 at 12:34