From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 26636 invoked by alias); 9 Apr 2010 02:41:27 -0000 Received: (qmail 26590 invoked by uid 22791); 9 Apr 2010 02:41:25 -0000 X-SWARE-Spam-Status: No, hits=-1.9 required=5.0 tests=BAYES_00,T_RP_MATCHES_RCVD X-Spam-Check-By: sourceware.org Received: from mail.codesourcery.com (HELO mail.codesourcery.com) (38.113.113.100) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Fri, 09 Apr 2010 02:41:19 +0000 Received: (qmail 19798 invoked from network); 9 Apr 2010 02:41:17 -0000 Received: from unknown (HELO orlando.localnet) (pedro@127.0.0.2) by mail.codesourcery.com with ESMTPA; 9 Apr 2010 02:41:17 -0000 From: Pedro Alves To: gdb-patches@sourceware.org Subject: PR8554: New command to save breakpoints to a file Date: Fri, 09 Apr 2010 02:41:00 -0000 User-Agent: KMail/1.12.2 (Linux/2.6.31-20-generic; KDE/4.3.2; x86_64; ; ) MIME-Version: 1.0 Content-Type: Text/Plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Message-Id: <201004090341.14389.pedro@codesourcery.com> 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: 2010-04/txt/msg00217.txt.bz2 (I finished this instead of dumping it.) Add a new save-breakpoints command to save breakpoint definitions to a file. Use the "source" command to bring the breakpoints back in. This handles all types of breakpoints, tracepoints, catchpoints, watchpoints, whatnot. The new breakpoint_ops->print_recreate method implementation for all catchpoints is always mostly a simplified version of breakpoint_ops->print_mention method. Docs/NEWS bits included below. -- Pedro Alves 2010-04-09 Pedro Alves PR breakpoints/8554. Implement `save-breakpoints'. gdb/ * breakpoint.c (print_recreate_catch_fork): New. (catch_fork_breakpoint_ops): Install it. (print_recreate_catch_vfork): New. (catch_vfork_breakpoint_ops): Install it. (print_recreate_catch_syscall): New. (catch_syscall_breakpoint_ops): Install it. (print_recreate_catch_exec): New. (catch_exec_breakpoint_ops): Install it. (print_recreate_exception_catchpoint): New. (gnu_v3_exception_catchpoint_ops): Install it. (breakpoint_save): New, based on tracepoint_save_command. (save_breakpoints_command): New. (tracepoint_save_command): Reimplement using breakpoint_save. (_initialize_breakpoints): Install the "save-breakpoints" command. * breakpoint.h (struct breakpoint_ops): New field `print_recreate'. * ada-lang.c (print_recreate_exception): New. (print_recreate_catch_exception): New. (catch_exception_breakpoint_ops): Install it. (print_recreate_catch_exception_unhandled): New. (catch_exception_unhandled_breakpoint_ops): Install it. (print_recreate_catch_assert): New. (catch_assert_breakpoint_ops): Install it. * NEWS: Mention the new save-breakpoints command. doc/ * gdb.texinfo (Save Breakpoints): New node. testsuite/ * gdb.trace/save-trace.exp: Adjust. --- gdb/NEWS | 7 + gdb/ada-lang.c | 57 +++++++- gdb/breakpoint.c | 231 ++++++++++++++++++++++++++++----- gdb/breakpoint.h | 3 gdb/doc/gdb.texinfo | 18 ++ gdb/testsuite/gdb.trace/save-trace.exp | 4 6 files changed, 286 insertions(+), 34 deletions(-) Index: src/gdb/breakpoint.c =================================================================== --- src.orig/gdb/breakpoint.c 2010-04-08 23:27:37.000000000 +0100 +++ src/gdb/breakpoint.c 2010-04-09 03:29:07.000000000 +0100 @@ -5838,6 +5838,15 @@ print_mention_catch_fork (struct breakpo printf_filtered (_("Catchpoint %d (fork)"), b->number); } +/* Implement the "print_recreate" breakpoint_ops method for fork + catchpoints. */ + +static void +print_recreate_catch_fork (struct breakpoint *b, struct ui_file *fp) +{ + fprintf_unfiltered (fp, "catch fork"); +} + /* The breakpoint_ops structure to be used in fork catchpoints. */ static struct breakpoint_ops catch_fork_breakpoint_ops = @@ -5847,7 +5856,8 @@ static struct breakpoint_ops catch_fork_ breakpoint_hit_catch_fork, print_it_catch_fork, print_one_catch_fork, - print_mention_catch_fork + print_mention_catch_fork, + print_recreate_catch_fork }; /* Implement the "insert" breakpoint_ops method for vfork catchpoints. */ @@ -5919,6 +5929,15 @@ print_mention_catch_vfork (struct breakp printf_filtered (_("Catchpoint %d (vfork)"), b->number); } +/* Implement the "print_recreate" breakpoint_ops method for vfork + catchpoints. */ + +static void +print_recreate_catch_vfork (struct breakpoint *b, struct ui_file *fp) +{ + fprintf_unfiltered (fp, "catch vfork"); +} + /* The breakpoint_ops structure to be used in vfork catchpoints. */ static struct breakpoint_ops catch_vfork_breakpoint_ops = @@ -5928,7 +5947,8 @@ static struct breakpoint_ops catch_vfork breakpoint_hit_catch_vfork, print_it_catch_vfork, print_one_catch_vfork, - print_mention_catch_vfork + print_mention_catch_vfork, + print_recreate_catch_vfork }; /* Implement the "insert" breakpoint_ops method for syscall @@ -6167,6 +6187,33 @@ print_mention_catch_syscall (struct brea b->number); } +/* Implement the "print_recreate" breakpoint_ops method for syscall + catchpoints. */ + +static void +print_recreate_catch_syscall (struct breakpoint *b, struct ui_file *fp) +{ + fprintf_unfiltered (fp, "catch syscall"); + + if (b->syscalls_to_be_caught) + { + int i, iter; + + for (i = 0; + VEC_iterate (int, b->syscalls_to_be_caught, i, iter); + i++) + { + struct syscall s; + + get_syscall_by_number (iter, &s); + if (s.name) + fprintf_unfiltered (fp, " %s", s.name); + else + fprintf_unfiltered (fp, " %d", s.number); + } + } +} + /* The breakpoint_ops structure to be used in syscall catchpoints. */ static struct breakpoint_ops catch_syscall_breakpoint_ops = @@ -6176,7 +6223,8 @@ static struct breakpoint_ops catch_sysca breakpoint_hit_catch_syscall, print_it_catch_syscall, print_one_catch_syscall, - print_mention_catch_syscall + print_mention_catch_syscall, + print_recreate_catch_syscall }; /* Returns non-zero if 'b' is a syscall catchpoint. */ @@ -6312,6 +6360,15 @@ print_mention_catch_exec (struct breakpo printf_filtered (_("Catchpoint %d (exec)"), b->number); } +/* Implement the "print_recreate" breakpoint_ops method for exec + catchpoints. */ + +static void +print_recreate_catch_exec (struct breakpoint *b, struct ui_file *fp) +{ + fprintf_unfiltered (fp, "catch exec"); +} + static struct breakpoint_ops catch_exec_breakpoint_ops = { insert_catch_exec, @@ -6319,7 +6376,8 @@ static struct breakpoint_ops catch_exec_ breakpoint_hit_catch_exec, print_it_catch_exec, print_one_catch_exec, - print_mention_catch_exec + print_mention_catch_exec, + print_recreate_catch_exec }; static void @@ -8279,13 +8337,29 @@ print_mention_exception_catchpoint (stru : _(" (catch)")); } +/* Implement the "print_recreate" breakpoint_ops method for throw and + catch catchpoints. */ + +static void +print_recreate_exception_catchpoint (struct breakpoint *b, struct ui_file *fp) +{ + int bp_temp; + int bp_throw; + + bp_temp = b->disposition == disp_del; + bp_throw = strstr (b->addr_string, "throw") != NULL; + fprintf_unfiltered (fp, bp_temp ? "tcatch " : "catch "); + fprintf_unfiltered (fp, bp_throw ? "throw" : "catch"); +} + static struct breakpoint_ops gnu_v3_exception_catchpoint_ops = { NULL, /* insert */ NULL, /* remove */ NULL, /* breakpoint_hit */ print_exception_catchpoint, print_one_exception_catchpoint, - print_mention_exception_catchpoint + print_mention_exception_catchpoint, + print_recreate_exception_catchpoint }; static int @@ -10644,30 +10718,45 @@ get_tracepoint_by_number (char **arg, in return NULL; } -/* save-tracepoints command */ +/* The save-breakpoints command. */ + static void -tracepoint_save_command (char *args, int from_tty) +breakpoint_save (char *args, int from_tty, + int (*filter) (const struct breakpoint *)) { struct breakpoint *tp; - int any_tp = 0; - struct command_line *line; + int any = 0; char *pathname; char tmp[40]; struct cleanup *cleanup; struct ui_file *fp; + int extra_trace_bits = 0; + int created_count = 0; if (args == 0 || *args == 0) - error (_("Argument required (file name in which to save tracepoints)")); + error (_("Argument required (file name in which to save)")); /* See if we have anything to save. */ - ALL_TRACEPOINTS (tp) + ALL_BREAKPOINTS (tp) { - any_tp = 1; + /* Skip internal and momentary breakpoints. */ + if (tp->number <= 0) + continue; + + /* If we have a filter, only save the breakpoints it accepts. */ + if (filter && !filter (tp)) + continue; + + if (is_tracepoint (tp)) + extra_trace_bits = 1; + + any = 1; break; } - if (!any_tp) + + if (!any) { - warning (_("save-tracepoints: no tracepoints to save.")); + warning (_("Nothing to save.")); return; } @@ -10675,32 +10764,82 @@ tracepoint_save_command (char *args, int cleanup = make_cleanup (xfree, pathname); fp = gdb_fopen (pathname, "w"); if (!fp) - error (_("Unable to open file '%s' for saving tracepoints (%s)"), + error (_("Unable to open file '%s' for saving (%s)"), args, safe_strerror (errno)); make_cleanup_ui_file_delete (fp); - save_trace_state_variables (fp); + if (extra_trace_bits) + save_trace_state_variables (fp); - ALL_TRACEPOINTS (tp) + ALL_BREAKPOINTS (tp) { - if (tp->type == bp_fast_tracepoint) - fprintf_unfiltered (fp, "ftrace"); - else - fprintf_unfiltered (fp, "trace"); + /* Skip internal and momentary breakpoints. */ + if (tp->number <= 0) + continue; + + /* If we have a filter, only save the breakpoints it accepts. */ + if (filter && !filter (tp)) + continue; - if (tp->addr_string) - fprintf_unfiltered (fp, " %s", tp->addr_string); + if (tp->ops != NULL) + (tp->ops->print_recreate) (tp, fp); else { - sprintf_vma (tmp, tp->loc->address); - fprintf_unfiltered (fp, " *0x%s", tmp); + if (tp->type == bp_fast_tracepoint) + fprintf_unfiltered (fp, "ftrace"); + else if (tp->type == bp_tracepoint) + fprintf_unfiltered (fp, "trace"); + else if (tp->type == bp_breakpoint && tp->disposition == disp_del) + fprintf_unfiltered (fp, "tbreak"); + else if (tp->type == bp_breakpoint) + fprintf_unfiltered (fp, "break"); + else if (tp->type == bp_hardware_breakpoint + && tp->disposition == disp_del) + fprintf_unfiltered (fp, "thbreak"); + else if (tp->type == bp_hardware_breakpoint) + fprintf_unfiltered (fp, "hbreak"); + else if (tp->type == bp_watchpoint) + fprintf_unfiltered (fp, "watch"); + else if (tp->type == bp_hardware_watchpoint) + fprintf_unfiltered (fp, "watch"); + else if (tp->type == bp_read_watchpoint) + fprintf_unfiltered (fp, "rwatch"); + else if (tp->type == bp_access_watchpoint) + fprintf_unfiltered (fp, "awatch"); + else + internal_error (__FILE__, __LINE__, + _("unhandled breakpoint type %d"), + (int) tp->type); + + if (tp->exp_string) + fprintf_unfiltered (fp, " %s", tp->exp_string); + else if (tp->addr_string) + fprintf_unfiltered (fp, " %s", tp->addr_string); + else + { + sprintf_vma (tmp, tp->loc->address); + fprintf_unfiltered (fp, " *0x%s", tmp); + } } + if (tp->thread != -1) + fprintf_unfiltered (fp, " thread %d", tp->thread); + + if (tp->task != 0) + fprintf_unfiltered (fp, " task %d", tp->task); + if (tp->cond_string) fprintf_unfiltered (fp, " if %s", tp->cond_string); fprintf_unfiltered (fp, "\n"); + /* Note, can't rely on tp->number for anything, as we can't assume + the recreated breakpoint numbers will match. Use $bpnum + instead. */ + + if (tp->ignore_count) + fprintf_unfiltered (fp, " ignore $bpnum %d\n", tp->ignore_count); + if (tp->pass_count) fprintf_unfiltered (fp, " passcount %d\n", tp->pass_count); @@ -10708,7 +10847,7 @@ tracepoint_save_command (char *args, int { volatile struct gdb_exception ex; - fprintf_unfiltered (fp, " actions\n"); + fprintf_unfiltered (fp, " commands\n"); ui_out_redirect (uiout, fp); TRY_CATCH (ex, RETURN_MASK_ERROR) @@ -10722,15 +10861,44 @@ tracepoint_save_command (char *args, int fprintf_unfiltered (fp, " end\n"); } + + if (tp->enable_state == bp_disabled) + fprintf_unfiltered (fp, "disable $bpnum\n"); + + /* If this is a multi-location breakpoint, check if the locations + should be individually disabled. Watchpoint locations are + special, and not user visible. */ + if (!is_watchpoint (tp) && tp->loc && tp->loc->next) + { + struct bp_location *loc; + int n = 1; + + for (loc = tp->loc; loc != NULL; loc = loc->next, n++) + if (!loc->enabled) + fprintf_unfiltered (fp, "disable $bpnum.%d\n", n); + } } - if (*default_collect) + if (extra_trace_bits && *default_collect) fprintf_unfiltered (fp, "set default-collect %s\n", default_collect); do_cleanups (cleanup); if (from_tty) - printf_filtered (_("Tracepoints saved to file '%s'.\n"), args); - return; + printf_filtered (_("Saved to file '%s'.\n"), args); +} + +/* save-breakpoints command */ +static void +save_breakpoints_command (char *args, int from_tty) +{ + breakpoint_save (args, from_tty, NULL); +} + +/* save-tracepoints command */ +static void +tracepoint_save_command (char *args, int from_tty) +{ + breakpoint_save (args, from_tty, is_tracepoint); } /* Create a vector of all tracepoints. */ @@ -11232,6 +11400,11 @@ Save current tracepoint definitions as a Use the 'source' command in another debug session to restore them.")); set_cmd_completer (c, filename_completer); + c = add_com ("save-breakpoints", class_breakpoint, save_breakpoints_command, _("\ +Save current breakpoint definitions as a script.\n\ +Use the 'source' command in another debug session to restore them.")); + set_cmd_completer (c, filename_completer); + add_prefix_cmd ("breakpoint", class_maintenance, set_breakpoint_cmd, _("\ Breakpoint specific settings\n\ Configure various breakpoint-specific variables such as\n\ Index: src/gdb/breakpoint.h =================================================================== --- src.orig/gdb/breakpoint.h 2010-04-09 00:00:42.000000000 +0100 +++ src/gdb/breakpoint.h 2010-04-09 01:52:13.000000000 +0100 @@ -362,6 +362,9 @@ struct breakpoint_ops /* Display information about this breakpoint after setting it (roughly speaking; this is called from "mention"). */ void (*print_mention) (struct breakpoint *); + + /* Print to FP the CLI command that recreates this breakpoint. */ + void (*print_recreate) (struct breakpoint *, struct ui_file *fp); }; enum watchpoint_triggered Index: src/gdb/ada-lang.c =================================================================== --- src.orig/gdb/ada-lang.c 2010-04-09 01:45:10.000000000 +0100 +++ src/gdb/ada-lang.c 2010-04-09 03:09:50.000000000 +0100 @@ -10348,6 +10348,35 @@ print_mention_exception (enum exception_ } } +/* Implement the PRINT_RECREATE method in the breakpoint_ops structure + for all exception catchpoint kinds. */ + +static void +print_recreate_exception (enum exception_catchpoint_kind ex, + struct breakpoint *b, struct ui_file *fp) +{ + switch (ex) + { + case ex_catch_exception: + fprintf_filtered (fp, "catch exception"); + if (b->exp_string != NULL) + fprintf_filtered (fp, " %s", b->exp_string); + break; + + case ex_catch_exception_unhandled: + fprintf_filtered (fp, "catch unhandled"); + break; + + case ex_catch_assert: + fprintf_filtered (fp, "catch assert"); + break; + + default: + internal_error (__FILE__, __LINE__, _("unexpected catchpoint type")); + break; + } +} + /* Virtual table for "catch exception" breakpoints. */ static enum print_stop_action @@ -10368,6 +10397,12 @@ print_mention_catch_exception (struct br print_mention_exception (ex_catch_exception, b); } +static void +print_recreate_catch_exception (struct breakpoint *b, struct ui_file *fp) +{ + print_recreate_exception (ex_catch_exception, b, fp); +} + static struct breakpoint_ops catch_exception_breakpoint_ops = { NULL, /* insert */ @@ -10375,7 +10410,8 @@ static struct breakpoint_ops catch_excep NULL, /* breakpoint_hit */ print_it_catch_exception, print_one_catch_exception, - print_mention_catch_exception + print_mention_catch_exception, + print_recreate_catch_exception }; /* Virtual table for "catch exception unhandled" breakpoints. */ @@ -10399,13 +10435,21 @@ print_mention_catch_exception_unhandled print_mention_exception (ex_catch_exception_unhandled, b); } +static void +print_recreate_catch_exception_unhandled (struct breakpoint *b, + struct ui_file *fp) +{ + print_recreate_exception (ex_catch_exception_unhandled, b, fp); +} + static struct breakpoint_ops catch_exception_unhandled_breakpoint_ops = { NULL, /* insert */ NULL, /* remove */ NULL, /* breakpoint_hit */ print_it_catch_exception_unhandled, print_one_catch_exception_unhandled, - print_mention_catch_exception_unhandled + print_mention_catch_exception_unhandled, + print_recreate_catch_exception_unhandled }; /* Virtual table for "catch assert" breakpoints. */ @@ -10428,13 +10472,20 @@ print_mention_catch_assert (struct break print_mention_exception (ex_catch_assert, b); } +static void +print_recreate_catch_assert (struct breakpoint *b, struct ui_file *fp) +{ + print_recreate_exception (ex_catch_assert, b, fp); +} + static struct breakpoint_ops catch_assert_breakpoint_ops = { NULL, /* insert */ NULL, /* remove */ NULL, /* breakpoint_hit */ print_it_catch_assert, print_one_catch_assert, - print_mention_catch_assert + print_mention_catch_assert, + print_recreate_catch_assert }; /* Return non-zero if B is an Ada exception catchpoint. */ Index: src/gdb/doc/gdb.texinfo =================================================================== --- src.orig/gdb/doc/gdb.texinfo 2010-04-09 02:34:45.000000000 +0100 +++ src/gdb/doc/gdb.texinfo 2010-04-09 03:20:04.000000000 +0100 @@ -3247,6 +3247,7 @@ all breakpoints in that range are operat * Disabling:: Disabling breakpoints * Conditions:: Break conditions * Break Commands:: Breakpoint command lists +* Save Breakpoints:: How to save breakpoints in a file * Error in Breakpoints:: ``Cannot insert breakpoints'' * Breakpoint-related Warnings:: ``Breakpoint address adjusted...'' @end menu @@ -4401,6 +4402,23 @@ cont end @end smallexample +@node Save Breakpoints +@subsection How to save breakpoints to a file + +To save breakpoint definitions to a file use the +@code{save-breakpoints} command. + +@table @code +@kindex save-breakpoints +@cindex save breakpoints to a file for future sessions +@item save-breakpoints [@var{filename}] +This command saves all current breakpoint definitions together with +their commands and ignore counts, into a file @file{@var{filename}} +suitable for use in a later debugging session. To read the saved +breakpoint definitions, use the @code{source} command (@pxref{Command +Files}). +@end table + @c @ifclear BARETARGET @node Error in Breakpoints @subsection ``Cannot insert breakpoints'' Index: src/gdb/NEWS =================================================================== --- src.orig/gdb/NEWS 2010-04-09 02:38:50.000000000 +0100 +++ src/gdb/NEWS 2010-04-09 02:44:43.000000000 +0100 @@ -23,6 +23,13 @@ single `break' command creates multiple breakpoints (e.g., breakpoints on overloaded c++ functions). +* New commands + +save-breakpoints filename + Save all current breakpoint definitions to a file suitable for use + in a later debugging session. To read the saved breakpoint + definitions, use the `source' command. + * Python scripting ** The GDB Python API now has access to symbols, symbol tables, and Index: src/gdb/testsuite/gdb.trace/save-trace.exp =================================================================== --- src.orig/gdb/testsuite/gdb.trace/save-trace.exp 2010-04-09 03:29:29.000000000 +0100 +++ src/gdb/testsuite/gdb.trace/save-trace.exp 2010-04-09 03:29:49.000000000 +0100 @@ -129,7 +129,7 @@ gdb_verify_tracepoints "10.x: verify tra remote_file host delete savetrace.tr gdb_test "save-tracepoints savetrace.tr" \ - "Tracepoints saved to file 'savetrace.tr'." \ + "Saved to file 'savetrace.tr'." \ "10.1: save tracepoint definitions" # 10.2 Read back tracepoint definitions @@ -147,7 +147,7 @@ remote_file host delete savetrace.tr set escapedfilename [string_to_regexp $objdir/savetrace.tr] remote_file host delete $objdir/savetrace.tr gdb_test "save-tracepoints $objdir/savetrace.tr" \ - "Tracepoints saved to file '${escapedfilename}'." \ + "Saved to file '${escapedfilename}'." \ "10.3: save tracepoint definitions, full path" gdb_delete_tracepoints