X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=gdb%2Fmi%2Fmi-cmd-break.c;h=cfe2d34f23fdd9823a025d82bd4c405d258f92aa;hb=93921405a46c0a58eae19fffb92e02416082801a;hp=c5a098e9d02587d042d16d7e85c24f86be591eb4;hpb=9b4c786c6c9f2599873343b935a46a446ba1c029;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/mi/mi-cmd-break.c b/gdb/mi/mi-cmd-break.c index c5a098e9d0..cfe2d34f23 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, 2010 - Free Software Foundation, Inc. + Copyright (C) 2000-2017 Free Software Foundation, Inc. Contributed by Cygnus Solutions (a Red Hat company). This file is part of GDB. @@ -24,11 +23,16 @@ #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 "language.h" +#include "location.h" +#include "linespec.h" +#include "gdb_obstack.h" +#include enum { @@ -43,13 +47,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,14 +63,113 @@ 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 ((const char *) 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, const 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; @@ -75,17 +178,23 @@ mi_cmd_break_insert (char *command, char **argv, int argc) int pending = 0; int enabled = 1; int tracepoint = 0; - struct cleanup *back_to; + struct cleanup *back_to = make_cleanup (null_cleanup, NULL); + enum bptype type_wanted; + event_location_up location; + struct breakpoint_ops *ops; + int is_explicit = 0; + struct explicit_location explicit_loc; + char *extra_string = NULL; - struct gdb_exception e; - struct gdb_events *old_hooks; enum opt { HARDWARE_OPT, TEMP_OPT, CONDITION_OPT, IGNORE_COUNT_OPT, THREAD_OPT, PENDING_OPT, DISABLE_OPT, TRACEPOINT_OPT, + EXPLICIT_SOURCE_OPT, EXPLICIT_FUNC_OPT, + EXPLICIT_LABEL_OPT, EXPLICIT_LINE_OPT }; - static struct mi_opt opts[] = + static const struct mi_opt opts[] = { {"h", HARDWARE_OPT, 0}, {"t", TEMP_OPT, 0}, @@ -95,16 +204,24 @@ mi_cmd_break_insert (char *command, char **argv, int argc) {"f", PENDING_OPT, 0}, {"d", DISABLE_OPT, 0}, {"a", TRACEPOINT_OPT, 0}, + {"-source" , EXPLICIT_SOURCE_OPT, 1}, + {"-function", EXPLICIT_FUNC_OPT, 1}, + {"-label", EXPLICIT_LABEL_OPT, 1}, + {"-line", EXPLICIT_LINE_OPT, 1}, { 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; + + initialize_explicit_location (&explicit_loc); + 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) @@ -116,13 +233,13 @@ mi_cmd_break_insert (char *command, char **argv, int argc) hardware = 1; break; 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; @@ -133,34 +250,128 @@ mi_cmd_break_insert (char *command, char **argv, int argc) case TRACEPOINT_OPT: tracepoint = 1; break; + case EXPLICIT_SOURCE_OPT: + is_explicit = 1; + explicit_loc.source_filename = oarg; + break; + case EXPLICIT_FUNC_OPT: + is_explicit = 1; + explicit_loc.function_name = oarg; + break; + case EXPLICIT_LABEL_OPT: + is_explicit = 1; + explicit_loc.label_name = oarg; + break; + case EXPLICIT_LINE_OPT: + is_explicit = 1; + explicit_loc.line_offset = linespec_parse_line_offset (oarg); + 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 && !is_explicit) + error (_("-%s-insert: Missing "), + dprintf ? "dprintf" : "break"); + if (dprintf) + { + int format_num = is_explicit ? oind : oind + 1; + + if (hardware || tracepoint) + error (_("-dprintf-insert: does not support -h or -a")); + if (format_num >= argc) + error (_("-dprintf-insert: Missing ")); - /* Now we have what we need, let's insert the breakpoint! */ - if (! mi_breakpoint_observers_installed) + extra_string = mi_argv_to_format (argv + format_num, argc - format_num); + make_cleanup (xfree, extra_string); + address = argv[oind]; + } + 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 (is_explicit) + { + if (oind < argc) + error (_("-break-insert: Garbage following explicit location")); + } + else + { + if (oind < argc - 1) + error (_("-break-insert: Garbage following ")); + address = argv[oind]; + } } - back_to = make_cleanup_restore_integer (&mi_can_breakpoint_notify); - mi_can_breakpoint_notify = 1; - create_breakpoint (get_current_arch (), address, condition, thread, + /* Now we have what we need, let's insert the breakpoint! */ + setup_breakpoint_reporting (); + + if (tracepoint) + { + /* 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; + } + else if (dprintf) + { + type_wanted = bp_dprintf; + ops = &dprintf_breakpoint_ops; + } + else + { + type_wanted = hardware ? bp_hardware_breakpoint : bp_breakpoint; + ops = &bkpt_breakpoint_ops; + } + + if (is_explicit) + { + /* Error check -- we must have one of the other + parameters specified. */ + if (explicit_loc.source_filename != NULL + && explicit_loc.function_name == NULL + && explicit_loc.label_name == NULL + && explicit_loc.line_offset.sign == LINE_OFFSET_UNKNOWN) + error (_("-%s-insert: --source option requires --function, --label," + " or --line"), dprintf ? "dprintf" : "break"); + + location = new_explicit_location (&explicit_loc); + } + else + { + location = string_to_event_location_basic (&address, current_language); + if (*address) + error (_("Garbage '%s' at end of location"), address); + } + + create_breakpoint (get_current_arch (), location.get (), condition, thread, + extra_string, 0 /* condition and thread are valid. */, - temp_p, hardware, tracepoint, + temp_p, type_wanted, ignore_count, pending ? AUTO_BOOLEAN_TRUE : AUTO_BOOLEAN_FALSE, - NULL, 0, enabled); + 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 (const 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 (const char *command, char **argv, int argc) +{ + mi_cmd_break_insert_1 (1, command, argv, argc); } enum wp_type @@ -171,11 +382,11 @@ enum wp_type }; void -mi_cmd_break_passcount (char *command, char **argv, int argc) +mi_cmd_break_passcount (const char *command, char **argv, int argc) { int n; int p; - struct breakpoint *t; + struct tracepoint *t; if (argc != 2) error (_("Usage: tracepoint-number passcount")); @@ -187,11 +398,11 @@ mi_cmd_break_passcount (char *command, char **argv, int argc) if (t) { t->pass_count = p; - observer_notify_tracepoint_modified (n); + observer_notify_breakpoint_modified (&t->base); } else { - error (_("Cound not find tracepoint %d"), n); + error (_("Could not find tracepoint %d"), n); } } @@ -199,10 +410,10 @@ mi_cmd_break_passcount (char *command, char **argv, int argc) 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) +mi_cmd_break_watch (const char *command, char **argv, int argc) { char *expr = NULL; enum wp_type type = REG_WP; @@ -210,7 +421,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}, @@ -218,11 +429,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) @@ -235,26 +449,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.")); } } @@ -277,38 +491,38 @@ mi_read_next_line (void) } void -mi_cmd_break_commands (char *command, char **argv, int argc) +mi_cmd_break_commands (const char *command, char **argv, int argc) { - struct command_line *break_command; + command_line_up break_command; char *endptr; int bnum; 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; - if (breakpoint_is_tracepoint (b)) + 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); + breakpoint_set_commands (b, std::move (break_command)); }