From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 17567 invoked by alias); 21 Nov 2009 09:41:01 -0000 Received: (qmail 17532 invoked by uid 22791); 21 Nov 2009 09:40:59 -0000 X-SWARE-Spam-Status: No, hits=-1.7 required=5.0 tests=AWL,BAYES_00,SARE_MSGID_LONG40,SPF_PASS X-Spam-Check-By: sourceware.org Received: from mail-px0-f189.google.com (HELO mail-px0-f189.google.com) (209.85.216.189) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Sat, 21 Nov 2009 09:39:55 +0000 Received: by pxi27 with SMTP id 27so2791981pxi.25 for ; Sat, 21 Nov 2009 01:39:54 -0800 (PST) MIME-Version: 1.0 Received: by 10.142.65.24 with SMTP id n24mr50010wfa.312.1258796394099; Sat, 21 Nov 2009 01:39:54 -0800 (PST) In-Reply-To: <4B06DAB2.7090409@vmware.com> References: <4AECE12F.3000704@vmware.com> <4AF31C1F.2000405@vmware.com> <200911051909.40796.pedro@codesourcery.com> <200911120027.03426.pedro@codesourcery.com> <4B06DAB2.7090409@vmware.com> From: Hui Zhu Date: Sat, 21 Nov 2009 09:41:00 -0000 Message-ID: Subject: Re: [RFA] Fix hw watchpoints in process record. To: Michael Snyder , Pedro Alves Cc: "gdb-patches@sourceware.org" Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: quoted-printable X-IsSubscribed: yes Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org X-SW-Source: 2009-11/txt/msg00462.txt.bz2 Hi guys, There are some patches about hw breakpoint are running on maillist. If you don't mind, I suggest we wait until they OK. Thanks, Hui On Sat, Nov 21, 2009 at 02:06, Michael Snyder wrote: > OK, I withdraw my patch in favor of this one. > If Hui likes it, let's check it in. > > Thanks for your help, Pedro! > > Pedro Alves wrote: >> >> On Thursday 05 November 2009 19:09:40, Pedro Alves wrote: >> >>> this assumes the target/arch has continuable watchpoints, >>> like x86/x86_64. =A0You'll see this misbehave on mips, when Hui >>> contributes the support. >>> >>> You're evaluating the watchpoint expression on every event --- I >>> have a feeling it would make more sense to decouple precord from >>> that, like all other targets are decoupled. =A0That is, have precord >>> check for low level watchpoint triggers --- given [addr,length,type] >>> low level watchpoints --- when memory changes (at record_mem_entry time= ), >>> instead of evaluating the whole high-level watchpoint expression. >>> >>> [IMO, we should mostly think of precord as just another a >>> simulator that mostly only interfaces gdb's core through >>> the target_ methods.] >> >> >> Sure enough, trying a simple test like this shows >> breakage: >> >> =A01 =A0 =A0 =A0 #include >> =A02 >> =A03 =A0 =A0 =A0 int glob; >> =A04 >> =A05 =A0 =A0 =A0 int main () >> =A06 =A0 =A0 =A0 { >> =A07 =A0 =A0 =A0 =A0 int loc =3D -1; >> =A08 >> =A09 =A0 =A0 =A0 =A0 while (1) >> =A010 =A0 =A0 =A0 =A0 =A0{ >> =A011 =A0 =A0 =A0 =A0 =A0 =A0printf ("glob =3D %d\n", glob); >> =A012 =A0 =A0 =A0 =A0 =A0 =A0glob++; >> =A013 =A0 =A0 =A0 =A0 =A0 =A0printf ("loc =3D %d\n", loc); >> =A014 =A0 =A0 =A0 =A0 =A0 =A0loc++; >> =A015 =A0 =A0 =A0 =A0 =A0} >> =A016 =A0 =A0 =A0} >> >> >> =A0(gdb) start >> =A0Temporary breakpoint 1, main () at test.c:7 >> =A07 =A0 =A0 =A0 =A0 int loc =3D -1; >> =A0(gdb) record >> =A0(gdb) watch loc >> =A0During symbol reading, incomplete CFI data; unspecified registers (e.= g., >> rax) at 0x40049c. >> =A0Hardware watchpoint 2: loc >> =A0(gdb) watch glob >> =A0Hardware watchpoint 3: glob >> =A0(gdb) n >> =A0Hardware watchpoint 2: loc >> >> =A0Old value =3D 0 >> =A0New value =3D -1 >> =A0main () at test.c:11 >> =A011 =A0 =A0 =A0 =A0 =A0 =A0printf ("glob =3D %d\n", glob); >> =A0(gdb) >> =A0glob =3D 0 >> =A012 =A0 =A0 =A0 =A0 =A0 =A0glob++; >> =A0(gdb) >> =A0Hardware watchpoint 3: glob >> >> =A0 >> >> =A0(gdb) reverse-continue >> =A0Continuing. >> =A0Hardware watchpoint 2: loc >> >> =A0Old value =3D 1 >> =A0New value =3D 0 >> =A0main () at test.c:14 >> =A014 =A0 =A0 =A0 =A0 =A0 =A0loc++; >> =A0(gdb) reverse-continue >> =A0Continuing. >> >> =A0Watchpoint 2 deleted because the program has left the block in >> =A0which its expression is valid. >> >> =A0Watchpoint 2 deleted because the program has left the block in >> =A0which its expression is valid. >> =A00x00007ffff7aebd15 in _IO_file_write () from /lib/libc.so.6 >> =A0(gdb) >> >> Nope, it hasn't left the block, I was continue'ing in the >> loop... =A0The trouble relates to the fact that precord forces >> single-stepping --- which reverse single-steps into the >> printf call --- and, watchpoint_check wants to check >> if the watchpoints are in scope. >> >> >> Here's the alternative implementation I was suggesting last >> week. =A0It ends up being simpler and more efficient, in fact. >> We checking for watchpoint hits less often, and the check is >> much cheaper since it doesn't do any extra reads, create >> values, or evaluate expressions. >> >> I also didn't see any need for set_executing calls, which >> were a sign of trouble. >> >> I've added a comment indicating what needs to be done >> to support targets/archs with non-continuable watchpoints >> (just check for inserted watchpoints that should trigger, >> before actually doing any memory change) >> >> An alternative to that is to expose better the continuable vs >> steppable watchpoints at the target layer, so that record can >> always claim continuable watchpoints while replaying, dispite >> what the target beneath or the arch supports. >> >> >> This passed the new watch-reverse.exp and watch-precsave.exp. >> Playing a bit with the small test shown above didn't show >> any issue. =A0Want to give it a try? >> >> -- >> Pedro Alves >> >> >> --- >> =A0gdb/NEWS =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 = =A0 =A0 =A0 | =A0 =A04 + >> =A0gdb/breakpoint.c =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 = =A0 | =A0 33 ++++++++++ >> =A0gdb/breakpoint.h =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 = =A0 | =A0 =A05 + >> =A0gdb/record.c =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 = =A0 =A0 | =A0 68 >> +++++++++++++++++++--- >> =A0gdb/testsuite/gdb.reverse/watch-precsave.exp | =A0 80 >> ++++++++++++++++++++++++++ >> =A0gdb/testsuite/gdb.reverse/watch-reverse.exp =A0| =A0 82 >> ++++++++++++++++++++++++++- >> =A06 files changed, 260 insertions(+), 12 deletions(-) >> >> Index: src/gdb/breakpoint.c >> =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D >> --- src.orig/gdb/breakpoint.c =A0 2009-11-12 00:06:31.000000000 +0000 >> +++ src/gdb/breakpoint.c =A0 =A0 =A0 =A02009-11-12 00:06:55.000000000 +0= 000 >> @@ -3063,6 +3063,39 @@ watchpoints_triggered (struct target_wai >> =A0 return 1; >> =A0} >> >> +int >> +hardware_watchpoint_inserted_in_range (CORE_ADDR addr, ULONGEST len) >> +{ >> + =A0struct breakpoint *bpt; >> + >> + =A0ALL_BREAKPOINTS (bpt) >> + =A0 =A0{ >> + =A0 =A0 =A0struct bp_location *loc; >> + >> + =A0 =A0 =A0if (bpt->type !=3D bp_hardware_watchpoint >> + =A0 =A0 =A0 =A0 && bpt->type !=3D bp_access_watchpoint) >> + =A0 =A0 =A0 continue; >> + >> + =A0 =A0 =A0if (!breakpoint_enabled (bpt)) >> + =A0 =A0 =A0 continue; >> + >> + =A0 =A0 =A0for (loc =3D bpt->loc; loc; loc =3D loc->next) >> + =A0 =A0 =A0 if (loc->inserted) >> + =A0 =A0 =A0 =A0 { >> + =A0 =A0 =A0 =A0 =A0 CORE_ADDR l, h; >> + >> + =A0 =A0 =A0 =A0 =A0 /* Check for interception. =A0*/ >> + >> + =A0 =A0 =A0 =A0 =A0 l =3D max (loc->address, addr); >> + =A0 =A0 =A0 =A0 =A0 h =3D min (loc->address + loc->length, addr + len); >> + >> + =A0 =A0 =A0 =A0 =A0 if (l < h) >> + =A0 =A0 =A0 =A0 =A0 =A0 return 1; >> + =A0 =A0 =A0 =A0 } >> + =A0 =A0} >> + =A0return 0; >> +} >> + >> =A0/* Possible return values for watchpoint_check (this can't be an enum >> =A0 =A0because of check_errors). =A0*/ >> =A0/* The watchpoint has been deleted. =A0*/ >> Index: src/gdb/breakpoint.h >> =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D >> --- src.orig/gdb/breakpoint.h =A0 2009-11-12 00:06:31.000000000 +0000 >> +++ src/gdb/breakpoint.h =A0 =A0 =A0 =A02009-11-12 00:06:55.000000000 +0= 000 >> @@ -978,4 +978,9 @@ extern struct breakpoint *get_tracepoint >> =A0 =A0is newly allocated; the caller should free when done with it. =A0= */ >> =A0extern VEC(breakpoint_p) *all_tracepoints (void); >> >> +/* Returns true if there's a hardware watchpoint or access watchpoint >> + =A0 inserted in the range defined by ADDR and LEN. =A0*/ >> +extern int hardware_watchpoint_inserted_in_range (CORE_ADDR addr, >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 = =A0 =A0 =A0 =A0 =A0 =A0 =A0 ULONGEST len); >> + >> =A0#endif /* !defined (BREAKPOINT_H) */ >> Index: src/gdb/record.c >> =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D >> --- src.orig/gdb/record.c =A0 =A0 =A0 2009-11-12 00:06:31.000000000 +0000 >> +++ src/gdb/record.c =A0 =A02009-11-12 00:06:55.000000000 +0000 >> @@ -224,6 +224,7 @@ static int (*record_beneath_to_insert_br >> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 = =A0 =A0 =A0 =A0 =A0 =A0 =A0 struct bp_target_info >> *); >> =A0static int (*record_beneath_to_remove_breakpoint) (struct gdbarch *, >> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 = =A0 =A0 =A0 =A0 =A0 =A0 =A0 struct bp_target_info >> *); >> +static int (*record_beneath_to_stopped_by_watchpoint) (void); >> >> =A0/* Alloc and free functions for record_reg, record_mem, and record_end >> =A0 =A0entries. =A0*/ >> @@ -673,6 +674,9 @@ record_gdb_operation_disable_set (void) >> =A0 return old_cleanups; >> =A0} >> >> +/* Flag set to TRUE for target_stopped_by_watchpoint. =A0*/ >> +static int record_hw_watchpoint =3D 0; >> + >> =A0/* Execute one instruction from the record log. =A0Each instruction in >> =A0 =A0the log will be represented by an arbitrary sequence of register >> =A0 =A0entries and memory entries, followed by an 'end' entry. =A0*/ >> @@ -739,7 +743,21 @@ record_exec_insn (struct regcache *regca >> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0entry->u.= mem.len); >> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 } >> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 else >> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0memcpy (record_get_loc (entry), mem= , entry->u.mem.len); >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 { >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 memcpy (record_get_loc (entry), me= m, >> entry->u.mem.len); >> + >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 /* We've changed memory --- check = if a hardware >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0watchpoint should trap. =A0= Note that this >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0presently assumes the targe= t beneath supports >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0continuable watchpoints. = =A0On non-continuable >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0watchpoints target, we'll w= ant to check this >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0_before_ actually doing the= memory change, and >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0not doing the change at all= if the watchpoint >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0traps. =A0*/ >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (hardware_watchpoint_inserted_i= n_range >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 (entry->u.mem.addr, entry-= >u.mem.len)) >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 record_hw_watchpoint =3D 1; >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 } >> =A0 =A0 =A0 =A0 =A0 =A0 =A0 } >> =A0 =A0 =A0 =A0 =A0 } >> =A0 =A0 =A0 } >> @@ -770,6 +788,7 @@ static int (*tmp_to_insert_breakpoint) ( >> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 = =A0 =A0struct bp_target_info *); >> =A0static int (*tmp_to_remove_breakpoint) (struct gdbarch *, >> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 = =A0 =A0struct bp_target_info *); >> +static int (*tmp_to_stopped_by_watchpoint) (void); >> >> =A0static void record_restore (void); >> >> @@ -894,6 +913,8 @@ record_open (char *name, int from_tty) >> =A0 =A0 =A0 =A0tmp_to_insert_breakpoint =3D t->to_insert_breakpoint; >> =A0 =A0 =A0 if (!tmp_to_remove_breakpoint) >> =A0 =A0 =A0 =A0tmp_to_remove_breakpoint =3D t->to_remove_breakpoint; >> + =A0 =A0 =A0if (!tmp_to_stopped_by_watchpoint) >> + =A0 =A0 =A0 tmp_to_stopped_by_watchpoint =3D t->to_stopped_by_watchpoi= nt; >> =A0 =A0 } >> =A0 if (!tmp_to_xfer_partial) >> =A0 =A0 error (_("Could not find 'to_xfer_partial' method on the target >> stack.")); >> @@ -915,6 +936,7 @@ record_open (char *name, int from_tty) >> =A0 record_beneath_to_xfer_partial =3D tmp_to_xfer_partial; >> =A0 record_beneath_to_insert_breakpoint =3D tmp_to_insert_breakpoint; >> =A0 record_beneath_to_remove_breakpoint =3D tmp_to_remove_breakpoint; >> + =A0record_beneath_to_stopped_by_watchpoint =3D tmp_to_stopped_by_watch= point; >> >> =A0 if (current_target.to_stratum =3D=3D core_stratum) >> =A0 =A0 record_core_open_1 (name, from_tty); >> @@ -1069,14 +1091,23 @@ record_wait (struct target_ops *ops, >> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0{ >> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0struct regcache *regcache; >> >> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 /* Yes -- check if there is a breakpoi= nt. =A0*/ >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 /* Yes -- this is likely our single-st= ep finishing, >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0but check if there's any reason= the core would be >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0interested in the event. =A0*/ >> + >> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0registers_changed (); >> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0regcache =3D get_current_regcache (); >> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0tmp_pc =3D regcache_read_pc (regcache= ); >> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (breakpoint_inserted_here_p (get_re= gcache_aspace >> (regcache), >> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 = =A0 =A0 =A0 =A0 =A0 =A0 =A0 tmp_pc)) >> + >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (target_stopped_by_watchpoint ()) >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 { >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 /* Always interested in watchp= oints. =A0*/ >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 } >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 else if (breakpoint_inserted_here_p (g= et_regcache_aspace >> (regcache), >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 = =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0tmp_pc)) >> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0{ >> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 /* There is a breakpoint. =A0G= DB will want to stop. >> =A0*/ >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 /* There is a breakpoint here.= =A0Let the core >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0handle it. =A0*/ >> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0struct gdbarch *gdbarch =3D g= et_regcache_arch >> (regcache); >> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0CORE_ADDR decr_pc_after_break >> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=3D gdbarch_decr_pc_after= _break (gdbarch); >> @@ -1086,10 +1117,8 @@ record_wait (struct target_ops *ops, >> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0} >> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0else >> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0{ >> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 /* There is not a breakpoint, = and gdb is not >> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0stepping, therefore gdb= will not stop. >> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0Therefore we will not r= eturn to gdb. >> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0Record the insn and res= ume. =A0*/ >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 /* This must be a single-step = trap. =A0Record the >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0insn and issue another = step. =A0*/ >> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0if (!do_record_message (regca= che, TARGET_SIGNAL_0)) >> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0break; >> >> @@ -1116,6 +1145,7 @@ record_wait (struct target_ops *ops, >> =A0 =A0 =A0 struct cleanup *old_cleanups =3D make_cleanup (record_wait_c= leanups, >> 0); >> =A0 =A0 =A0 CORE_ADDR tmp_pc; >> >> + =A0 =A0 =A0record_hw_watchpoint =3D 0; >> =A0 =A0 =A0 status->kind =3D TARGET_WAITKIND_STOPPED; >> >> =A0 =A0 =A0 /* Check breakpoint when forward execute. =A0*/ >> @@ -1219,6 +1249,14 @@ record_wait (struct target_ops *ops, >> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 = =A0 =A0 =A0 gdbarch_decr_pc_after_break >> (gdbarch)); >> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0continue_flag =3D 0; >> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0} >> + >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (record_hw_watchpoint) >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 { >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (record_debug) >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 fprintf_unfiltered (gdb_st= dlog, >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 = =A0 =A0 =A0 =A0 "Process record: hit hw >> watchpoint.\n"); >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 continue_flag =3D 0; >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 } >> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0/* Check target signal */ >> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0if (record_list->u.end.sigval !=3D TA= RGET_SIGNAL_0) >> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0/* FIXME: better way to check */ >> @@ -1260,6 +1298,16 @@ replay_out: >> =A0 return inferior_ptid; >> =A0} >> >> +/* to_stopped_by_watchpoint method */ >> +static int >> +record_stopped_by_watchpoint (void) >> +{ >> + =A0if (RECORD_IS_REPLAY) >> + =A0 =A0return record_hw_watchpoint; >> + =A0else >> + =A0 =A0return record_beneath_to_stopped_by_watchpoint (); >> +} >> + >> =A0/* "to_disconnect" method for process record target. =A0*/ >> >> =A0static void >> @@ -1545,6 +1593,7 @@ init_record_ops (void) >> =A0 record_ops.to_remove_breakpoint =3D record_remove_breakpoint; >> =A0 record_ops.to_can_execute_reverse =3D record_can_execute_reverse; >> =A0 record_ops.to_stratum =3D record_stratum; >> + =A0record_ops.to_stopped_by_watchpoint =3D record_stopped_by_watchpoin= t; >> =A0 record_ops.to_magic =3D OPS_MAGIC; >> =A0} >> >> @@ -1750,6 +1799,7 @@ init_record_core_ops (void) >> =A0 record_core_ops.to_can_execute_reverse =3D record_can_execute_revers= e; >> =A0 record_core_ops.to_has_execution =3D record_core_has_execution; >> =A0 record_core_ops.to_stratum =3D record_stratum; >> + =A0record_core_ops.to_stopped_by_watchpoint =3D >> record_stopped_by_watchpoint; >> =A0 record_core_ops.to_magic =3D OPS_MAGIC; >> =A0} >> >> Index: src/gdb/NEWS >> =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D >> --- src.orig/gdb/NEWS =A0 2009-11-12 00:06:31.000000000 +0000 >> +++ src/gdb/NEWS =A0 =A0 =A0 =A02009-11-12 00:06:55.000000000 +0000 >> @@ -71,6 +71,10 @@ show follow-exec-mode >> =A0 creates a new one. =A0This is useful to be able to restart the old >> =A0 executable after the inferior having done an exec call. >> >> +* Bug fixes >> + >> +Process record now works correctly with hardware watchpoints. >> + >> =A0*** Changes in GDB 7.0 >> >> =A0* GDB now has an interface for JIT compilation. =A0Applications that >> Index: src/gdb/testsuite/gdb.reverse/watch-reverse.exp >> =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D >> --- src.orig/gdb/testsuite/gdb.reverse/watch-reverse.exp =A0 =A0 =A0 =A0= 2009-11-12 >> 00:06:31.000000000 +0000 >> +++ src/gdb/testsuite/gdb.reverse/watch-reverse.exp =A0 =A0 2009-11-12 >> 00:10:23.000000000 +0000 >> @@ -38,8 +38,8 @@ if [target_info exists gdb,use_precord] >> =A0 =A0 # FIXME: command ought to acknowledge, so we can test if it succ= eeded. >> =A0} >> >> -# Only software watchpoints can be used in reverse >> -gdb_test "set can-use-hw-watchpoints 0" "" "" >> +# Test software watchpoints >> +gdb_test "set can-use-hw-watchpoints 0" "" "disable hw watchpoints" >> >> =A0gdb_test "break marker1" \ >> =A0 =A0 "Breakpoint $decimal at $hex: file .*$srcfile, line $decimal.*" \ >> @@ -122,3 +122,81 @@ gdb_test "continue" \ >> =A0gdb_test "continue" \ >> =A0 =A0 ".*\[Ww\]atchpoint.*ival3.*Old value =3D 0.*New value =3D -1.*iv= al3 =3D >> count; ival4 =3D count;.*" \ >> =A0 =A0 "watchpoint hit in reverse, fifth time" >> + >> +gdb_test "set can-use-hw-watchpoints 1" "" "enable hw watchpoints" >> + >> +### >> +### >> +### >> + >> +# FIXME 'set exec-dir' command should give some output so we can test. >> +gdb_test "set exec-direction forward" "" "set forward" >> + >> +# Continue until first change, from -1 to 0 >> + >> +gdb_test "continue" \ >> + =A0 =A0".*\[Ww\]atchpoint.*ival3.*Old value =3D -1.*New value =3D 0.*i= val3 =3D >> count; ival4 =3D count;.*" \ >> + =A0 =A0"watchpoint hit, forward replay, first time" >> + >> +# Continue until the next change, from 0 to 1. >> +gdb_test "continue" \ >> + =A0 =A0".*\[Ww\]atchpoint.*ival3.*Old value =3D 0.*New value =3D 1.*iv= al3 =3D >> count; ival4 =3D count;.*" \ >> + =A0 =A0"watchpoint hit, forward replay, second time" >> + >> +# Continue until the next change, from 1 to 2. >> +gdb_test "continue" \ >> + =A0 =A0".*\[Ww\]atchpoint.*ival3.*Old value =3D 1.*New value =3D 2.*iv= al3 =3D >> count; ival4 =3D count;.*" \ >> + =A0 =A0"watchpoint hit, forward replay, third time" >> + >> +# Continue until the next change, from 2 to 3. >> +gdb_test "continue" \ >> + =A0 =A0".*\[Ww\]atchpoint.*ival3.*Old value =3D 2.*New value =3D 3.*iv= al3 =3D >> count; ival4 =3D count;.*" \ >> + =A0 =A0"watchpoint hit, forward replay, fourth time" >> + >> +# Continue until the next change, from 3 to 4. >> +# Note that this one is outside the loop. >> + >> +gdb_test "continue" \ >> + =A0 =A0".*\[Ww\]atchpoint.*ival3.*Old value =3D 3.*New value =3D 4.*iv= al3 =3D >> count; ival4 =3D count;.*" \ >> + =A0 =A0"watchpoint hit, forward replay, fifth time" >> + >> +# Continue until we hit the finishing marker function. >> +# Make sure we hit no more watchpoints. >> + >> +gdb_test "continue" "marker2 .*" "replay forward to marker2" >> + >> +### >> +### >> +### >> + >> +# FIXME 'set exec-dir' command should give some output so we can test. >> +gdb_test "set exec-direction reverse" "" "set reverse" >> + >> +# Reverse until the previous change, from 4 to 3 >> +# Note that this one is outside the loop >> + >> +gdb_test "continue" \ >> + =A0 =A0".*\[Ww\]atchpoint.*ival3.*Old value =3D 4.*New value =3D 3.*iv= al3 =3D >> count; ival4 =3D count;.*" \ >> + =A0 =A0"watchpoint hit in reverse, HW, first time" >> + >> +# Reverse until the previous change, from 3 to 2. >> +gdb_test "continue" \ >> + =A0 =A0".*\[Ww\]atchpoint.*ival3.*Old value =3D 3.*New value =3D 2.*iv= al3 =3D >> count; ival4 =3D count;.*" \ >> + =A0 =A0"watchpoint hit in reverse, HW, second time" >> + >> +# Reverse until the previous change, from 2 to 1. >> +gdb_test "continue" \ >> + =A0 =A0".*\[Ww\]atchpoint.*ival3.*Old value =3D 2.*New value =3D 1.*iv= al3 =3D >> count; ival4 =3D count;.*" \ >> + =A0 =A0"watchpoint hit in reverse, HW, third time" >> + >> +# Reverse until the previous change, from 1 to 0. >> +gdb_test "continue" \ >> + =A0 =A0".*\[Ww\]atchpoint.*ival3.*Old value =3D 1.*New value =3D 0.*iv= al3 =3D >> count; ival4 =3D count;.*" \ >> + =A0 =A0"watchpoint hit in reverse, HW, fourth time" >> + >> +# Reverse until first change, from 0 to -1 >> + >> +gdb_test "continue" \ >> + =A0 =A0".*\[Ww\]atchpoint.*ival3.*Old value =3D 0.*New value =3D -1.*i= val3 =3D >> count; ival4 =3D count;.*" \ >> + =A0 =A0"watchpoint hit in reverse, HW, fifth time" >> + >> Index: src/gdb/testsuite/gdb.reverse/watch-precsave.exp >> =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D >> --- src.orig/gdb/testsuite/gdb.reverse/watch-precsave.exp =A0 =A0 =A0 20= 09-11-12 >> 00:06:31.000000000 +0000 >> +++ src/gdb/testsuite/gdb.reverse/watch-precsave.exp =A0 =A02009-11-12 >> 00:10:07.000000000 +0000 >> @@ -1,4 +1,4 @@ >> -# Copyright 2008, 2009 Free Software Foundation, Inc. >> +# Copyright 2009 Free Software Foundation, Inc. >> >> =A0# This program is free software; you can redistribute it and/or modify >> =A0# it under the terms of the GNU General Public License as published by >> @@ -140,3 +140,81 @@ gdb_test "continue" \ >> =A0gdb_test "continue" \ >> =A0 =A0 ".*\[Ww\]atchpoint.*ival3.*Old value =3D 0.*New value =3D -1.*iv= al3 =3D >> count; ival4 =3D count;.*" \ >> =A0 =A0 "watchpoint hit in reverse, fifth time" >> + >> +gdb_test "set can-use-hw-watchpoints 1" "" "enable hw watchpoints" >> + >> +### >> +### >> +### >> + >> +# FIXME 'set exec-dir' command should give some output so we can test. >> +gdb_test "set exec-direction forward" "" "set forward" >> + >> +# Continue until first change, from -1 to 0 >> + >> +gdb_test "continue" \ >> + =A0 =A0".*\[Ww\]atchpoint.*ival3.*Old value =3D -1.*New value =3D 0.*i= val3 =3D >> count; ival4 =3D count;.*" \ >> + =A0 =A0"watchpoint hit, forward replay, first time" >> + >> +# Continue until the next change, from 0 to 1. >> +gdb_test "continue" \ >> + =A0 =A0".*\[Ww\]atchpoint.*ival3.*Old value =3D 0.*New value =3D 1.*iv= al3 =3D >> count; ival4 =3D count;.*" \ >> + =A0 =A0"watchpoint hit, forward replay, second time" >> + >> +# Continue until the next change, from 1 to 2. >> +gdb_test "continue" \ >> + =A0 =A0".*\[Ww\]atchpoint.*ival3.*Old value =3D 1.*New value =3D 2.*iv= al3 =3D >> count; ival4 =3D count;.*" \ >> + =A0 =A0"watchpoint hit, forward replay, third time" >> + >> +# Continue until the next change, from 2 to 3. >> +gdb_test "continue" \ >> + =A0 =A0".*\[Ww\]atchpoint.*ival3.*Old value =3D 2.*New value =3D 3.*iv= al3 =3D >> count; ival4 =3D count;.*" \ >> + =A0 =A0"watchpoint hit, forward replay, fourth time" >> + >> +# Continue until the next change, from 3 to 4. >> +# Note that this one is outside the loop. >> + >> +gdb_test "continue" \ >> + =A0 =A0".*\[Ww\]atchpoint.*ival3.*Old value =3D 3.*New value =3D 4.*iv= al3 =3D >> count; ival4 =3D count;.*" \ >> + =A0 =A0"watchpoint hit, forward replay, fifth time" >> + >> +# Continue until we hit the finishing marker function. >> +# Make sure we hit no more watchpoints. >> + >> +gdb_test "continue" "marker2 .*" "replay forward to marker2" >> + >> +### >> +### >> +### >> + >> +# FIXME 'set exec-dir' command should give some output so we can test. >> +gdb_test "set exec-direction reverse" "" "set reverse" >> + >> +# Reverse until the previous change, from 4 to 3 >> +# Note that this one is outside the loop >> + >> +gdb_test "continue" \ >> + =A0 =A0".*\[Ww\]atchpoint.*ival3.*Old value =3D 4.*New value =3D 3.*iv= al3 =3D >> count; ival4 =3D count;.*" \ >> + =A0 =A0"watchpoint hit in reverse, HW, first time" >> + >> +# Reverse until the previous change, from 3 to 2. >> +gdb_test "continue" \ >> + =A0 =A0".*\[Ww\]atchpoint.*ival3.*Old value =3D 3.*New value =3D 2.*iv= al3 =3D >> count; ival4 =3D count;.*" \ >> + =A0 =A0"watchpoint hit in reverse, HW, second time" >> + >> +# Reverse until the previous change, from 2 to 1. >> +gdb_test "continue" \ >> + =A0 =A0".*\[Ww\]atchpoint.*ival3.*Old value =3D 2.*New value =3D 1.*iv= al3 =3D >> count; ival4 =3D count;.*" \ >> + =A0 =A0"watchpoint hit in reverse, HW, third time" >> + >> +# Reverse until the previous change, from 1 to 0. >> +gdb_test "continue" \ >> + =A0 =A0".*\[Ww\]atchpoint.*ival3.*Old value =3D 1.*New value =3D 0.*iv= al3 =3D >> count; ival4 =3D count;.*" \ >> + =A0 =A0"watchpoint hit in reverse, HW, fourth time" >> + >> +# Reverse until first change, from 0 to -1 >> + >> +gdb_test "continue" \ >> + =A0 =A0".*\[Ww\]atchpoint.*ival3.*Old value =3D 0.*New value =3D -1.*i= val3 =3D >> count; ival4 =3D count;.*" \ >> + =A0 =A0"watchpoint hit in reverse, HW, fifth time" >> + >> > >