Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Setting GDB hardware watchpoint/how to set software watchpoint

Tags:

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?

like image 829
c-urchin Avatar asked Aug 12 '10 18:08

c-urchin


People also ask

How do I add a watchpoint in GDB?

If GDB cannot set a hardware watchpoint, it sets a software watchpoint, which executes more slowly and reports the change in value at the next statement, not the instruction, after the change occurs. You can force GDB to use only software watchpoints with the set can-use-hw-watchpoints 0 command.

What is hardware watchpoint?

Hardware watchpoints - allow execution to halt when a read or write access is made to a data variable address. Count Event - can be used to measure clock cycles between two points in the code. Data Access Count - can be used to determine the number of times a data variable address has been accessed.

How do you set breakpoints in GDB?

Setting breakpoints A breakpoint is like a stop sign in your code -- whenever gdb gets to a breakpoint it halts execution of your program and allows you to examine it. To set breakpoints, type "break [filename]:[linenumber]". For example, if you wanted to set a breakpoint at line 55 of main.


2 Answers

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.

like image 171
karlphillip Avatar answered Oct 01 '22 20:10

karlphillip


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.)

like image 34
Alcaro Avatar answered Oct 01 '22 19:10

Alcaro