X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=gdb%2Fmi%2Fmi-cmd-break.c;h=332d9e287ba35278275aa8c79d55215a7524e893;hb=c9657e708a03cb06ad92ce81bf17c68d28e57689;hp=9ab8f2df775ab3ba08ceef4fe584ea8168b78374;hpb=48cb2d85819efcb448e7b635e0a5da776f5bfd8c;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/mi/mi-cmd-break.c b/gdb/mi/mi-cmd-break.c index 9ab8f2df77..332d9e287b 100644 --- a/gdb/mi/mi-cmd-break.c +++ b/gdb/mi/mi-cmd-break.c @@ -1,6 +1,5 @@ /* MI Command Set - breakpoint and watchpoint commands. - Copyright (C) 2000, 2001, 2002, 2007, 2008, 2009 - Free Software Foundation, Inc. + Copyright (C) 2000-2014 Free Software Foundation, Inc. Contributed by Cygnus Solutions (a Red Hat company). This file is part of GDB. @@ -24,11 +23,13 @@ #include "ui-out.h" #include "mi-out.h" #include "breakpoint.h" -#include "gdb_string.h" #include "mi-getopt.h" #include "gdb.h" -#include "exceptions.h" #include "observer.h" +#include "mi-main.h" +#include "mi-cmd-break.h" +#include "gdb_obstack.h" +#include enum { @@ -43,13 +44,13 @@ static int mi_breakpoint_observers_installed; static int mi_can_breakpoint_notify; -/* Output a single breakpoint, when allowed. */ +/* Output a single breakpoint, when allowed. */ static void -breakpoint_notify (int b) +breakpoint_notify (struct breakpoint *b) { if (mi_can_breakpoint_notify) - gdb_breakpoint_query (uiout, b, NULL); + gdb_breakpoint_query (current_uiout, b->number, NULL); } enum bp_type @@ -59,29 +60,133 @@ enum bp_type REGEXP_BP }; -/* Implements the -break-insert command. - See the MI manual for the list of possible options. */ +/* Arrange for all new breakpoints and catchpoints to be reported to + CURRENT_UIOUT until the cleanup returned by this function is run. -void -mi_cmd_break_insert (char *command, char **argv, int argc) + Note that MI output will be probably invalid if more than one + breakpoint is created inside one MI command. */ + +struct cleanup * +setup_breakpoint_reporting (void) +{ + struct cleanup *rev_flag; + + if (! mi_breakpoint_observers_installed) + { + observer_attach_breakpoint_created (breakpoint_notify); + mi_breakpoint_observers_installed = 1; + } + + rev_flag = make_cleanup_restore_integer (&mi_can_breakpoint_notify); + mi_can_breakpoint_notify = 1; + + return rev_flag; +} + + +/* Convert arguments in ARGV to the string in "format",argv,argv... + and return it. */ + +static char * +mi_argv_to_format (char **argv, int argc) +{ + int i; + struct obstack obstack; + char *ret; + + obstack_init (&obstack); + + /* Convert ARGV[OIND + 1] to format string and save to FORMAT. */ + obstack_1grow (&obstack, '\"'); + for (i = 0; i < strlen (argv[0]); i++) + { + switch (argv[0][i]) + { + case '\\': + obstack_grow (&obstack, "\\\\", 2); + break; + case '\a': + obstack_grow (&obstack, "\\a", 2); + break; + case '\b': + obstack_grow (&obstack, "\\b", 2); + break; + case '\f': + obstack_grow (&obstack, "\\f", 2); + break; + case '\n': + obstack_grow (&obstack, "\\n", 2); + break; + case '\r': + obstack_grow (&obstack, "\\r", 2); + break; + case '\t': + obstack_grow (&obstack, "\\t", 2); + break; + case '\v': + obstack_grow (&obstack, "\\v", 2); + break; + case '"': + obstack_grow (&obstack, "\\\"", 2); + break; + default: + if (isprint (argv[0][i])) + obstack_grow (&obstack, argv[0] + i, 1); + else + { + char tmp[5]; + + xsnprintf (tmp, sizeof (tmp), "\\%o", + (unsigned char) argv[0][i]); + obstack_grow (&obstack, tmp, strlen (tmp)); + } + break; + } + } + obstack_1grow (&obstack, '\"'); + + /* Apply other argv to FORMAT. */ + for (i = 1; i < argc; i++) + { + obstack_1grow (&obstack, ','); + obstack_grow (&obstack, argv[i], strlen (argv[i])); + } + obstack_1grow (&obstack, '\0'); + + ret = xstrdup (obstack_finish (&obstack)); + obstack_free (&obstack, NULL); + + return ret; +} + +/* Insert breakpoint. + If dprintf is true, it will insert dprintf. + If not, it will insert other type breakpoint. */ + +static void +mi_cmd_break_insert_1 (int dprintf, char *command, char **argv, int argc) { char *address = NULL; - enum bp_type type = REG_BP; + int hardware = 0; int temp_p = 0; int thread = -1; int ignore_count = 0; char *condition = NULL; int pending = 0; int enabled = 1; + int tracepoint = 0; + struct cleanup *back_to = make_cleanup (null_cleanup, NULL); + enum bptype type_wanted; + struct breakpoint_ops *ops; + char *extra_string = NULL; - struct gdb_exception e; - struct gdb_events *old_hooks; enum opt { - HARDWARE_OPT, TEMP_OPT /*, REGEXP_OPT */ , CONDITION_OPT, - IGNORE_COUNT_OPT, THREAD_OPT, PENDING_OPT, DISABLE_OPT + HARDWARE_OPT, TEMP_OPT, CONDITION_OPT, + IGNORE_COUNT_OPT, THREAD_OPT, PENDING_OPT, DISABLE_OPT, + TRACEPOINT_OPT, }; - static struct mi_opt opts[] = + static const struct mi_opt opts[] = { {"h", HARDWARE_OPT, 0}, {"t", TEMP_OPT, 0}, @@ -90,16 +195,19 @@ mi_cmd_break_insert (char *command, char **argv, int argc) {"p", THREAD_OPT, 1}, {"f", PENDING_OPT, 0}, {"d", DISABLE_OPT, 0}, + {"a", TRACEPOINT_OPT, 0}, { 0, 0, 0 } }; /* Parse arguments. It could be -r or -h or -t, or ``--'' to denote the end of the option list. */ - int optind = 0; - char *optarg; + int oind = 0; + char *oarg; + while (1) { - int opt = mi_getopt ("mi_cmd_break_insert", argc, argv, opts, &optind, &optarg); + int opt = mi_getopt ("-break-insert", argc, argv, + opts, &oind, &oarg); if (opt < 0) break; switch ((enum opt) opt) @@ -108,79 +216,103 @@ mi_cmd_break_insert (char *command, char **argv, int argc) temp_p = 1; break; case HARDWARE_OPT: - type = HW_BP; + hardware = 1; break; -#if 0 - case REGEXP_OPT: - type = REGEXP_BP; - break; -#endif case CONDITION_OPT: - condition = optarg; + condition = oarg; break; case IGNORE_COUNT_OPT: - ignore_count = atol (optarg); + ignore_count = atol (oarg); break; case THREAD_OPT: - thread = atol (optarg); + thread = atol (oarg); break; case PENDING_OPT: pending = 1; break; case DISABLE_OPT: enabled = 0; + break; + case TRACEPOINT_OPT: + tracepoint = 1; + break; } } - if (optind >= argc) - error (_("mi_cmd_break_insert: Missing ")); - if (optind < argc - 1) - error (_("mi_cmd_break_insert: Garbage following ")); - address = argv[optind]; + if (oind >= argc) + error (_("-%s-insert: Missing "), + dprintf ? "dprintf" : "break"); + address = argv[oind]; + if (dprintf) + { + int format_num = oind + 1; - /* Now we have what we need, let's insert the breakpoint! */ - if (! mi_breakpoint_observers_installed) + if (hardware || tracepoint) + error (_("-dprintf-insert: does not support -h or -a")); + if (format_num >= argc) + error (_("-dprintf-insert: Missing ")); + + extra_string = mi_argv_to_format (argv + format_num, argc - format_num); + make_cleanup (xfree, extra_string); + } + else { - observer_attach_breakpoint_created (breakpoint_notify); - observer_attach_breakpoint_modified (breakpoint_notify); - observer_attach_breakpoint_deleted (breakpoint_notify); - mi_breakpoint_observers_installed = 1; + if (oind < argc - 1) + error (_("-break-insert: Garbage following ")); } - mi_can_breakpoint_notify = 1; - /* Make sure we restore hooks even if exception is thrown. */ - TRY_CATCH (e, RETURN_MASK_ALL) + /* Now we have what we need, let's insert the breakpoint! */ + setup_breakpoint_reporting (); + + if (tracepoint) { - switch (type) - { - case REG_BP: - set_breakpoint (get_current_arch (), address, condition, - 0 /*hardwareflag */ , temp_p, - thread, ignore_count, - pending, enabled); - break; - case HW_BP: - set_breakpoint (get_current_arch (), address, condition, - 1 /*hardwareflag */ , temp_p, - thread, ignore_count, - pending, enabled); - break; -#if 0 - case REGEXP_BP: - if (temp_p) - error (_("mi_cmd_break_insert: Unsupported tempoary regexp breakpoint")); - else - rbreak_command_wrapper (address, FROM_TTY); - break; -#endif - default: - internal_error (__FILE__, __LINE__, - _("mi_cmd_break_insert: Bad switch.")); - } + /* Note that to request a fast tracepoint, the client uses the + "hardware" flag, although there's nothing of hardware related to + fast tracepoints -- one can implement slow tracepoints with + hardware breakpoints, but fast tracepoints are always software. + "fast" is a misnomer, actually, "jump" would be more appropriate. + A simulator or an emulator could conceivably implement fast + regular non-jump based tracepoints. */ + type_wanted = hardware ? bp_fast_tracepoint : bp_tracepoint; + ops = &tracepoint_breakpoint_ops; } - mi_can_breakpoint_notify = 0; - if (e.reason < 0) - throw_exception (e); + else if (dprintf) + { + type_wanted = bp_dprintf; + ops = &dprintf_breakpoint_ops; + } + else + { + type_wanted = hardware ? bp_hardware_breakpoint : bp_breakpoint; + ops = &bkpt_breakpoint_ops; + } + + create_breakpoint (get_current_arch (), address, condition, thread, + extra_string, + 0 /* condition and thread are valid. */, + temp_p, type_wanted, + ignore_count, + pending ? AUTO_BOOLEAN_TRUE : AUTO_BOOLEAN_FALSE, + ops, 0, enabled, 0, 0); + do_cleanups (back_to); +} + +/* Implements the -break-insert command. + See the MI manual for the list of possible options. */ + +void +mi_cmd_break_insert (char *command, char **argv, int argc) +{ + mi_cmd_break_insert_1 (0, command, argv, argc); +} + +/* Implements the -dprintf-insert command. + See the MI manual for the list of possible options. */ + +void +mi_cmd_dprintf_insert (char *command, char **argv, int argc) +{ + mi_cmd_break_insert_1 (1, command, argv, argc); } enum wp_type @@ -190,11 +322,36 @@ enum wp_type ACCESS_WP }; +void +mi_cmd_break_passcount (char *command, char **argv, int argc) +{ + int n; + int p; + struct tracepoint *t; + + if (argc != 2) + error (_("Usage: tracepoint-number passcount")); + + n = atoi (argv[0]); + p = atoi (argv[1]); + t = get_tracepoint (n); + + if (t) + { + t->pass_count = p; + observer_notify_breakpoint_modified (&t->base); + } + else + { + error (_("Could not find tracepoint %d"), n); + } +} + /* Insert a watchpoint. The type of watchpoint is specified by the first argument: -break-watch --> insert a regular wp. -break-watch -r --> insert a read watchpoint. - -break-watch -a --> insert an access wp. */ + -break-watch -a --> insert an access wp. */ void mi_cmd_break_watch (char *command, char **argv, int argc) @@ -205,7 +362,7 @@ mi_cmd_break_watch (char *command, char **argv, int argc) { READ_OPT, ACCESS_OPT }; - static struct mi_opt opts[] = + static const struct mi_opt opts[] = { {"r", READ_OPT, 0}, {"a", ACCESS_OPT, 0}, @@ -213,11 +370,14 @@ mi_cmd_break_watch (char *command, char **argv, int argc) }; /* Parse arguments. */ - int optind = 0; - char *optarg; + int oind = 0; + char *oarg; + while (1) { - int opt = mi_getopt ("mi_cmd_break_watch", argc, argv, opts, &optind, &optarg); + int opt = mi_getopt ("-break-watch", argc, argv, + opts, &oind, &oarg); + if (opt < 0) break; switch ((enum opt) opt) @@ -230,26 +390,26 @@ mi_cmd_break_watch (char *command, char **argv, int argc) break; } } - if (optind >= argc) - error (_("mi_cmd_break_watch: Missing ")); - if (optind < argc - 1) - error (_("mi_cmd_break_watch: Garbage following ")); - expr = argv[optind]; + if (oind >= argc) + error (_("-break-watch: Missing ")); + if (oind < argc - 1) + error (_("-break-watch: Garbage following ")); + expr = argv[oind]; - /* Now we have what we need, let's insert the watchpoint! */ + /* Now we have what we need, let's insert the watchpoint! */ switch (type) { case REG_WP: - watch_command_wrapper (expr, FROM_TTY); + watch_command_wrapper (expr, FROM_TTY, 0); break; case READ_WP: - rwatch_command_wrapper (expr, FROM_TTY); + rwatch_command_wrapper (expr, FROM_TTY, 0); break; case ACCESS_WP: - awatch_command_wrapper (expr, FROM_TTY); + awatch_command_wrapper (expr, FROM_TTY, 0); break; default: - error (_("mi_cmd_break_watch: Unknown watchpoint type.")); + error (_("-break-watch: Unknown watchpoint type.")); } } @@ -263,7 +423,7 @@ static int mi_command_line_array_cnt; static int mi_command_line_array_ptr; static char * -mi_read_next_line () +mi_read_next_line (void) { if (mi_command_line_array_ptr == mi_command_line_array_cnt) return NULL; @@ -280,25 +440,30 @@ mi_cmd_break_commands (char *command, char **argv, int argc) struct breakpoint *b; if (argc < 1) - error ("USAGE: %s [ [...]]", command); + error (_("USAGE: %s [ [...]]"), command); bnum = strtol (argv[0], &endptr, 0); if (endptr == argv[0]) - error ("breakpoint number argument \"%s\" is not a number.", + error (_("breakpoint number argument \"%s\" is not a number."), argv[0]); else if (*endptr != '\0') - error ("junk at the end of breakpoint number argument \"%s\".", + error (_("junk at the end of breakpoint number argument \"%s\"."), argv[0]); b = get_breakpoint (bnum); if (b == NULL) - error ("breakpoint %d not found.", bnum); + error (_("breakpoint %d not found."), bnum); mi_command_line_array = argv; mi_command_line_array_ptr = 1; mi_command_line_array_cnt = argc; - break_command = read_command_lines_1 (mi_read_next_line, 0); + if (is_tracepoint (b)) + break_command = read_command_lines_1 (mi_read_next_line, 1, + check_tracepoint_command, b); + else + break_command = read_command_lines_1 (mi_read_next_line, 1, 0, 0); + breakpoint_set_commands (b, break_command); }