From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 25613 invoked by alias); 3 Nov 2009 08:35:02 -0000 Received: (qmail 25508 invoked by uid 22791); 3 Nov 2009 08:34: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; Tue, 03 Nov 2009 08:34:54 +0000 Received: by pxi27 with SMTP id 27so3986820pxi.25 for ; Tue, 03 Nov 2009 00:34:53 -0800 (PST) MIME-Version: 1.0 Received: by 10.142.55.8 with SMTP id d8mr876789wfa.54.1257237293108; Tue, 03 Nov 2009 00:34:53 -0800 (PST) In-Reply-To: <4AEE27E9.1070005@vmware.com> References: <4AEDF9F4.9040207@vmware.com> <834opec530.fsf@gnu.org> <4AEE27E9.1070005@vmware.com> From: Hui Zhu Date: Tue, 03 Nov 2009 08:35:00 -0000 Message-ID: Subject: Re: [RFA] replay bookmarks To: Michael Snyder Cc: Eli Zaretskii , "gdb-patches@sourceware.org" , "glaw@undo-software.com" , "jakob@virtutech.com" 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/msg00044.txt.bz2 I try this patch in i386 ubuntu. It works very good. Could you add some works in cmd help to talk about "begin" and "end"? Thanks, Hui On Mon, Nov 2, 2009 at 08:29, Michael Snyder wrote: > Eli Zaretskii wrote: >>> >>> Date: Sun, 01 Nov 2009 13:13:24 -0800 >>> From: Michael Snyder >>> >>> + =A0add_com ("bookmark", class_bookmark, save_bookmark_command, _("\ >>> +Set a bookmark.\n\ >> >> This is way too short. =A0Suggest to expand a bit: >> >> =A0Set a bookmark in the inferior's execution history >> >>> + =A0add_com ("goto-bookmark", class_bookmark, goto_bookmark_command, _= ("\ >>> +Go to bookmark \n\ >> >> Similarly here: such a short description is hardly useful, as it just >> repeats the name of the command. > > How about this? > > > > 2009-10-25 =A0Michael Snyder =A0 > > =A0 =A0 =A0 =A0* target.h (struct target_ops): New methods to_get_bookmark > =A0 =A0 =A0 =A0and to_goto_bookmark. > =A0 =A0 =A0 =A0(target_get_bookmark): New macro. > =A0 =A0 =A0 =A0(target_goto_bookmark): New macro. > =A0 =A0 =A0 =A0* target.c (dummy_get_bookmark): New function, default > implementation. > =A0 =A0 =A0 =A0(dummy_goto_bookmark): New function, default implementatio= n. > =A0 =A0 =A0 =A0(update_current_target): Inherit new methods. > =A0 =A0 =A0 =A0* record.c (record_get_bookmark): New function. > =A0 =A0 =A0 =A0(record_goto_bookmark): New function. > =A0 =A0 =A0 =A0(init_record_ops): Set to_get_bookmark and to_goto_bookmar= k methods. > =A0 =A0 =A0 =A0* reverse.c (struct bookmark): New type. > =A0 =A0 =A0 =A0(save_bookmark_command): New function (command). > =A0 =A0 =A0 =A0(delete_bookmark_command): New function (command). > =A0 =A0 =A0 =A0(goto_bookmark_command): New function (command). > =A0 =A0 =A0 =A0(bookmarks_info): New function (command). > =A0 =A0 =A0 =A0(_initialize_reverse): Add new bookmark commands. > =A0 =A0 =A0 =A0* remote.c (remote_get_bookmark): New target method. > =A0 =A0 =A0 =A0(remote_goto_bookmark): New target method. > =A0 =A0 =A0 =A0* command.h (enum command_class): Add class_bookmark. > =A0 =A0 =A0 =A0* NEWS: Mention bookmark commands. > > 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-11-01 14:05:02.000000000 -0800 > +++ gdb/record.c =A0 =A0 =A0 =A02009-11-01 16:26:37.000000000 -0800 > @@ -1523,6 +1523,57 @@ > =A0 return 1; > =A0} > > +/* "to_get_bookmark" method for process record and prec over core. =A0*/ > + > +static gdb_byte * > +record_get_bookmark (char *args, int from_tty) > +{ > + =A0gdb_byte *ret =3D NULL; > + > + =A0/* Return stringified form of instruction count. =A0*/ > + =A0if (record_list && record_list->type =3D=3D record_end) > + =A0 =A0ret =3D xstrdup (pulongest (record_list->u.end.insn_num)); > + > + =A0if (record_debug) > + =A0 =A0{ > + =A0 =A0 =A0if (ret) > + =A0 =A0 =A0 fprintf_unfiltered (gdb_stdlog, > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 "record_get_bookmar= k returns %s\n", ret); > + =A0 =A0 =A0else > + =A0 =A0 =A0 fprintf_unfiltered (gdb_stdlog, > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 "record_get_bookmar= k returns NULL\n"); > + =A0 =A0} > + =A0return ret; > +} > + > +/* The implementation of the command "record goto". =A0*/ > +static void cmd_record_goto (char *, int); > + > +/* "to_goto_bookmark" method for process record and prec over core. =A0*/ > + > +static void > +record_goto_bookmark (gdb_byte *bookmark, int from_tty) > +{ > + =A0if (record_debug) > + =A0 =A0fprintf_unfiltered (gdb_stdlog, > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 "record_goto_bookmark recei= ves %s\n", bookmark); > + > + =A0if (bookmark[0] =3D=3D '\'' || bookmark[0] =3D=3D '\"') > + =A0 =A0{ > + =A0 =A0 =A0if (bookmark[strlen (bookmark) - 1] !=3D bookmark[0]) > + =A0 =A0 =A0 error (_("Unbalanced quotes: %s"), bookmark); > + > + =A0 =A0 =A0/* Strip trailing quote. =A0*/ > + =A0 =A0 =A0bookmark[strlen (bookmark) - 1] =3D '\0'; > + =A0 =A0 =A0/* Strip leading quote. =A0*/ > + =A0 =A0 =A0bookmark++; > + =A0 =A0 =A0/* Pass along to cmd_record_goto. =A0*/ > + =A0 =A0} > + > + =A0cmd_record_goto ((char *) bookmark, from_tty); > + =A0return; > +} > + > =A0static void > =A0init_record_ops (void) > =A0{ > @@ -1545,6 +1596,9 @@ > =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; > + =A0/* Add bookmark target methods. =A0*/ > + =A0record_ops.to_get_bookmark =3D record_get_bookmark; > + =A0record_ops.to_goto_bookmark =3D record_goto_bookmark; > =A0 record_ops.to_magic =3D OPS_MAGIC; > =A0} > > @@ -1750,6 +1804,9 @@ > =A0 record_core_ops.to_can_execute_reverse =3D record_can_execute_reverse; > =A0 record_core_ops.to_has_execution =3D record_core_has_execution; > =A0 record_core_ops.to_stratum =3D record_stratum; > + =A0/* Add bookmark target methods. =A0*/ > + =A0record_core_ops.to_get_bookmark =3D record_get_bookmark; > + =A0record_core_ops.to_goto_bookmark =3D record_goto_bookmark; > =A0 record_core_ops.to_magic =3D OPS_MAGIC; > =A0} > > @@ -2407,6 +2464,99 @@ > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 recfilename); > =A0} > > +/* record_goto_insn -- rewind the record log (forward or backward, > + =A0 depending on DIR) to the given entry, changing the program state > + =A0 correspondingly. =A0*/ > + > +static void > +record_goto_insn (struct record_entry *entry, > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 enum exec_direction_kind dir) > +{ > + =A0struct cleanup *set_cleanups =3D record_gdb_operation_disable_set (); > + =A0struct regcache *regcache =3D get_current_regcache (); > + =A0struct gdbarch *gdbarch =3D get_regcache_arch (regcache); > + > + =A0/* Assume everything is valid: we will hit the entry, > + =A0 =A0 and we will not hit the end of the recording. =A0*/ > + > + =A0if (dir =3D=3D EXEC_FORWARD) > + =A0 =A0record_list =3D record_list->next; > + > + =A0do > + =A0 =A0{ > + =A0 =A0 =A0record_exec_insn (regcache, gdbarch, record_list); > + =A0 =A0 =A0if (dir =3D=3D EXEC_REVERSE) > + =A0 =A0 =A0 record_list =3D record_list->prev; > + =A0 =A0 =A0else > + =A0 =A0 =A0 record_list =3D record_list->next; > + =A0 =A0} while (record_list !=3D entry); > + =A0do_cleanups (set_cleanups); > +} > + > +/* "record goto" command. =A0Argument is an instruction number, > + =A0 as given by "info record". > + > + =A0 Rewinds the recording (forward or backward) to the given instructio= n. > =A0*/ > + > +static void > +cmd_record_goto (char *arg, int from_tty) > +{ > + =A0struct record_entry *p =3D NULL; > + =A0ULONGEST target_insn =3D 0; > + > + =A0if (arg =3D=3D NULL || *arg =3D=3D '\0') > + =A0 =A0error (_("Command requires an argument (insn number to go to).")= ); > + > + =A0if (strncmp (arg, "start", strlen ("start")) =3D=3D 0 || > + =A0 =A0 =A0strncmp (arg, "begin", strlen ("begin")) =3D=3D 0) > + =A0 =A0{ > + =A0 =A0 =A0/* Special case. =A0Find first insn. =A0*/ > + =A0 =A0 =A0for (p =3D &record_first; p !=3D NULL; p =3D p->next) > + =A0 =A0 =A0 if (p->type =3D=3D record_end) > + =A0 =A0 =A0 =A0 break; > + =A0 =A0 =A0if (p) > + =A0 =A0 =A0 target_insn =3D p->u.end.insn_num; > + =A0 =A0} > + =A0else if (strncmp (arg, "end", strlen ("end")) =3D=3D 0) > + =A0 =A0{ > + =A0 =A0 =A0/* Special case. =A0Find last insn. =A0*/ > + =A0 =A0 =A0for (p =3D record_list; p->next !=3D NULL; p =3D p->next) > + =A0 =A0 =A0 ; > + =A0 =A0 =A0for (; p!=3D NULL; p =3D p->prev) > + =A0 =A0 =A0 if (p->type =3D=3D record_end) > + =A0 =A0 =A0 =A0 break; > + =A0 =A0 =A0if (p) > + =A0 =A0 =A0 target_insn =3D p->u.end.insn_num; > + =A0 =A0} > + =A0else > + =A0 =A0{ > + =A0 =A0 =A0/* General case. =A0Find designated insn. =A0*/ > + =A0 =A0 =A0target_insn =3D parse_and_eval_long (arg); > + > + =A0 =A0 =A0for (p =3D &record_first; p !=3D NULL; p =3D p->next) > + =A0 =A0 =A0 if (p->type =3D=3D record_end && p->u.end.insn_num =3D=3D t= arget_insn) > + =A0 =A0 =A0 =A0 break; > + =A0 =A0} > + > + =A0if (p =3D=3D NULL) > + =A0 =A0error ("Target insn '%s' not found.", arg); > + =A0else if (p =3D=3D record_list) > + =A0 =A0error ("Already at insn '%s'.", arg); > + =A0else if (p->u.end.insn_num > record_list->u.end.insn_num) > + =A0 =A0{ > + =A0 =A0 =A0printf_filtered ("Go forward to insn number %d\n", (int) > target_insn); > + =A0 =A0 =A0record_goto_insn (p, EXEC_FORWARD); > + =A0 =A0} > + =A0else > + =A0 =A0{ > + =A0 =A0 =A0printf_filtered ("Go backward to insn number %d\n", (int) > target_insn); > + =A0 =A0 =A0record_goto_insn (p, EXEC_REVERSE); > + =A0 =A0} > + =A0registers_changed (); > + =A0reinit_frame_cache (); > + =A0print_stack_frame (get_selected_frame (NULL), 1, SRC_AND_LOC); > +} > + > =A0void > =A0_initialize_record (void) > =A0{ > @@ -2492,4 +2642,9 @@ > =A0record/replay buffer. =A0Zero means unlimited. =A0Default is 200000."), > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0set_record_insn_ma= x_num, > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0NULL, &set_record_= cmdlist, &show_record_cmdlist); > + > + =A0add_cmd ("goto", class_obscure, cmd_record_goto, _("\ > +Restore the program to its state at instruction number N.\n\ > +Argument is instruction number, as shown by 'info record'."), > + =A0 =A0 =A0 =A0 =A0&record_cmdlist); > =A0} > Index: gdb/remote.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/remote.c =A0 2009-11-01 14:05:02.000000000 -0800 > +++ gdb/remote.c =A0 =A0 =A0 =A02009-11-01 14:08:31.000000000 -0800 > @@ -8882,6 +8882,46 @@ > =A0 return rs->cond_tracepoints; > =A0} > > +/* "to_get_bookmark" target method. > + > + =A0 Return a string from the target that uniquely identifies the > + =A0 current machine state, such that the target will be able to > + =A0 return to this machine state at a later request. > + > + =A0 Only expected to work with record/replay targets. =A0*/ > + > +static gdb_byte * > +remote_get_bookmark (char *args, int from_tty) > +{ > + =A0struct remote_state *rs =3D get_remote_state (); > + > + =A0putpkt ("qBookmark"); > + =A0getpkt (&rs->buf, &rs->buf_size, 0); > + =A0if (rs->buf[0] =3D=3D 'Q' && rs->buf[1] =3D=3D 'B') > + =A0 =A0return &rs->buf[2]; > + =A0else > + =A0 =A0return NULL; > +} > + > +/* "to_goto_bookmark" target method. > + > + =A0 Restore the target to an earlier-recorded machine state. =A0*/ > + > +static void > +remote_goto_bookmark (gdb_byte *bookmark, int from_tty) > +{ > + =A0struct remote_state *rs =3D get_remote_state (); > + =A0char *p =3D rs->buf; > + > + =A0xsnprintf (rs->buf, rs->buf_size, "QBookmark:%s", bookmark); > + > + =A0putpkt (p); > + =A0getpkt (&rs->buf, &rs->buf_size, 0); > + =A0if (rs->buf[0] !=3D 'O' && rs->buf[1] !=3D 'K') > + =A0 =A0error (_("remote goto bookmark not implemented.")); > +} > + > + > =A0static void > =A0init_remote_ops (void) > =A0{ > @@ -8931,7 +8971,6 @@ > =A0 remote_ops.to_has_execution =3D default_child_has_execution; > =A0 remote_ops.to_has_thread_control =3D tc_schedlock; =A0 =A0 /* can loc= k scheduler > */ > =A0 remote_ops.to_can_execute_reverse =3D remote_can_execute_reverse; > - =A0remote_ops.to_magic =3D OPS_MAGIC; > =A0 remote_ops.to_memory_map =3D remote_memory_map; > =A0 remote_ops.to_flash_erase =3D remote_flash_erase; > =A0 remote_ops.to_flash_done =3D remote_flash_done; > @@ -8945,6 +8984,9 @@ > =A0 remote_ops.to_terminal_ours =3D remote_terminal_ours; > =A0 remote_ops.to_supports_non_stop =3D remote_supports_non_stop; > =A0 remote_ops.to_supports_multi_process =3D remote_supports_multi_proces= s; > + =A0remote_ops.to_get_bookmark =3D remote_get_bookmark; > + =A0remote_ops.to_goto_bookmark =3D remote_goto_bookmark; > + =A0remote_ops.to_magic =3D OPS_MAGIC; > =A0} > > =A0/* Set up the extended remote vector by making a copy of the standard > Index: gdb/reverse.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/reverse.c =A02009-11-01 14:05:02.000000000 -0800 > +++ gdb/reverse.c =A0 =A0 =A0 2009-11-01 16:28:40.000000000 -0800 > @@ -24,6 +24,7 @@ > =A0#include "cli/cli-cmds.h" > =A0#include "cli/cli-decode.h" > =A0#include "inferior.h" > +#include "regcache.h" > > =A0/* User interface: > =A0 =A0reverse-step, reverse-next etc. =A0*/ > @@ -101,6 +102,221 @@ > =A0 exec_reverse_once ("finish", args, from_tty); > =A0} > > +/* Data structures for a bookmark list. =A0*/ > + > +struct bookmark { > + =A0struct bookmark *next; > + =A0int number; > + =A0CORE_ADDR pc; > + =A0struct symtab_and_line sal; > + =A0gdb_byte *opaque_data; > +}; > + > +struct bookmark *bookmark_chain; > +int bookmark_count; > + > +#define ALL_BOOKMARKS(B) for ((B) =3D bookmark_chain; (B); (B) =3D (B)->= next) > + > +#define ALL_BOOKMARKS_SAFE(B,TMP) =A0 =A0 =A0 =A0 =A0 \ > + =A0 =A0 for ((B) =3D bookmark_chain; =A0 =A0 =A0 =A0 =A0 =A0 \ > + =A0 =A0 =A0 =A0 =A0(B) ? ((TMP) =3D (B)->next, 1) : 0; \ > + =A0 =A0 =A0 =A0 =A0(B) =3D (TMP)) > + > +/* save_bookmark_command -- implement "bookmark" command. > + =A0 Call target method to get a bookmark identifier. > + =A0 Insert bookmark identifier into list. > + > + =A0 Identifier will be a malloc string (gdb_byte *). > + =A0 Up to us to free it as required. =A0*/ > + > +static void > +save_bookmark_command (char *args, int from_tty) > +{ > + =A0/* Get target's idea of a bookmark. =A0*/ > + =A0gdb_byte *bookmark_id =3D target_get_bookmark (args, from_tty); > + =A0struct bookmark *b, *b1; > + =A0struct gdbarch *gdbarch =3D get_regcache_arch (get_current_regcache = ()); > + > + =A0/* CR should not cause another identical bookmark. =A0*/ > + =A0dont_repeat (); > + > + =A0if (bookmark_id =3D=3D NULL) > + =A0 =A0error (_("target_get_bookmark failed.")); > + > + =A0/* Set up a bookmark struct. =A0*/ > + =A0b =3D xcalloc (1, sizeof (struct bookmark)); > + =A0b->number =3D ++bookmark_count; > + =A0init_sal (&b->sal); > + =A0b->pc =3D regcache_read_pc (get_current_regcache ()); > + =A0b->sal =3D find_pc_line (b->pc, 0); > + =A0b->sal.pspace =3D get_frame_program_space (get_current_frame ()); > + =A0b->opaque_data =3D bookmark_id; > + =A0b->next =3D NULL; > + > + =A0/* Add this bookmark to the end of the chain, so that a list > + =A0 =A0 of bookmarks will come out in order of increasing numbers. =A0*/ > + > + =A0b1 =3D bookmark_chain; > + =A0if (b1 =3D=3D 0) > + =A0 =A0bookmark_chain =3D b; > + =A0else > + =A0 =A0{ > + =A0 =A0 =A0while (b1->next) > + =A0 =A0 =A0 b1 =3D b1->next; > + =A0 =A0 =A0b1->next =3D b; > + =A0 =A0} > + =A0printf_filtered (_("Saved bookmark %d at %s\n"), b->number, > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0paddress (gdbarch, b->sal.pc)); > +} > + > +/* Implement "delete bookmark" command. =A0*/ > + > +static int > +delete_one_bookmark (struct bookmark *b) > +{ > + =A0struct bookmark *b1; > + > + =A0/* Special case, first item in list. =A0*/ > + =A0if (b =3D=3D bookmark_chain) > + =A0 =A0bookmark_chain =3D b->next; > + > + =A0/* Find bookmark preceeding "marked" one, so we can unlink. =A0*/ > + =A0/* FIXME what about end cases (first and last)? =A0*/ > + =A0if (b) > + =A0 =A0{ > + =A0 =A0 =A0ALL_BOOKMARKS (b1) > + =A0 =A0 =A0 if (b1->next =3D=3D b) > + =A0 =A0 =A0 =A0 { > + =A0 =A0 =A0 =A0 =A0 /* Found designated bookmark. =A0Unlink and delete.= =A0*/ > + =A0 =A0 =A0 =A0 =A0 b1->next =3D b->next; > + =A0 =A0 =A0 =A0 =A0 break; > + =A0 =A0 =A0 =A0 } > + =A0 =A0 =A0xfree (b->opaque_data); > + =A0 =A0 =A0xfree (b); > + =A0 =A0 =A0return 1; =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0/* success */ > + =A0 =A0} > + =A0return 0; =A0 =A0 =A0 =A0 =A0 =A0/* failure */ > +} > + > +static void > +delete_all_bookmarks (void) > +{ > + =A0struct bookmark *b, *b1; > + > + =A0ALL_BOOKMARKS_SAFE (b, b1) > + =A0 =A0{ > + =A0 =A0 =A0xfree (b->opaque_data); > + =A0 =A0 =A0xfree (b); > + =A0 =A0} > + =A0bookmark_chain =3D NULL; > +} > + > +static void > +delete_bookmark_command (char *args, int from_tty) > +{ > + =A0struct bookmark *b, *b1; > + =A0unsigned long num; > + > + =A0if (bookmark_chain =3D=3D NULL) > + =A0 =A0{ > + =A0 =A0 =A0warning ("No bookmarks."); > + =A0 =A0 =A0return; > + =A0 =A0} > + > + =A0if (args =3D=3D NULL || args[0] =3D=3D '\0') > + =A0 =A0{ > + =A0 =A0 =A0if (from_tty && !query (_("Delete all bookmarks? "))) > + =A0 =A0 =A0 return; > + =A0 =A0 =A0delete_all_bookmarks (); > + =A0 =A0 =A0return; > + =A0 =A0} > + > + =A0num =3D strtoul (args, NULL, 0); > + =A0/* Find bookmark with corresponding number. =A0*/ > + =A0ALL_BOOKMARKS (b) > + =A0 =A0if (b->number =3D=3D num) > + =A0 =A0 =A0break; > + > + =A0if (!delete_one_bookmark (b)) > + =A0 =A0/* Not found. =A0*/ > + =A0 =A0error (_("delete bookmark: no bookmark found for '%s'."), args); > +} > + > +/* Implement "goto-bookmark" command. =A0*/ > + > +static void > +goto_bookmark_command (char *args, int from_tty) > +{ > + =A0struct bookmark *b; > + =A0unsigned long num; > + > + =A0if (args =3D=3D NULL || args[0] =3D=3D '\0') > + =A0 =A0error (_("Command requires an argument.")); > + > + =A0if (strncmp (args, "start", strlen ("start")) =3D=3D 0 || > + =A0 =A0 =A0strncmp (args, "begin", strlen ("begin")) =3D=3D 0 || > + =A0 =A0 =A0strncmp (args, "end", =A0 strlen ("end")) =3D=3D 0) > + =A0 =A0{ > + =A0 =A0 =A0/* Special case. =A0Give target opportunity to handle. =A0*/ > + =A0 =A0 =A0target_goto_bookmark (args, from_tty); > + =A0 =A0 =A0return; > + =A0 =A0} > + > + =A0if (args[0] =3D=3D '\'' || args[0] =3D=3D '\"') > + =A0 =A0{ > + =A0 =A0 =A0/* Special case -- quoted string. =A0Pass on to target. =A0*/ > + =A0 =A0 =A0if (args[strlen (args) - 1] !=3D args[0]) > + =A0 =A0 =A0 error (_("Unbalanced quotes: %s"), args); > + =A0 =A0 =A0target_goto_bookmark (args, from_tty); > + =A0 =A0 =A0return; > + =A0 =A0} > + > + =A0/* General case. =A0Bookmark identified by bookmark number. =A0*/ > + =A0num =3D strtoul (args, NULL, 0); > + =A0ALL_BOOKMARKS (b) > + =A0 =A0if (b->number =3D=3D num) > + =A0 =A0 =A0break; > + > + =A0if (b) > + =A0 =A0{ > + =A0 =A0 =A0/* Found. =A0Send to target method. =A0*/ > + =A0 =A0 =A0target_goto_bookmark (b->opaque_data, from_tty); > + =A0 =A0 =A0return; > + =A0 =A0} > + =A0/* Not found. =A0*/ > + =A0error (_("goto-bookmark: no bookmark found for '%s'."), args); > +} > + > +/* Implement "info bookmarks" command. =A0*/ > + > +static void > +bookmarks_info (char *args, int from_tty) > +{ > + =A0struct bookmark *b; > + =A0int bnum =3D -1; > + =A0struct gdbarch *gdbarch; > + > + =A0if (args) > + =A0 =A0bnum =3D parse_and_eval_long (args); > + > + =A0if (!bookmark_chain) > + =A0 =A0{ > + =A0 =A0 =A0printf_filtered (_("No bookmarks.\n")); > + =A0 =A0 =A0return; > + =A0 =A0} > + > + =A0gdbarch =3D get_regcache_arch (get_current_regcache ()); > + =A0printf_filtered (_("Bookmark =A0 =A0Address =A0 =A0 Opaque\n")); > + =A0printf_filtered (_(" =A0 ID =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0D= ata \n")); > + > + =A0ALL_BOOKMARKS (b) > + =A0 =A0printf_filtered (" =A0 %d =A0 =A0 =A0 %s =A0 =A0'%s'\n", > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0b->number, > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0paddress (gdbarch, b->pc), > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0b->opaque_data); > +} > + > + > =A0/* Provide a prototype to silence -Wmissing-prototypes. =A0*/ > =A0extern initialize_file_ftype _initialize_reverse; > > @@ -142,4 +358,19 @@ > > =A0 add_com ("reverse-finish", class_run, reverse_finish, _("\ > =A0Execute backward until just before selected stack frame is called.")); > + > + =A0add_com ("bookmark", class_bookmark, save_bookmark_command, _("\ > +Set a bookmark in the program's execution history.\n\ > +A bookmark represents a point in the execution history \n\ > +that can be returned to at a later point in the debug session.")); > + =A0add_info ("bookmarks", bookmarks_info, _("\ > +Status of user-settable bookmarks.\n\ > +Bookmarks are user-settable markers representing a point in the \n\ > +execution history that can be returned to later in the same debug \n\ > +session.")); > + =A0add_cmd ("bookmark", class_bookmark, delete_bookmark_command, _("\ > +Delete a bookmark from the bookmark list.\n"), &deletelist); > + =A0add_com ("goto-bookmark", class_bookmark, goto_bookmark_command, _("\ > +Go to an earlier-bookmarked point in the program's execution history.\n\ > +The bookmark must be saved earlier by using the 'bookmark' command.")); > =A0} > Index: gdb/target.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/target.c =A0 2009-11-01 14:05:02.000000000 -0800 > +++ gdb/target.c =A0 =A0 =A0 =A02009-11-01 14:08:31.000000000 -0800 > @@ -674,6 +674,8 @@ > =A0 =A0 =A0 INHERIT (to_async_mask, t); > =A0 =A0 =A0 INHERIT (to_find_memory_regions, t); > =A0 =A0 =A0 INHERIT (to_make_corefile_notes, t); > + =A0 =A0 =A0INHERIT (to_get_bookmark, t); > + =A0 =A0 =A0INHERIT (to_goto_bookmark, t); > =A0 =A0 =A0 /* Do not inherit to_get_thread_local_address. =A0*/ > =A0 =A0 =A0 INHERIT (to_can_execute_reverse, t); > =A0 =A0 =A0 INHERIT (to_thread_architecture, t); > @@ -2767,6 +2769,21 @@ > =A0 return NULL; > =A0} > > +/* Error-catcher for target_get_bookmark. =A0*/ > +static gdb_byte * > +dummy_get_bookmark (char *ignore1, int ignore2) > +{ > + =A0tcomplain (); > + =A0return NULL; > +} > + > +/* Error-catcher for target_goto_bookmark. =A0*/ > +static void > +dummy_goto_bookmark (gdb_byte *ignore, int from_tty) > +{ > + =A0tcomplain (); > +} > + > =A0/* Set up the handful of non-empty slots needed by the dummy target > =A0 =A0vector. =A0*/ > > @@ -2787,6 +2804,8 @@ > =A0 dummy_target.to_stratum =3D dummy_stratum; > =A0 dummy_target.to_find_memory_regions =3D dummy_find_memory_regions; > =A0 dummy_target.to_make_corefile_notes =3D dummy_make_corefile_notes; > + =A0dummy_target.to_get_bookmark =3D dummy_get_bookmark; > + =A0dummy_target.to_goto_bookmark =3D dummy_goto_bookmark; > =A0 dummy_target.to_xfer_partial =3D default_xfer_partial; > =A0 dummy_target.to_has_all_memory =3D (int (*) (struct target_ops *)) > return_zero; > =A0 dummy_target.to_has_memory =3D (int (*) (struct target_ops *)) return= _zero; > Index: gdb/target.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/target.h =A0 2009-11-01 14:05:02.000000000 -0800 > +++ gdb/target.h =A0 =A0 =A0 =A02009-11-01 14:08:31.000000000 -0800 > @@ -459,13 +459,18 @@ > =A0 =A0 void (*to_async) (void (*) (enum inferior_event_type, void *), vo= id *); > =A0 =A0 int (*to_async_mask) (int); > =A0 =A0 int (*to_supports_non_stop) (void); > + =A0 =A0/* find_memory_regions support method for gcore */ > =A0 =A0 int (*to_find_memory_regions) (int (*) (CORE_ADDR, > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 = =A0 =A0 =A0 =A0unsigned long, > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 = =A0 =A0 =A0 =A0int, int, int, > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 = =A0 =A0 =A0 =A0void *), > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 void = *); > + =A0 =A0/* make_corefile_notes support method for gcore */ > =A0 =A0 char * (*to_make_corefile_notes) (bfd *, int *); > - > + =A0 =A0/* get_bookmark support method for bookmarks */ > + =A0 =A0gdb_byte * (*to_get_bookmark) (char *, int); > + =A0 =A0/* goto_bookmark support method for bookmarks */ > + =A0 =A0void (*to_goto_bookmark) (gdb_byte *, int); > =A0 =A0 /* Return the thread-local address at OFFSET in the > =A0 =A0 =A0 =A0thread-local storage for the thread PTID and the shared li= brary > =A0 =A0 =A0 =A0or executable file given by OBJFILE. =A0If that block of > @@ -1141,6 +1146,13 @@ > =A0#define target_make_corefile_notes(BFD, SIZE_P) \ > =A0 =A0 =A0(current_target.to_make_corefile_notes) (BFD, SIZE_P) > > +/* Bookmark interfaces. =A0*/ > +#define target_get_bookmark(ARGS, FROM_TTY) \ > + =A0 =A0 (current_target.to_get_bookmark) (ARGS, FROM_TTY) > + > +#define target_goto_bookmark(ARG, FROM_TTY) \ > + =A0 =A0 (current_target.to_goto_bookmark) (ARG, FROM_TTY) > + > =A0/* Hardware watchpoint interfaces. =A0*/ > > =A0/* Returns non-zero if we were stopped by a hardware watchpoint (memory > read or > 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-11-01 14:05:02.000000000 -0800 > +++ gdb/breakpoint.c =A0 =A02009-11-01 16:26:37.000000000 -0800 > @@ -10086,6 +10086,8 @@ > =A0Convenience variable \"$bpnum\" contains the number of the last\n\ > =A0breakpoint set.")); > > + =A0add_info_alias ("b", "breakpoints", 1); > + > =A0 if (xdb_commands) > =A0 =A0 add_com ("lb", class_breakpoint, breakpoints_info, _("\ > =A0Status of user-settable breakpoints, or breakpoint number NUMBER.\n\ > Index: 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 > --- gdb.orig/NEWS =A0 =A0 =A0 2009-11-01 14:05:02.000000000 -0800 > +++ gdb/NEWS =A0 =A02009-11-01 16:26:37.000000000 -0800 > @@ -24,8 +24,25 @@ > > =A0* New commands (for set/show, see "New options" below) > > +bookmark > + =A0Save a reference to the current position in the execution log (for > + =A0replay targets such as process record/replay). =A0This execution > + =A0position can then be returned to later with the 'goto-bookmark' > + =A0command. > + > +goto-bookmark [] > + =A0Return the replay target to the excution position represented by the > + =A0Nth bookmark. =A0Resume replay debugging from that point. > + > +info bookmarks > + =A0List the bookmarks presently known to gdb. =A0Each bookmark can be > + =A0returned to using the 'goto-bookmark' command. > + > +delete bookmark [] > + =A0Delete the Nth bookmark, or all bookmarks. > + > =A0record save [] > - =A0Save a file (in core file format) containing the process record > + =A0Save a file (in core file format) containing the process record > =A0 execution log for replay debugging at a later time. > > =A0record restore > Index: gdb/command.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/command.h =A02009-11-01 14:05:02.000000000 -0800 > +++ gdb/command.h =A0 =A0 =A0 2009-11-01 14:08:31.000000000 -0800 > @@ -32,8 +32,8 @@ > =A0 /* Classes of commands */ > =A0 no_class =3D -1, class_run =3D 0, class_vars, class_stack, > =A0 class_files, class_support, class_info, class_breakpoint, class_trace, > - =A0class_alias, class_obscure, class_user, class_maintenance, > - =A0class_pseudo, class_tui, class_xdb > + =A0class_bookmark, class_alias, class_obscure, class_user, > + =A0class_maintenance, class_pseudo, class_tui, class_xdb > =A0}; > > =A0/* FIXME: cagney/2002-03-17: Once cmd_type() has been removed, ``enum > >