From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 11218 invoked by alias); 4 Nov 2009 03:01:28 -0000 Received: (qmail 10453 invoked by uid 22791); 4 Nov 2009 03:01:25 -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-pw0-f49.google.com (HELO mail-pw0-f49.google.com) (209.85.160.49) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Wed, 04 Nov 2009 03:01:20 +0000 Received: by pwj3 with SMTP id 3so3131990pwj.8 for ; Tue, 03 Nov 2009 19:01:19 -0800 (PST) MIME-Version: 1.0 Received: by 10.143.24.38 with SMTP id b38mr89946wfj.254.1257303679107; Tue, 03 Nov 2009 19:01:19 -0800 (PST) In-Reply-To: <4AECE12F.3000704@vmware.com> References: <4AECE12F.3000704@vmware.com> From: Hui Zhu Date: Wed, 04 Nov 2009 03:01:00 -0000 Message-ID: Subject: Re: [RFA] Fix hw watchpoints in process record. To: Michael Snyder 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/msg00069.txt.bz2 Hi Michael, I do some test with this patch. But sometime hb didn't work in replay mode. For example: Temporary breakpoint 1, main () at 1.c:20 20 int b =3D 0; (gdb) record (gdb) n During symbol reading, incomplete CFI data; unspecified registers (e.g., eax) at 0x80483be. 21 int c =3D 1; (gdb) hb Hardware assisted breakpoint 2 at 0x80483c8: file 1.c, line 21. (gdb) c Continuing. a =3D 0 b =3D 0 c =3D 1 a =3D 3 a =3D 3 b =3D 3 c =3D 1 a =3D 3 b =3D 3 c =3D 2 a =3D 1 b =3D 3 c =3D 2 The next instruction is syscall exit_group. It will make the program exit. Do you want to stop the program?([y] or n) Process record: inferior program stopped. Program received signal SIGTRAP, Trace/breakpoint trap. 0xb7fe3405 in __kernel_vsyscall () (gdb) rc Continuing. Breakpoint 2, main () at 1.c:21 21 int c =3D 1; (gdb) info b Num Type Disp Enb Address What 2 hw breakpoint keep y 0x080483c8 in main at 1.c:21 breakpoint already hit 1 time (gdb) c Continuing. No more reverse-execution history. 0xb7fe3405 in __kernel_vsyscall () (gdb) rc Continuing. Breakpoint 2, main () at 1.c:21 21 int c =3D 1; Thanks, Hui On Sun, Nov 1, 2009 at 09:15, Michael Snyder wrote: > Here is a patch to make hardware watchpoints work in precord. > > Biggest change is in breakpoint.c, but it's mainly mechanical. > I abstracted most of the function "watchpoint_check" into a > separate function so it could be called from two places. > > Then in record_wait, if not replay mode we call > target_stopped_by_watchpoint to see if a watchpoint > was triggered. =A0In replay mode we call the new function > hw_watchpoint_check. > > > 2009-10-31 =A0Michael Snyder =A0 > =A0 =A0 =A0 =A0Make hardware watchpoints work for process record. > =A0 =A0 =A0 =A0* breakpoint.c (watchpoint_check_1): Abstracted from > watchpoint_check. > =A0 =A0 =A0 =A0(watchpoint_check_2): Check_error entry point for above. > =A0 =A0 =A0 =A0(watchpoint_check): Call watchpoint_check_1. > =A0 =A0 =A0 =A0(hw_watchpoint_check): New function. =A0Return true if > =A0 =A0 =A0 =A0a hardware watchpoint expression has changed. > =A0 =A0 =A0 =A0* breakpoint.h (hw_watchpoint_check): Export. > > =A0 =A0 =A0 =A0* record.c (record_beneath_to_stopped_by_watchpoint): New = pointer. > =A0 =A0 =A0 =A0(record_open): Initialize above pointer. > =A0 =A0 =A0 =A0(record_stopped_by_watchpoint): New target method. > =A0 =A0 =A0 =A0(record_wait): Check to see if hitting hardware watchpoint. > > Index: 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 > --- gdb.orig/breakpoint.c =A0 =A0 =A0 2009-10-31 17:31:15.000000000 -0700 > +++ gdb/breakpoint.c =A0 =A02009-10-31 17:50:07.000000000 -0700 > @@ -3075,18 +3075,13 @@ > =A0#define BP_TEMPFLAG 1 > =A0#define BP_HARDWAREFLAG 2 > > -/* Check watchpoint condition. =A0*/ > - > =A0static int > -watchpoint_check (void *p) > +watchpoint_check_1 (void *p, struct value **new_valp) > =A0{ > - =A0bpstat bs =3D (bpstat) p; > - =A0struct breakpoint *b; > + =A0struct breakpoint *b =3D p; > =A0 struct frame_info *fr; > =A0 int within_current_scope; > > - =A0b =3D bs->breakpoint_at->owner; > - > =A0 if (b->exp_valid_block =3D=3D NULL) > =A0 =A0 within_current_scope =3D 1; > =A0 else > @@ -3137,20 +3132,16 @@ > =A0 =A0 =A0 =A0 =A0we might be in the middle of evaluating a function cal= l. =A0*/ > > =A0 =A0 =A0 struct value *mark =3D value_mark (); > - =A0 =A0 =A0struct value *new_val; > > - =A0 =A0 =A0fetch_watchpoint_value (b->exp, &new_val, NULL, NULL); > - =A0 =A0 =A0if ((b->val !=3D NULL) !=3D (new_val !=3D NULL) > - =A0 =A0 =A0 =A0 || (b->val !=3D NULL && !value_equal (b->val, new_val))) > + =A0 =A0 =A0fetch_watchpoint_value (b->exp, new_valp, NULL, NULL); > + =A0 =A0 =A0if ((b->val !=3D NULL) !=3D (*new_valp !=3D NULL) > + =A0 =A0 =A0 =A0 || (b->val !=3D NULL && !value_equal (b->val, *new_valp= ))) > =A0 =A0 =A0 =A0{ > - =A0 =A0 =A0 =A0 if (new_val !=3D NULL) > + =A0 =A0 =A0 =A0 if (*new_valp !=3D NULL) > =A0 =A0 =A0 =A0 =A0 =A0{ > - =A0 =A0 =A0 =A0 =A0 =A0 release_value (new_val); > + =A0 =A0 =A0 =A0 =A0 =A0 release_value (*new_valp); > =A0 =A0 =A0 =A0 =A0 =A0 =A0value_free_to_mark (mark); > =A0 =A0 =A0 =A0 =A0 =A0} > - =A0 =A0 =A0 =A0 bs->old_val =3D b->val; > - =A0 =A0 =A0 =A0 b->val =3D new_val; > - =A0 =A0 =A0 =A0 b->val_valid =3D 1; > =A0 =A0 =A0 =A0 =A0/* We will stop here */ > =A0 =A0 =A0 =A0 =A0return WP_VALUE_CHANGED; > =A0 =A0 =A0 =A0} > @@ -3181,8 +3172,9 @@ > =A0 =A0 =A0 =A0 =A0(uiout, "reason", async_reason_lookup > (EXEC_ASYNC_WATCHPOINT_SCOPE)); > =A0 =A0 =A0 ui_out_text (uiout, "\nWatchpoint "); > =A0 =A0 =A0 ui_out_field_int (uiout, "wpnum", b->number); > - =A0 =A0 =A0ui_out_text (uiout, " deleted because the program has left t= he block > in\n\ > -which its expression is valid.\n"); > + =A0 =A0 =A0ui_out_text (uiout, > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0" deleted because the program has le= ft the block in\n\ > +which its expression is valid.\n"); > > =A0 =A0 =A0 if (b->related_breakpoint) > =A0 =A0 =A0 =A0b->related_breakpoint->disposition =3D disp_del_at_next_st= op; > @@ -3192,6 +3184,36 @@ > =A0 =A0 } > =A0} > > +static int > +watchpoint_check_2 (void *p) > +{ > + =A0struct value *notused; > + > + =A0return watchpoint_check_1 (p, ¬used); > +} > + > +/* Check watchpoint condition. =A0*/ > + > +static int > +watchpoint_check (void *p) > +{ > + =A0bpstat bs =3D (bpstat) p; > + =A0struct value *new_val; > + =A0struct breakpoint *b; > + =A0int ret; > + > + =A0b =3D bs->breakpoint_at->owner; > + =A0ret =3D watchpoint_check_1 (b, &new_val); > + > + =A0if (ret =3D=3D WP_VALUE_CHANGED) > + =A0 =A0{ > + =A0 =A0 =A0bs->old_val =3D b->val; > + =A0 =A0 =A0b->val =3D new_val; > + =A0 =A0 =A0b->val_valid =3D 1; > + =A0 =A0} > + =A0return ret; > +} > + > =A0/* Return true if it looks like target has stopped due to hitting > =A0 =A0breakpoint location BL. =A0This function does not check if we > =A0 =A0should stop, only if BL explains the stop. =A0 */ > @@ -3250,6 +3272,29 @@ > =A0 return 1; > =A0} > > +int > +hw_watchpoint_check (void) > +{ > + =A0struct breakpoint *b; > + =A0struct value *new_val; > + > + =A0ALL_BREAKPOINTS (b) > + =A0 =A0if (b->type =3D=3D bp_hardware_watchpoint > + =A0 =A0 =A0 || b->type =3D=3D bp_access_watchpoint) > + =A0 =A0 =A0{ > + =A0 =A0 =A0 char *msg > + =A0 =A0 =A0 =A0 =3D xstrprintf (_("Error evaluating expression for watc= hpoint > %d\n"), > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 b->number); > + =A0 =A0 =A0 struct cleanup *cleanups =3D make_cleanup (xfree, msg); > + =A0 =A0 =A0 int e =3D catch_errors (watchpoint_check_2, b, msg, RETURN_= MASK_ALL); > + =A0 =A0 =A0 do_cleanups (cleanups); > + =A0 =A0 =A0 if (e =3D=3D WP_VALUE_CHANGED) > + =A0 =A0 =A0 =A0 return 1; =A0 =A0 /* should stop */ > + =A0 =A0 =A0} > + =A0return 0; =A0 =A0 =A0 =A0 =A0 =A0/* don't stop */ > +} > + > + > =A0/* If BS refers to a watchpoint, determine if the watched values > =A0 =A0has actually changed, and we should stop. =A0If not, set BS->stop > =A0 =A0to 0. =A0*/ > @@ -3267,7 +3312,7 @@ > =A0 =A0 =A0 CORE_ADDR addr; > =A0 =A0 =A0 struct value *v; > =A0 =A0 =A0 int must_check_value =3D 0; > - > + > =A0 =A0 =A0 if (b->type =3D=3D bp_watchpoint) > =A0 =A0 =A0 =A0/* For a software watchpoint, we must always check the > =A0 =A0 =A0 =A0 =A0 watched value. =A0*/ > @@ -3284,7 +3329,7 @@ > =A0 =A0 =A0 =A0 =A0 value. =A0Access and read watchpoints are out of luck= ; without > =A0 =A0 =A0 =A0 =A0 a data address, we can't figure it out. =A0*/ > =A0 =A0 =A0 =A0must_check_value =3D 1; > - > + > =A0 =A0 =A0 if (must_check_value) > =A0 =A0 =A0 =A0{ > =A0 =A0 =A0 =A0 =A0char *message =3D xstrprintf ("Error evaluating expres= sion for > watchpoint %d\n", > Index: 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 > --- gdb.orig/breakpoint.h =A0 =A0 =A0 2009-10-31 17:31:21.000000000 -0700 > +++ gdb/breakpoint.h =A0 =A02009-10-31 17:33:23.000000000 -0700 > @@ -978,4 +978,6 @@ > =A0 =A0is newly allocated; the caller should free when done with it. =A0*/ > =A0extern VEC(breakpoint_p) *all_tracepoints (void); > > +extern int hw_watchpoint_check (void); > + > =A0#endif /* !defined (BREAKPOINT_H) */ > Index: 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 > --- gdb.orig/record.c =A0 2009-10-31 17:31:00.000000000 -0700 > +++ gdb/record.c =A0 =A0 =A0 =A02009-10-31 17:34:24.000000000 -0700 > @@ -224,6 +224,7 @@ > =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*/ > @@ -770,6 +771,7 @@ > =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 +896,8 @@ > =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_watchpoin= t; > =A0 =A0 } > =A0 if (!tmp_to_xfer_partial) > =A0 =A0 error (_("Could not find 'to_xfer_partial' method on the target > stack.")); > @@ -915,6 +919,7 @@ > =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_watchp= oint; > > =A0 if (current_target.to_stratum =3D=3D core_stratum) > =A0 =A0 record_core_open_1 (name, from_tty); > @@ -1010,6 +1015,9 @@ > =A0 =A0 record_list =3D record_list->prev; > =A0} > > +/* Flag set to TRUE for target_stopped_by_watchpoint. =A0*/ > +static int record_hw_watchpoint =3D 0; > + > =A0/* "to_wait" target method for process record target. > > =A0 =A0In record mode, the target is always run in singlestep mode > @@ -1069,21 +1077,27 @@ > =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 breakpoin= t. =A0*/ > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 /* Yes -- check if there is a breakpoin= t or watchpoint. > =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 =A0if (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 =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 =A0 =A0 || target_stopped_by_watchpoint= ()) > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0{ > - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 /* There is a breakpoint. =A0GD= B will want to stop. =A0*/ > - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 struct gdbarch *gdbarch =3D get= _regcache_arch > (regcache); > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 /* There is a breakpoint, or wa= tchpoint. > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0GDB will want to stop. = =A0*/ > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (!target_stopped_by_watchpoi= nt ()) > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 { > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 struct gdbarch *gdbarch > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =3D get_regcache_ar= ch (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); > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0if (decr_pc_after_break) > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0regcache_write_pc (regcach= e, > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 = =A0 =A0 =A0 tmp_pc + decr_pc_after_break); > =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 =A0 =A0else > =A0 =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 > @@ -1116,9 +1130,10 @@ > =A0 =A0 =A0 struct cleanup *old_cleanups =3D make_cleanup (record_wait_cl= eanups, 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*/ > + =A0 =A0 =A0/* Check for breakpoint or watchpoint when forward execute. = =A0*/ > =A0 =A0 =A0 if (execution_direction =3D=3D EXEC_FORWARD) > =A0 =A0 =A0 =A0{ > =A0 =A0 =A0 =A0 =A0tmp_pc =3D regcache_read_pc (regcache); > @@ -1136,6 +1151,14 @@ > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 gdbar= ch_decr_pc_after_break (gdbarch)); > =A0 =A0 =A0 =A0 =A0 =A0 =A0goto replay_out; > =A0 =A0 =A0 =A0 =A0 =A0} > + =A0 =A0 =A0 =A0 if (hw_watchpoint_check ()) > + =A0 =A0 =A0 =A0 =A0 { > + =A0 =A0 =A0 =A0 =A0 =A0 if (record_debug) > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 fprintf_unfiltered (gdb_stdlog, > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 "Pr= ocess record: hit hw watchpoint.\n"); > + =A0 =A0 =A0 =A0 =A0 =A0 record_hw_watchpoint =3D 1; > + =A0 =A0 =A0 =A0 =A0 } > + > =A0 =A0 =A0 =A0} > > =A0 =A0 =A0 record_get_sig =3D 0; > @@ -1219,6 +1242,15 @@ > =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 /* check watchpoint */ > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (hw_watchpoint_check ()) > + =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_std= log, > + =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 record_hw_watchpoint =3D 1; > + =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 TAR= GET_SIGNAL_0) > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0/* FIXME: better way to check */ > @@ -1260,6 +1292,16 @@ > =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 > @@ -1587,6 +1629,7 @@ > =A0 /* Add bookmark target methods. =A0*/ > =A0 record_ops.to_get_bookmark =3D record_get_bookmark; > =A0 record_ops.to_goto_bookmark =3D record_goto_bookmark; > + =A0record_ops.to_stopped_by_watchpoint =3D record_stopped_by_watchpoint; > =A0 record_ops.to_magic =3D OPS_MAGIC; > =A0} > > @@ -1795,6 +1838,7 @@ > =A0 /* Add bookmark target methods. =A0*/ > =A0 record_core_ops.to_get_bookmark =3D record_get_bookmark; > =A0 record_core_ops.to_goto_bookmark =3D record_goto_bookmark; > + =A0record_core_ops.to_stopped_by_watchpoint =3D record_stopped_by_watch= point; > =A0 record_core_ops.to_magic =3D OPS_MAGIC; > =A0} > > >