From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 19977 invoked by alias); 11 Nov 2005 18:19:44 -0000 Mailing-List: contact gdb-help@sourceware.org; run by ezmlm Precedence: bulk List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-owner@sourceware.org Received: (qmail 19953 invoked by uid 22791); 11 Nov 2005 18:19:42 -0000 Received: from romy.inter.net.il (HELO romy.inter.net.il) (192.114.186.66) by sourceware.org (qpsmtpd/0.30-dev) with ESMTP; Fri, 11 Nov 2005 18:19:42 +0000 Received: from HOME-C4E4A596F7 (IGLD-84-228-244-241.inter.net.il [84.228.244.241]) by romy.inter.net.il (MOS 3.5.8-GR) with ESMTP id CYR01939 (AUTH halo1); Fri, 11 Nov 2005 20:19:38 +0200 (IST) Date: Fri, 11 Nov 2005 18:19:00 -0000 Message-Id: From: Eli Zaretskii To: Vladimir Prus CC: gdb@sources.redhat.com In-reply-to: <200511111622.01337.ghost@cs.msu.su> (message from Vladimir Prus on Fri, 11 Nov 2005 16:22:00 +0300) Subject: Re: read watchpoints ignored? Reply-to: Eli Zaretskii References: <200511111622.01337.ghost@cs.msu.su> X-SW-Source: 2005-11/txt/msg00231.txt.bz2 > From: Vladimir Prus > Date: Fri, 11 Nov 2005 16:22:00 +0300 > > (gdb) b main > Breakpoint 1 at 0x80483a4: file rw.cpp, line 8. > (gdb) r > Starting program: /tmp/a.out > > Breakpoint 1, main () at rw.cpp:8 > 8 a = 10; > (gdb) rwatch a > Hardware read watchpoint 2: a > (gdb) c > Continuing. > Hardware read watchpoint 2: a > > Value = 10 > 0x080483bd in main () at rw.cpp:11 > 11 c = a; > > Expected result: gdb stops on "b = a" line. > Actual result: gdb stops on "c = a". On what platform was that, and with which version of GDB? Also, what debug info format was used by the compiler in your case, and what compiler switches were used to compile and link the program? I will assume that this is on some x86 platform; if not, the rest of this message might not be useful. First, I cannot reproduce this problem with the MS-Windows port of GCC; the session transcript I saw is at the end of this message. On Debian GNU/Linux, I can reproduce the problem, but it seems that it is a side effect of another problem: the breakpoint set by "b main" stops the program too late. Observe: ~$ gdb ./rwt GNU gdb 6.1-debian Copyright 2004 Free Software Foundation, Inc. GDB is free software, covered by the GNU General Public License, and you are welcome to change it and/or distribute copies of it under certain conditions. Type "show copying" to see the conditions. There is absolutely no warranty for GDB. Type "show warranty" for details. This GDB was configured as "i386-linux"...Using host libthread_db library "/lib/tls/libthread_db.so.1". (gdb) info address main Symbol "main" is a function at address 0x8048364. (gdb) b *0x8048364 Breakpoint 1 at 0x8048364: file rwt.c, line 6. (gdb) r Starting program: /home/e/eliz/rwt Breakpoint 1, main () at rwt.c:6 6 { (gdb) rwatch a Hardware read watchpoint 2: a (gdb) c Continuing. Here I am Hardware read watchpoint 2: a Value = 10 0x0804838f in main () at rwt.c:10 10 b = a; (gdb) c Continuing. Hardware read watchpoint 2: a Value = 10 0x08048399 in main () at rwt.c:11 11 c = a; Note that a breakpoint set by address now stops the program at the right place: the opening brace of the main function. In your session (and also here, if I use "b main"), it stopped on line 7, not line 6. Can someone please tell why "b main" stops the program one line too late? So I'm guessing that the problem happens because GDB misses the data write into a in line 7, and thus doesn't take notice that a was assigned the value 10. That's why it gets confused when "b = a;" reads from a. > Here's why it happens. When breakpoint is set, gdb reads the current value > of 'a', which is zero. After continue, a is assigned the value of '10', and > then first read watchpoint fires (on "b = a"). We arrive to > "bpstat_stop_status" (breakpoint.c), which has the following code: > > > else if (b->type == bp_read_watchpoint || > b->type == bp_access_watchpoint) > { > ... > if (found) > { > ... > int e = catch_errors (watchpoint_check, bs, message, > RETURN_MASK_ALL); > switch (e) > { > ....... > case WP_VALUE_CHANGED: > if (b->type == bp_read_watchpoint) > { > /* Don't stop: read watchpoints shouldn't fire if > the value has changed. This is for targets > which cannot set read-only watchpoints. */ > bs->print_it = print_it_noop; > bs->stop = 0; > continue; > } > > > Since value of 'a' was changed by the "a = 10" line, "watchpoint_check" > returns "WP_VALUE_CHANGED", and reporting of watchpoint is completely > suppressed. > > Questions: > 1. Is this a bug? No, I don't think so. The theory behind the read watchpoint support on x86 is that GDB should also see the data writes into the watched variable, and thus always track its current value. This is because x86 debug hardware doesn't support read watchpoints, it only supports data-write watchpoints and access (read or write) watchpoints. So GDB _emulates_ read watchpoints on x86 by setting an access watchpoint, and monitoring value changes with the code you presented above. Access watchpoint should trigger when the address is written by the "a = 10;" line, at which point GDB should get control, record the new value, then continue the debuggee without announcing the watchpoint (since the value changed). Later, when "b = a;" reads from a, the access watchpoint fires again, but this time the value didn't change, so the watchpoint should be announced. Can you see which part of the above doesn't work, and why? > 2. Can this bug be fixed by removing this inner > > if (b->type == bp_read_wathcpoint) > > statement? I hope the description above explains why not. > This will cause watchpoints to trigger more often > on those target that don't have "read-only watchpoints", but > there will be no risk of missing watchpoint. Not only does it cause extra read watchpoints, it wreaks a complete havoc in all but the most simple situations. For example, consider the case that two or more watchpoints are set on the same address, each one with a different condition. Without the above code, read watchpoints are unusable on x86, and, worse, any use of read watchpoints completely disrupts all other hardware watchpoints, because the facilities used by GDB to find out which watchpoints fired are very limited, so it gets completely confused when more than one watchpoint seems to fire. > And I think missed > watchpoint is more harm then spurious watchpoint. Both of these harmful, so we should fix this problem. But not at a price of going back to the mess we had back before this condition was added; that's a price which is too heavy, IMO. Here's the GDB session on MS-Windows. As you see, "b main" stops at line 6, the opening brace of the main function, and then the watchpoint works as you expected. D:\usr\eli>gdb ./rwt.exe GNU gdb 6.3 Copyright 2004 Free Software Foundation, Inc. GDB is free software, covered by the GNU General Public License, and you are welcome to change it and/or distribute copies of it under certain conditions. Type "show copying" to see the conditions. There is absolutely no warranty for GDB. Type "show warranty" for details. This GDB was configured as "i686-pc-mingw32"... (gdb) b main Breakpoint 1 at 0x4012b5: file rwt.c, line 6. (gdb) r Starting program: D:\usr\eli/./rwt.exe Breakpoint 1, main () at rwt.c:6 6 { (gdb) rwatch a Hardware read watchpoint 2: a (gdb) c Continuing. Here I am Hardware read watchpoint 2: a Value = 10 0x004012d5 in main () at rwt.c:10 10 b = a; (gdb) c Continuing. Hardware read watchpoint 2: a Value = 10 0x004012df in main () at rwt.c:11 11 c = a; (gdb)