X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=gdb%2Ftracepoint.c;h=8e04cad504e9a039c51204bfe9021ef818d7967a;hb=b61121178ec07f9da1242e439fe1a23a314ad30e;hp=bc45470153e504f631e8a87340a2f008fe1ce6e9;hpb=c2f4122d5cc2a21a441470336c8637b6a6965c6e;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/tracepoint.c b/gdb/tracepoint.c index bc45470153..8e04cad504 100644 --- a/gdb/tracepoint.c +++ b/gdb/tracepoint.c @@ -1,6 +1,6 @@ /* Tracing functionality for remote targets in custom GDB protocol - Copyright (C) 1997-2016 Free Software Foundation, Inc. + Copyright (C) 1997-2019 Free Software Foundation, Inc. This file is part of GDB. @@ -36,7 +36,7 @@ #include "completer.h" #include "block.h" #include "dictionary.h" -#include "observer.h" +#include "observable.h" #include "user-regs.h" #include "valprint.h" #include "gdbcore.h" @@ -51,18 +51,12 @@ #include "memrange.h" #include "cli/cli-utils.h" #include "probe.h" -#include "ctf.h" -#include "filestuff.h" -#include "rsp-low.h" +#include "gdbsupport/filestuff.h" +#include "gdbsupport/rsp-low.h" #include "tracefile.h" #include "location.h" - -/* readline include files */ -#include "readline/readline.h" -#include "readline/history.h" - -/* readline defines this. */ -#undef savestring +#include +#include "cli/cli-style.h" #include @@ -113,10 +107,7 @@ void (*deprecated_trace_start_stop_hook) (int start, int from_tty); any of these for any reason - API is by name or number only - so it works to have a vector of objects. */ -typedef struct trace_state_variable tsv_s; -DEF_VEC_O(tsv_s); - -static VEC(tsv_s) *tvariables; +static std::vector tvariables; /* The next integer to assign to a variable. */ @@ -132,20 +123,20 @@ static int tracepoint_number; yet attempted to fetch it, or if the target does not support fetching this object, or if we're not inspecting a traceframe presently. */ -static struct traceframe_info *traceframe_info; +static traceframe_info_up current_traceframe_info; /* Tracing command lists. */ static struct cmd_list_element *tfindlist; /* List of expressions to collect by default at each tracepoint hit. */ -char *default_collect = ""; +char *default_collect; -static int disconnected_tracing; +static bool disconnected_tracing; /* This variable controls whether we ask the target for a linear or circular trace buffer. */ -static int circular_trace_buffer; +static bool circular_trace_buffer; /* This variable is the requested trace buffer size, or -1 to indicate that we don't care and leave it up to the target to set a size. */ @@ -164,31 +155,12 @@ char *trace_notes = NULL; char *trace_stop_notes = NULL; -/* ======= Important command functions: ======= */ -static void trace_actions_command (char *, int); -static void trace_start_command (char *, int); -static void trace_stop_command (char *, int); -static void trace_status_command (char *, int); -static void trace_find_command (char *, int); -static void trace_find_pc_command (char *, int); -static void trace_find_tracepoint_command (char *, int); -static void trace_find_line_command (char *, int); -static void trace_find_range_command (char *, int); -static void trace_find_outside_command (char *, int); -static void trace_dump_command (char *, int); - /* support routines */ struct collection_list; -static void add_aexpr (struct collection_list *, struct agent_expr *); static char *mem2hex (gdb_byte *, char *, int); -static void add_register (struct collection_list *collection, - unsigned int regno); - -static struct command_line * - all_tracepoint_actions_and_cleanup (struct breakpoint *t); -extern void _initialize_tracepoint (void); +static counted_command_line all_tracepoint_actions (struct breakpoint *); static struct trace_status trace_status; @@ -208,28 +180,13 @@ current_trace_status (void) return &trace_status; } -/* Destroy INFO. */ - -static void -free_traceframe_info (struct traceframe_info *info) -{ - if (info != NULL) - { - VEC_free (mem_range_s, info->memory); - VEC_free (int, info->tvars); - - xfree (info); - } -} - /* Free and clear the traceframe info cache of the current traceframe. */ static void clear_traceframe_info (void) { - free_traceframe_info (traceframe_info); - traceframe_info = NULL; + current_traceframe_info = NULL; } /* Set traceframe number to NUM. */ @@ -256,7 +213,7 @@ set_traceframe_context (struct frame_info *trace_frame) { CORE_ADDR trace_pc; struct symbol *traceframe_fun; - struct symtab_and_line traceframe_sal; + symtab_and_line traceframe_sal; /* Save as globals for internal use. */ if (trace_frame != NULL @@ -272,7 +229,6 @@ set_traceframe_context (struct frame_info *trace_frame) } else { - init_sal (&traceframe_sal); traceframe_fun = NULL; set_internalvar_integer (lookup_internalvar ("trace_line"), -1); } @@ -280,11 +236,11 @@ set_traceframe_context (struct frame_info *trace_frame) /* Save func name as "$trace_func", a debugger variable visible to users. */ if (traceframe_fun == NULL - || SYMBOL_LINKAGE_NAME (traceframe_fun) == NULL) + || traceframe_fun->linkage_name () == NULL) clear_internalvar (lookup_internalvar ("trace_func")); else set_internalvar_string (lookup_internalvar ("trace_func"), - SYMBOL_LINKAGE_NAME (traceframe_fun)); + traceframe_fun->linkage_name ()); /* Save file name as "$trace_file", a debugger variable visible to users. */ @@ -300,12 +256,8 @@ set_traceframe_context (struct frame_info *trace_frame) struct trace_state_variable * create_trace_state_variable (const char *name) { - struct trace_state_variable tsv; - - memset (&tsv, 0, sizeof (tsv)); - tsv.name = xstrdup (name); - tsv.number = next_tsv_number++; - return VEC_safe_push (tsv_s, tvariables, &tsv); + tvariables.emplace_back (name, next_tsv_number++); + return &tvariables.back (); } /* Look for a trace state variable of the given name. */ @@ -313,12 +265,9 @@ create_trace_state_variable (const char *name) struct trace_state_variable * find_trace_state_variable (const char *name) { - struct trace_state_variable *tsv; - int ix; - - for (ix = 0; VEC_iterate (tsv_s, tvariables, ix, tsv); ++ix) - if (strcmp (name, tsv->name) == 0) - return tsv; + for (trace_state_variable &tsv : tvariables) + if (tsv.name == name) + return &tsv; return NULL; } @@ -329,12 +278,9 @@ find_trace_state_variable (const char *name) struct trace_state_variable * find_trace_state_variable_by_number (int number) { - struct trace_state_variable *tsv; - int ix; - - for (ix = 0; VEC_iterate (tsv_s, tvariables, ix, tsv); ++ix) - if (tsv->number == number) - return tsv; + for (trace_state_variable &tsv : tvariables) + if (tsv.number == number) + return &tsv; return NULL; } @@ -342,17 +288,11 @@ find_trace_state_variable_by_number (int number) static void delete_trace_state_variable (const char *name) { - struct trace_state_variable *tsv; - int ix; - - for (ix = 0; VEC_iterate (tsv_s, tvariables, ix, tsv); ++ix) - if (strcmp (name, tsv->name) == 0) + for (auto it = tvariables.begin (); it != tvariables.end (); it++) + if (it->name == name) { - observer_notify_tsv_deleted (tsv); - - xfree ((void *)tsv->name); - VEC_unordered_remove (tsv_s, tvariables, ix); - + gdb::observers::tsv_deleted.notify (&*it); + tvariables.erase (it); return; } @@ -387,12 +327,11 @@ validate_trace_state_variable_name (const char *name) evaluate into an initial value. */ static void -trace_variable_command (char *args, int from_tty) +trace_variable_command (const char *args, int from_tty) { - struct cleanup *old_chain; LONGEST initval = 0; struct trace_state_variable *tsv; - char *name, *p; + const char *name_start, *p; if (!args || !*args) error_no_arg (_("Syntax is $NAME [ = EXPR ]")); @@ -403,150 +342,133 @@ trace_variable_command (char *args, int from_tty) if (*p++ != '$') error (_("Name of trace variable should start with '$'")); - name = p; + name_start = p; while (isalnum (*p) || *p == '_') p++; - name = savestring (name, p - name); - old_chain = make_cleanup (xfree, name); + std::string name (name_start, p - name_start); p = skip_spaces (p); if (*p != '=' && *p != '\0') error (_("Syntax must be $NAME [ = EXPR ]")); - validate_trace_state_variable_name (name); + validate_trace_state_variable_name (name.c_str ()); if (*p == '=') initval = value_as_long (parse_and_eval (++p)); /* If the variable already exists, just change its initial value. */ - tsv = find_trace_state_variable (name); + tsv = find_trace_state_variable (name.c_str ()); if (tsv) { if (tsv->initial_value != initval) { tsv->initial_value = initval; - observer_notify_tsv_modified (tsv); + gdb::observers::tsv_modified.notify (tsv); } printf_filtered (_("Trace state variable $%s " "now has initial value %s.\n"), - tsv->name, plongest (tsv->initial_value)); - do_cleanups (old_chain); + tsv->name.c_str (), plongest (tsv->initial_value)); return; } /* Create a new variable. */ - tsv = create_trace_state_variable (name); + tsv = create_trace_state_variable (name.c_str ()); tsv->initial_value = initval; - observer_notify_tsv_created (tsv); + gdb::observers::tsv_created.notify (tsv); printf_filtered (_("Trace state variable $%s " "created, with initial value %s.\n"), - tsv->name, plongest (tsv->initial_value)); - - do_cleanups (old_chain); + tsv->name.c_str (), plongest (tsv->initial_value)); } static void -delete_trace_variable_command (char *args, int from_tty) +delete_trace_variable_command (const char *args, int from_tty) { - int ix; - char **argv; - struct cleanup *back_to; - if (args == NULL) { if (query (_("Delete all trace state variables? "))) - VEC_free (tsv_s, tvariables); + tvariables.clear (); dont_repeat (); - observer_notify_tsv_deleted (NULL); + gdb::observers::tsv_deleted.notify (NULL); return; } - argv = gdb_buildargv (args); - back_to = make_cleanup_freeargv (argv); + gdb_argv argv (args); - for (ix = 0; argv[ix] != NULL; ix++) + for (char *arg : argv) { - if (*argv[ix] == '$') - delete_trace_state_variable (argv[ix] + 1); + if (*arg == '$') + delete_trace_state_variable (arg + 1); else - warning (_("Name \"%s\" not prefixed with '$', ignoring"), argv[ix]); + warning (_("Name \"%s\" not prefixed with '$', ignoring"), arg); } - do_cleanups (back_to); - dont_repeat (); } void tvariables_info_1 (void) { - struct trace_state_variable *tsv; - int ix; - int count = 0; - struct cleanup *back_to; struct ui_out *uiout = current_uiout; - if (VEC_length (tsv_s, tvariables) == 0 && !ui_out_is_mi_like_p (uiout)) - { - printf_filtered (_("No trace state variables.\n")); - return; - } - /* Try to acquire values from the target. */ - for (ix = 0; VEC_iterate (tsv_s, tvariables, ix, tsv); ++ix, ++count) - tsv->value_known = target_get_trace_state_variable_value (tsv->number, - &(tsv->value)); + for (trace_state_variable &tsv : tvariables) + tsv.value_known + = target_get_trace_state_variable_value (tsv.number, &tsv.value); - back_to = make_cleanup_ui_out_table_begin_end (uiout, 3, - count, "trace-variables"); - ui_out_table_header (uiout, 15, ui_left, "name", "Name"); - ui_out_table_header (uiout, 11, ui_left, "initial", "Initial"); - ui_out_table_header (uiout, 11, ui_left, "current", "Current"); + { + ui_out_emit_table table_emitter (uiout, 3, tvariables.size (), + "trace-variables"); + uiout->table_header (15, ui_left, "name", "Name"); + uiout->table_header (11, ui_left, "initial", "Initial"); + uiout->table_header (11, ui_left, "current", "Current"); - ui_out_table_body (uiout); + uiout->table_body (); - for (ix = 0; VEC_iterate (tsv_s, tvariables, ix, tsv); ++ix) - { - struct cleanup *back_to2; - char *c; - char *name; - - back_to2 = make_cleanup_ui_out_tuple_begin_end (uiout, "variable"); - - name = concat ("$", tsv->name, (char *) NULL); - make_cleanup (xfree, name); - ui_out_field_string (uiout, "name", name); - ui_out_field_string (uiout, "initial", plongest (tsv->initial_value)); - - if (tsv->value_known) - c = plongest (tsv->value); - else if (ui_out_is_mi_like_p (uiout)) - /* For MI, we prefer not to use magic string constants, but rather - omit the field completely. The difference between unknown and - undefined does not seem important enough to represent. */ - c = NULL; - else if (current_trace_status ()->running || traceframe_number >= 0) - /* The value is/was defined, but we don't have it. */ - c = ""; - else - /* It is not meaningful to ask about the value. */ - c = ""; - if (c) - ui_out_field_string (uiout, "current", c); - ui_out_text (uiout, "\n"); - - do_cleanups (back_to2); - } + for (const trace_state_variable &tsv : tvariables) + { + const char *c; + + ui_out_emit_tuple tuple_emitter (uiout, "variable"); + + uiout->field_string ("name", std::string ("$") + tsv.name); + uiout->field_string ("initial", plongest (tsv.initial_value)); + + ui_file_style style; + if (tsv.value_known) + c = plongest (tsv.value); + else if (uiout->is_mi_like_p ()) + /* For MI, we prefer not to use magic string constants, but rather + omit the field completely. The difference between unknown and + undefined does not seem important enough to represent. */ + c = NULL; + else if (current_trace_status ()->running || traceframe_number >= 0) + { + /* The value is/was defined, but we don't have it. */ + c = ""; + style = metadata_style.style (); + } + else + { + /* It is not meaningful to ask about the value. */ + c = ""; + style = metadata_style.style (); + } + if (c) + uiout->field_string ("current", c, style); + uiout->text ("\n"); + } + } - do_cleanups (back_to); + if (tvariables.empty ()) + uiout->text (_("No trace state variables.\n")); } /* List all the trace state variables. */ static void -tvariables_info (char *args, int from_tty) +info_tvariables_command (const char *args, int from_tty) { tvariables_info_1 (); } @@ -556,14 +478,11 @@ tvariables_info (char *args, int from_tty) void save_trace_state_variables (struct ui_file *fp) { - struct trace_state_variable *tsv; - int ix; - - for (ix = 0; VEC_iterate (tsv_s, tvariables, ix, tsv); ++ix) + for (const trace_state_variable &tsv : tvariables) { - fprintf_unfiltered (fp, "tvariable $%s", tsv->name); - if (tsv->initial_value) - fprintf_unfiltered (fp, " = %s", plongest (tsv->initial_value)); + fprintf_unfiltered (fp, "tvariable $%s", tsv.name.c_str ()); + if (tsv.initial_value) + fprintf_unfiltered (fp, " = %s", plongest (tsv.initial_value)); fprintf_unfiltered (fp, "\n"); } } @@ -580,25 +499,25 @@ save_trace_state_variables (struct ui_file *fp) which is always an error. */ static void -end_actions_pseudocommand (char *args, int from_tty) +end_actions_pseudocommand (const char *args, int from_tty) { error (_("This command cannot be used at the top level.")); } static void -while_stepping_pseudocommand (char *args, int from_tty) +while_stepping_pseudocommand (const char *args, int from_tty) { error (_("This command can only be used in a tracepoint actions list.")); } static void -collect_pseudocommand (char *args, int from_tty) +collect_pseudocommand (const char *args, int from_tty) { error (_("This command can only be used in a tracepoint actions list.")); } static void -teval_pseudocommand (char *args, int from_tty) +teval_pseudocommand (const char *args, int from_tty) { error (_("This command can only be used in a tracepoint actions list.")); } @@ -640,30 +559,31 @@ decode_agent_options (const char *exp, int *trace_string) else error (_("Undefined collection format \"%c\"."), *exp); - exp = skip_spaces_const (exp); + exp = skip_spaces (exp); return exp; } /* Enter a list of actions for a tracepoint. */ static void -trace_actions_command (char *args, int from_tty) +actions_command (const char *args, int from_tty) { struct tracepoint *t; - struct command_line *l; t = get_tracepoint_by_number (&args, NULL); if (t) { - char *tmpbuf = - xstrprintf ("Enter actions for tracepoint %d, one per line.", - t->base.number); - struct cleanup *cleanups = make_cleanup (xfree, tmpbuf); - - l = read_command_lines (tmpbuf, from_tty, 1, - check_tracepoint_command, t); - do_cleanups (cleanups); - breakpoint_set_commands (&t->base, l); + std::string tmpbuf = + string_printf ("Enter actions for tracepoint %d, one per line.", + t->number); + + counted_command_line l = read_command_lines (tmpbuf.c_str (), + from_tty, 1, + [=] (const char *line) + { + validate_actionline (line, t); + }); + breakpoint_set_commands (t, std::move (l)); } /* else just return */ } @@ -695,24 +615,34 @@ report_agent_reqs_errors (struct agent_expr *aexpr) error (_("Expression is too complicated.")); } +/* Call ax_reqs on AEXPR and raise an error if something is wrong. */ + +static void +finalize_tracepoint_aexpr (struct agent_expr *aexpr) +{ + ax_reqs (aexpr); + + if (aexpr->len > MAX_AGENT_EXPR_LEN) + error (_("Expression is too complicated.")); + + report_agent_reqs_errors (aexpr); +} + /* worker function */ void validate_actionline (const char *line, struct breakpoint *b) { struct cmd_list_element *c; - struct expression *exp = NULL; - struct cleanup *old_chain = NULL; const char *tmp_p; const char *p; struct bp_location *loc; - struct agent_expr *aexpr; struct tracepoint *t = (struct tracepoint *) b; /* If EOF is typed, *line is NULL. */ if (line == NULL) return; - p = skip_spaces_const (line); + p = skip_spaces (line); /* Symbol lookup etc. */ if (*p == '\0') /* empty line: just prompt for another line. */ @@ -735,7 +665,7 @@ validate_actionline (const char *line, struct breakpoint *b) do { /* Repeat over a comma-separated list. */ QUIT; /* Allow user to bail out with ^C. */ - p = skip_spaces_const (p); + p = skip_spaces (p); if (*p == '$') /* Look for special pseudo-symbols. */ { @@ -751,12 +681,11 @@ validate_actionline (const char *line, struct breakpoint *b) /* else fall thru, treat p as an expression and parse it! */ } tmp_p = p; - for (loc = t->base.loc; loc; loc = loc->next) + for (loc = t->loc; loc; loc = loc->next) { p = tmp_p; - exp = parse_exp_1 (&p, loc->address, - block_for_pc (loc->address), 1); - old_chain = make_cleanup (free_current_contents, &exp); + expression_up exp = parse_exp_1 (&p, loc->address, + block_for_pc (loc->address), 1); if (exp->elts[0].opcode == OP_VAR_VALUE) { @@ -764,7 +693,7 @@ validate_actionline (const char *line, struct breakpoint *b) { error (_("constant `%s' (value %s) " "will not be collected."), - SYMBOL_PRINT_NAME (exp->elts[2].symbol), + exp->elts[2].symbol->print_name (), plongest (SYMBOL_VALUE (exp->elts[2].symbol))); } else if (SYMBOL_CLASS (exp->elts[2].symbol) @@ -772,24 +701,18 @@ validate_actionline (const char *line, struct breakpoint *b) { error (_("`%s' is optimized away " "and cannot be collected."), - SYMBOL_PRINT_NAME (exp->elts[2].symbol)); + exp->elts[2].symbol->print_name ()); } } /* We have something to collect, make sure that the expr to bytecode translator can handle it and that it's not too long. */ - aexpr = gen_trace_for_expr (loc->address, exp, trace_string); - make_cleanup_free_agent_expr (aexpr); - - if (aexpr->len > MAX_AGENT_EXPR_LEN) - error (_("Expression is too complicated.")); - - ax_reqs (aexpr); - - report_agent_reqs_errors (aexpr); + agent_expr_up aexpr = gen_trace_for_expr (loc->address, + exp.get (), + trace_string); - do_cleanups (old_chain); + finalize_tracepoint_aexpr (aexpr.get ()); } } while (p && *p++ == ','); @@ -800,31 +723,23 @@ validate_actionline (const char *line, struct breakpoint *b) do { /* Repeat over a comma-separated list. */ QUIT; /* Allow user to bail out with ^C. */ - p = skip_spaces_const (p); + p = skip_spaces (p); tmp_p = p; - for (loc = t->base.loc; loc; loc = loc->next) + for (loc = t->loc; loc; loc = loc->next) { p = tmp_p; /* Only expressions are allowed for this action. */ - exp = parse_exp_1 (&p, loc->address, - block_for_pc (loc->address), 1); - old_chain = make_cleanup (free_current_contents, &exp); + expression_up exp = parse_exp_1 (&p, loc->address, + block_for_pc (loc->address), 1); /* We have something to evaluate, make sure that the expr to bytecode translator can handle it and that it's not too long. */ - aexpr = gen_eval_for_expr (loc->address, exp); - make_cleanup_free_agent_expr (aexpr); + agent_expr_up aexpr = gen_eval_for_expr (loc->address, exp.get ()); - if (aexpr->len > MAX_AGENT_EXPR_LEN) - error (_("Expression is too complicated.")); - - ax_reqs (aexpr); - report_agent_reqs_errors (aexpr); - - do_cleanups (old_chain); + finalize_tracepoint_aexpr (aexpr.get ()); } } while (p && *p++ == ','); @@ -834,7 +749,7 @@ validate_actionline (const char *line, struct breakpoint *b) { char *endp; - p = skip_spaces_const (p); + p = skip_spaces (p); t->step_count = strtol (p, &endp, 0); if (endp == p || t->step_count == 0) error (_("while-stepping step count `%s' is malformed."), line); @@ -854,117 +769,152 @@ enum { /* MEMRANGE functions: */ -static int memrange_cmp (const void *, const void *); +/* Compare memranges for std::sort. */ -/* Compare memranges for qsort. */ -static int -memrange_cmp (const void *va, const void *vb) +static bool +memrange_comp (const memrange &a, const memrange &b) { - const struct memrange *a = (const struct memrange *) va; - const struct memrange *b = (const struct memrange *) vb; - - if (a->type < b->type) - return -1; - if (a->type > b->type) - return 1; - if (a->type == memrange_absolute) - { - if ((bfd_vma) a->start < (bfd_vma) b->start) - return -1; - if ((bfd_vma) a->start > (bfd_vma) b->start) - return 1; - } - else + if (a.type == b.type) { - if (a->start < b->start) - return -1; - if (a->start > b->start) - return 1; + if (a.type == memrange_absolute) + return (bfd_vma) a.start < (bfd_vma) b.start; + else + return a.start < b.start; } - return 0; + + return a.type < b.type; } -/* Sort the memrange list using qsort, and merge adjacent memranges. */ +/* Sort the memrange list using std::sort, and merge adjacent memranges. */ + static void -memrange_sortmerge (struct collection_list *memranges) +memrange_sortmerge (std::vector &memranges) { - int a, b; - - qsort (memranges->list, memranges->next_memrange, - sizeof (struct memrange), memrange_cmp); - if (memranges->next_memrange > 0) + if (!memranges.empty ()) { - for (a = 0, b = 1; b < memranges->next_memrange; b++) + int a, b; + + std::sort (memranges.begin (), memranges.end (), memrange_comp); + + for (a = 0, b = 1; b < memranges.size (); b++) { /* If memrange b overlaps or is adjacent to memrange a, merge them. */ - if (memranges->list[a].type == memranges->list[b].type - && memranges->list[b].start <= memranges->list[a].end) + if (memranges[a].type == memranges[b].type + && memranges[b].start <= memranges[a].end) { - if (memranges->list[b].end > memranges->list[a].end) - memranges->list[a].end = memranges->list[b].end; + if (memranges[b].end > memranges[a].end) + memranges[a].end = memranges[b].end; continue; /* next b, same a */ } a++; /* next a */ if (a != b) - memcpy (&memranges->list[a], &memranges->list[b], - sizeof (struct memrange)); + memranges[a] = memranges[b]; } - memranges->next_memrange = a + 1; + memranges.resize (a + 1); } } -/* Add a register to a collection list. */ -static void -add_register (struct collection_list *collection, unsigned int regno) +/* Add remote register number REGNO to the collection list mask. */ + +void +collection_list::add_remote_register (unsigned int regno) { if (info_verbose) printf_filtered ("collect register %d\n", regno); - if (regno >= (8 * sizeof (collection->regs_mask))) - error (_("Internal: register number %d too large for tracepoint"), - regno); - collection->regs_mask[regno / 8] |= 1 << (regno % 8); + + m_regs_mask.at (regno / 8) |= 1 << (regno % 8); } -/* Add a memrange to a collection list. */ -static void -add_memrange (struct collection_list *memranges, - int type, bfd_signed_vma base, - unsigned long len) +/* Add all the registers from the mask in AEXPR to the mask in the + collection list. Registers in the AEXPR mask are already remote + register numbers. */ + +void +collection_list::add_ax_registers (struct agent_expr *aexpr) { - if (info_verbose) + if (aexpr->reg_mask_len > 0) + { + for (int ndx1 = 0; ndx1 < aexpr->reg_mask_len; ndx1++) + { + QUIT; /* Allow user to bail out with ^C. */ + if (aexpr->reg_mask[ndx1] != 0) + { + /* Assume chars have 8 bits. */ + for (int ndx2 = 0; ndx2 < 8; ndx2++) + if (aexpr->reg_mask[ndx1] & (1 << ndx2)) + /* It's used -- record it. */ + add_remote_register (ndx1 * 8 + ndx2); + } + } + } +} + +/* If REGNO is raw, add its corresponding remote register number to + the mask. If REGNO is a pseudo-register, figure out the necessary + registers using a temporary agent expression, and add it to the + list if it needs more than just a mask. */ + +void +collection_list::add_local_register (struct gdbarch *gdbarch, + unsigned int regno, + CORE_ADDR scope) +{ + if (regno < gdbarch_num_regs (gdbarch)) + { + int remote_regno = gdbarch_remote_register_number (gdbarch, regno); + + if (remote_regno < 0) + error (_("Can't collect register %d"), regno); + + add_remote_register (remote_regno); + } + else { - printf_filtered ("(%d,", type); - printf_vma (base); - printf_filtered (",%ld)\n", len); + agent_expr_up aexpr (new agent_expr (gdbarch, scope)); + + ax_reg_mask (aexpr.get (), regno); + + finalize_tracepoint_aexpr (aexpr.get ()); + + add_ax_registers (aexpr.get ()); + + /* Usually ax_reg_mask for a pseudo-regiser only sets the + corresponding raw registers in the ax mask, but if this isn't + the case add the expression that is generated to the + collection list. */ + if (aexpr->len > 0) + add_aexpr (std::move (aexpr)); } +} + +/* Add a memrange to a collection list. */ + +void +collection_list::add_memrange (struct gdbarch *gdbarch, + int type, bfd_signed_vma base, + unsigned long len, CORE_ADDR scope) +{ + if (info_verbose) + printf_filtered ("(%d,%s,%ld)\n", type, paddress (gdbarch, base), len); /* type: memrange_absolute == memory, other n == basereg */ - memranges->list[memranges->next_memrange].type = type; /* base: addr if memory, offset if reg relative. */ - memranges->list[memranges->next_memrange].start = base; /* len: we actually save end (base + len) for convenience */ - memranges->list[memranges->next_memrange].end = base + len; - memranges->next_memrange++; - if (memranges->next_memrange >= memranges->listsize) - { - memranges->listsize *= 2; - memranges->list = (struct memrange *) xrealloc (memranges->list, - memranges->listsize); - } + m_memranges.emplace_back (type, base, base + len); if (type != memrange_absolute) /* Better collect the base register! */ - add_register (memranges, type); + add_local_register (gdbarch, type, scope); } /* Add a symbol to a collection list. */ -static void -collect_symbol (struct collection_list *collect, - struct symbol *sym, - struct gdbarch *gdbarch, - long frame_regno, long frame_offset, - CORE_ADDR scope, - int trace_string) + +void +collection_list::collect_symbol (struct symbol *sym, + struct gdbarch *gdbarch, + long frame_regno, long frame_offset, + CORE_ADDR scope, + int trace_string) { unsigned long len; unsigned int reg; @@ -976,83 +926,74 @@ collect_symbol (struct collection_list *collect, { default: printf_filtered ("%s: don't know symbol class %d\n", - SYMBOL_PRINT_NAME (sym), - SYMBOL_CLASS (sym)); + sym->print_name (), SYMBOL_CLASS (sym)); break; case LOC_CONST: printf_filtered ("constant %s (value %s) will not be collected.\n", - SYMBOL_PRINT_NAME (sym), plongest (SYMBOL_VALUE (sym))); + sym->print_name (), plongest (SYMBOL_VALUE (sym))); break; case LOC_STATIC: offset = SYMBOL_VALUE_ADDRESS (sym); if (info_verbose) { - char tmp[40]; - - sprintf_vma (tmp, offset); printf_filtered ("LOC_STATIC %s: collect %ld bytes at %s.\n", - SYMBOL_PRINT_NAME (sym), len, - tmp /* address */); + sym->print_name (), len, + paddress (gdbarch, offset)); } /* A struct may be a C++ class with static fields, go to general expression handling. */ if (TYPE_CODE (SYMBOL_TYPE (sym)) == TYPE_CODE_STRUCT) treat_as_expr = 1; else - add_memrange (collect, memrange_absolute, offset, len); + add_memrange (gdbarch, memrange_absolute, offset, len, scope); break; case LOC_REGISTER: reg = SYMBOL_REGISTER_OPS (sym)->register_number (sym, gdbarch); if (info_verbose) - printf_filtered ("LOC_REG[parm] %s: ", - SYMBOL_PRINT_NAME (sym)); - add_register (collect, reg); + printf_filtered ("LOC_REG[parm] %s: ", sym->print_name ()); + add_local_register (gdbarch, reg, scope); /* Check for doubles stored in two registers. */ /* FIXME: how about larger types stored in 3 or more regs? */ if (TYPE_CODE (SYMBOL_TYPE (sym)) == TYPE_CODE_FLT && len > register_size (gdbarch, reg)) - add_register (collect, reg + 1); + add_local_register (gdbarch, reg + 1, scope); break; case LOC_REF_ARG: printf_filtered ("Sorry, don't know how to do LOC_REF_ARG yet.\n"); - printf_filtered (" (will not collect %s)\n", - SYMBOL_PRINT_NAME (sym)); + printf_filtered (" (will not collect %s)\n", sym->print_name ()); break; case LOC_ARG: reg = frame_regno; offset = frame_offset + SYMBOL_VALUE (sym); if (info_verbose) { - printf_filtered ("LOC_LOCAL %s: Collect %ld bytes at offset ", - SYMBOL_PRINT_NAME (sym), len); - printf_vma (offset); - printf_filtered (" from frame ptr reg %d\n", reg); + printf_filtered ("LOC_LOCAL %s: Collect %ld bytes at offset %s" + " from frame ptr reg %d\n", sym->print_name (), len, + paddress (gdbarch, offset), reg); } - add_memrange (collect, reg, offset, len); + add_memrange (gdbarch, reg, offset, len, scope); break; case LOC_REGPARM_ADDR: reg = SYMBOL_VALUE (sym); offset = 0; if (info_verbose) { - printf_filtered ("LOC_REGPARM_ADDR %s: Collect %ld bytes at offset ", - SYMBOL_PRINT_NAME (sym), len); - printf_vma (offset); - printf_filtered (" from reg %d\n", reg); + printf_filtered ("LOC_REGPARM_ADDR %s: Collect %ld bytes at offset %s" + " from reg %d\n", sym->print_name (), len, + paddress (gdbarch, offset), reg); } - add_memrange (collect, reg, offset, len); + add_memrange (gdbarch, reg, offset, len, scope); break; case LOC_LOCAL: reg = frame_regno; offset = frame_offset + SYMBOL_VALUE (sym); if (info_verbose) { - printf_filtered ("LOC_LOCAL %s: Collect %ld bytes at offset ", - SYMBOL_PRINT_NAME (sym), len); - printf_vma (offset); - printf_filtered (" from frame ptr reg %d\n", reg); + printf_filtered ("LOC_LOCAL %s: Collect %ld bytes at offset %s" + " from frame ptr reg %d\n", sym->print_name (), len, + paddress (gdbarch, offset), reg); } - add_memrange (collect, reg, offset, len); + add_memrange (gdbarch, reg, offset, len, scope); break; case LOC_UNRESOLVED: @@ -1061,7 +1002,7 @@ collect_symbol (struct collection_list *collect, case LOC_OPTIMIZED_OUT: printf_filtered ("%s has been optimized out of existence.\n", - SYMBOL_PRINT_NAME (sym)); + sym->print_name ()); break; case LOC_COMPUTED: @@ -1072,10 +1013,8 @@ collect_symbol (struct collection_list *collect, /* Expressions are the most general case. */ if (treat_as_expr) { - struct agent_expr *aexpr; - struct cleanup *old_chain1 = NULL; - - aexpr = gen_trace_for_var (scope, gdbarch, sym, trace_string); + agent_expr_up aexpr = gen_trace_for_var (scope, gdbarch, + sym, trace_string); /* It can happen that the symbol is recorded as a computed location, but it's been optimized away and doesn't actually @@ -1083,37 +1022,16 @@ collect_symbol (struct collection_list *collect, if (!aexpr) { printf_filtered ("%s has been optimized out of existence.\n", - SYMBOL_PRINT_NAME (sym)); + sym->print_name ()); return; } - old_chain1 = make_cleanup_free_agent_expr (aexpr); - - ax_reqs (aexpr); - - report_agent_reqs_errors (aexpr); - - discard_cleanups (old_chain1); - add_aexpr (collect, aexpr); + finalize_tracepoint_aexpr (aexpr.get ()); /* Take care of the registers. */ - if (aexpr->reg_mask_len > 0) - { - int ndx1, ndx2; + add_ax_registers (aexpr.get ()); - for (ndx1 = 0; ndx1 < aexpr->reg_mask_len; ndx1++) - { - QUIT; /* Allow user to bail out with ^C. */ - if (aexpr->reg_mask[ndx1] != 0) - { - /* Assume chars have 8 bits. */ - for (ndx2 = 0; ndx2 < 8; ndx2++) - if (aexpr->reg_mask[ndx1] & (1 << ndx2)) - /* It's used -- record it. */ - add_register (collect, ndx1 * 8 + ndx2); - } - } - } + add_aexpr (std::move (aexpr)); } } @@ -1140,25 +1058,30 @@ do_collect_symbol (const char *print_name, { struct add_local_symbols_data *p = (struct add_local_symbols_data *) cb_data; - collect_symbol (p->collect, sym, p->gdbarch, p->frame_regno, - p->frame_offset, p->pc, p->trace_string); + p->collect->collect_symbol (sym, p->gdbarch, p->frame_regno, + p->frame_offset, p->pc, p->trace_string); p->count++; - VEC_safe_push (char_ptr, p->collect->wholly_collected, - xstrdup (print_name)); + p->collect->add_wholly_collected (print_name); +} + +void +collection_list::add_wholly_collected (const char *print_name) +{ + m_wholly_collected.push_back (print_name); } /* Add all locals (or args) symbols to collection list. */ -static void -add_local_symbols (struct collection_list *collect, - struct gdbarch *gdbarch, CORE_ADDR pc, - long frame_regno, long frame_offset, int type, - int trace_string) + +void +collection_list::add_local_symbols (struct gdbarch *gdbarch, CORE_ADDR pc, + long frame_regno, long frame_offset, int type, + int trace_string) { const struct block *block; struct add_local_symbols_data cb_data; - cb_data.collect = collect; + cb_data.collect = this; cb_data.gdbarch = gdbarch; cb_data.pc = pc; cb_data.frame_regno = frame_regno; @@ -1196,197 +1119,169 @@ add_local_symbols (struct collection_list *collect, } } -static void -add_static_trace_data (struct collection_list *collection) +void +collection_list::add_static_trace_data () { if (info_verbose) printf_filtered ("collect static trace data\n"); - collection->strace_data = 1; + m_strace_data = true; } -/* worker function */ -static void -clear_collection_list (struct collection_list *list) +collection_list::collection_list () + : m_strace_data (false) { - int ndx; - - list->next_memrange = 0; - for (ndx = 0; ndx < list->next_aexpr_elt; ndx++) + int max_remote_regno = 0; + for (int i = 0; i < gdbarch_num_regs (target_gdbarch ()); i++) { - free_agent_expr (list->aexpr_list[ndx]); - list->aexpr_list[ndx] = NULL; - } - list->next_aexpr_elt = 0; - memset (list->regs_mask, 0, sizeof (list->regs_mask)); - list->strace_data = 0; - - xfree (list->aexpr_list); - xfree (list->list); - - VEC_free (char_ptr, list->wholly_collected); - VEC_free (char_ptr, list->computed); -} + int remote_regno = (gdbarch_remote_register_number + (target_gdbarch (), i)); -/* A cleanup wrapper for function clear_collection_list. */ + if (remote_regno >= 0 && remote_regno > max_remote_regno) + max_remote_regno = remote_regno; + } -static void -do_clear_collection_list (void *list) -{ - struct collection_list *l = (struct collection_list *) list; + m_regs_mask.resize ((max_remote_regno / 8) + 1); - clear_collection_list (l); + m_memranges.reserve (128); + m_aexprs.reserve (128); } -/* Initialize collection_list CLIST. */ +/* Reduce a collection list to string form (for gdb protocol). */ -static void -init_collection_list (struct collection_list *clist) +std::vector +collection_list::stringify () { - memset (clist, 0, sizeof *clist); + gdb::char_vector temp_buf (2048); - clist->listsize = 128; - clist->list = XCNEWVEC (struct memrange, clist->listsize); - - clist->aexpr_listsize = 128; - clist->aexpr_list = XCNEWVEC (struct agent_expr *, clist->aexpr_listsize); -} - -/* Reduce a collection list to string form (for gdb protocol). */ -static char ** -stringify_collection_list (struct collection_list *list) -{ - char temp_buf[2048]; - char tmp2[40]; int count; - int ndx = 0; - char *(*str_list)[]; char *end; long i; + std::vector str_list; - count = 1 + 1 + list->next_memrange + list->next_aexpr_elt + 1; - str_list = (char *(*)[]) xmalloc (count * sizeof (char *)); - - if (list->strace_data) + if (m_strace_data) { if (info_verbose) printf_filtered ("\nCollecting static trace data\n"); - end = temp_buf; + end = temp_buf.data (); *end++ = 'L'; - (*str_list)[ndx] = savestring (temp_buf, end - temp_buf); - ndx++; + str_list.emplace_back (temp_buf.data (), end - temp_buf.data ()); } - for (i = sizeof (list->regs_mask) - 1; i > 0; i--) - if (list->regs_mask[i] != 0) /* Skip leading zeroes in regs_mask. */ + for (i = m_regs_mask.size () - 1; i > 0; i--) + if (m_regs_mask[i] != 0) /* Skip leading zeroes in regs_mask. */ break; - if (list->regs_mask[i] != 0) /* Prepare to send regs_mask to the stub. */ + if (m_regs_mask[i] != 0) /* Prepare to send regs_mask to the stub. */ { if (info_verbose) printf_filtered ("\nCollecting registers (mask): 0x"); - end = temp_buf; + + /* One char for 'R', one for the null terminator and two per + mask byte. */ + std::size_t new_size = (i + 1) * 2 + 2; + if (new_size > temp_buf.size ()) + temp_buf.resize (new_size); + + end = temp_buf.data (); *end++ = 'R'; for (; i >= 0; i--) { QUIT; /* Allow user to bail out with ^C. */ if (info_verbose) - printf_filtered ("%02X", list->regs_mask[i]); - sprintf (end, "%02X", list->regs_mask[i]); - end += 2; + printf_filtered ("%02X", m_regs_mask[i]); + + end = pack_hex_byte (end, m_regs_mask[i]); } - (*str_list)[ndx] = xstrdup (temp_buf); - ndx++; + *end = '\0'; + + str_list.emplace_back (temp_buf.data ()); } if (info_verbose) printf_filtered ("\n"); - if (list->next_memrange > 0 && info_verbose) + if (!m_memranges.empty () && info_verbose) printf_filtered ("Collecting memranges: \n"); - for (i = 0, count = 0, end = temp_buf; i < list->next_memrange; i++) + for (i = 0, count = 0, end = temp_buf.data (); + i < m_memranges.size (); i++) { QUIT; /* Allow user to bail out with ^C. */ - sprintf_vma (tmp2, list->list[i].start); if (info_verbose) { printf_filtered ("(%d, %s, %ld)\n", - list->list[i].type, - tmp2, - (long) (list->list[i].end - list->list[i].start)); + m_memranges[i].type, + paddress (target_gdbarch (), + m_memranges[i].start), + (long) (m_memranges[i].end + - m_memranges[i].start)); } if (count + 27 > MAX_AGENT_EXPR_LEN) { - (*str_list)[ndx] = savestring (temp_buf, count); - ndx++; + str_list.emplace_back (temp_buf.data (), count); count = 0; - end = temp_buf; + end = temp_buf.data (); } { - bfd_signed_vma length = list->list[i].end - list->list[i].start; + bfd_signed_vma length + = m_memranges[i].end - m_memranges[i].start; /* The "%X" conversion specifier expects an unsigned argument, so passing -1 (memrange_absolute) to it directly gives you "FFFFFFFF" (or more, depending on sizeof (unsigned)). Special-case it. */ - if (list->list[i].type == memrange_absolute) - sprintf (end, "M-1,%s,%lX", tmp2, (long) length); + if (m_memranges[i].type == memrange_absolute) + sprintf (end, "M-1,%s,%lX", phex_nz (m_memranges[i].start, 0), + (long) length); else - sprintf (end, "M%X,%s,%lX", list->list[i].type, tmp2, (long) length); + sprintf (end, "M%X,%s,%lX", m_memranges[i].type, + phex_nz (m_memranges[i].start, 0), (long) length); } count += strlen (end); - end = temp_buf + count; + end = temp_buf.data () + count; } - for (i = 0; i < list->next_aexpr_elt; i++) + for (i = 0; i < m_aexprs.size (); i++) { QUIT; /* Allow user to bail out with ^C. */ - if ((count + 10 + 2 * list->aexpr_list[i]->len) > MAX_AGENT_EXPR_LEN) + if ((count + 10 + 2 * m_aexprs[i]->len) > MAX_AGENT_EXPR_LEN) { - (*str_list)[ndx] = savestring (temp_buf, count); - ndx++; + str_list.emplace_back (temp_buf.data (), count); count = 0; - end = temp_buf; + end = temp_buf.data (); } - sprintf (end, "X%08X,", list->aexpr_list[i]->len); + sprintf (end, "X%08X,", m_aexprs[i]->len); end += 10; /* 'X' + 8 hex digits + ',' */ count += 10; - end = mem2hex (list->aexpr_list[i]->buf, - end, list->aexpr_list[i]->len); - count += 2 * list->aexpr_list[i]->len; + end = mem2hex (m_aexprs[i]->buf, end, m_aexprs[i]->len); + count += 2 * m_aexprs[i]->len; } if (count != 0) { - (*str_list)[ndx] = savestring (temp_buf, count); - ndx++; + str_list.emplace_back (temp_buf.data (), count); count = 0; - end = temp_buf; + end = temp_buf.data (); } - (*str_list)[ndx] = NULL; - if (ndx == 0) - { - xfree (str_list); - return NULL; - } - else - return *str_list; + return str_list; } /* Add the printed expression EXP to *LIST. */ -static void -append_exp (struct expression *exp, VEC(char_ptr) **list) +void +collection_list::append_exp (struct expression *exp) { - struct ui_file *tmp_stream = mem_fileopen (); - char *text; + string_file tmp_stream; - print_expression (exp, tmp_stream); + print_expression (exp, &tmp_stream); - text = ui_file_xstrdup (tmp_stream, NULL); + m_computed.push_back (std::move (tmp_stream.string ())); +} - VEC_safe_push (char_ptr, *list, text); - ui_file_delete (tmp_stream); +void +collection_list::finish () +{ + memrange_sortmerge (m_memranges); } static void @@ -1398,17 +1293,15 @@ encode_actions_1 (struct command_line *action, struct collection_list *stepping_list) { const char *action_exp; - struct expression *exp = NULL; int i; struct value *tempval; struct cmd_list_element *cmd; - struct agent_expr *aexpr; for (; action; action = action->next) { QUIT; /* Allow user to bail out with ^C. */ action_exp = action->line; - action_exp = skip_spaces_const (action_exp); + action_exp = skip_spaces (action_exp); cmd = lookup_cmd (&action_exp, cmdlist, "", -1, 1); if (cmd == 0) @@ -1424,88 +1317,71 @@ encode_actions_1 (struct command_line *action, do { /* Repeat over a comma-separated list. */ QUIT; /* Allow user to bail out with ^C. */ - action_exp = skip_spaces_const (action_exp); + action_exp = skip_spaces (action_exp); if (0 == strncasecmp ("$reg", action_exp, 4)) { - for (i = 0; i < gdbarch_num_regs (tloc->gdbarch); i++) - add_register (collect, i); + for (i = 0; i < gdbarch_num_regs (target_gdbarch ()); + i++) + { + int remote_regno = (gdbarch_remote_register_number + (target_gdbarch (), i)); + + /* Ignore arch regnos without a corresponding + remote regno. This can happen for regnos not + in the tdesc. */ + if (remote_regno >= 0) + collect->add_remote_register (remote_regno); + } action_exp = strchr (action_exp, ','); /* more? */ } else if (0 == strncasecmp ("$arg", action_exp, 4)) { - add_local_symbols (collect, - tloc->gdbarch, - tloc->address, - frame_reg, - frame_offset, - 'A', - trace_string); + collect->add_local_symbols (target_gdbarch (), + tloc->address, + frame_reg, + frame_offset, + 'A', + trace_string); action_exp = strchr (action_exp, ','); /* more? */ } else if (0 == strncasecmp ("$loc", action_exp, 4)) { - add_local_symbols (collect, - tloc->gdbarch, - tloc->address, - frame_reg, - frame_offset, - 'L', - trace_string); + collect->add_local_symbols (target_gdbarch (), + tloc->address, + frame_reg, + frame_offset, + 'L', + trace_string); action_exp = strchr (action_exp, ','); /* more? */ } else if (0 == strncasecmp ("$_ret", action_exp, 5)) { - struct cleanup *old_chain1 = NULL; - - aexpr = gen_trace_for_return_address (tloc->address, - tloc->gdbarch, - trace_string); - - old_chain1 = make_cleanup_free_agent_expr (aexpr); - - ax_reqs (aexpr); - report_agent_reqs_errors (aexpr); + agent_expr_up aexpr + = gen_trace_for_return_address (tloc->address, + target_gdbarch (), + trace_string); - discard_cleanups (old_chain1); - add_aexpr (collect, aexpr); + finalize_tracepoint_aexpr (aexpr.get ()); /* take care of the registers */ - if (aexpr->reg_mask_len > 0) - { - int ndx1, ndx2; - - for (ndx1 = 0; ndx1 < aexpr->reg_mask_len; ndx1++) - { - QUIT; /* allow user to bail out with ^C */ - if (aexpr->reg_mask[ndx1] != 0) - { - /* assume chars have 8 bits */ - for (ndx2 = 0; ndx2 < 8; ndx2++) - if (aexpr->reg_mask[ndx1] & (1 << ndx2)) - /* it's used -- record it */ - add_register (collect, - ndx1 * 8 + ndx2); - } - } - } + collect->add_ax_registers (aexpr.get ()); + collect->add_aexpr (std::move (aexpr)); action_exp = strchr (action_exp, ','); /* more? */ } else if (0 == strncasecmp ("$_sdata", action_exp, 7)) { - add_static_trace_data (collect); + collect->add_static_trace_data (); action_exp = strchr (action_exp, ','); /* more? */ } else { unsigned long addr; - struct cleanup *old_chain = NULL; - struct cleanup *old_chain1 = NULL; - exp = parse_exp_1 (&action_exp, tloc->address, - block_for_pc (tloc->address), 1); - old_chain = make_cleanup (free_current_contents, &exp); + expression_up exp = parse_exp_1 (&action_exp, tloc->address, + block_for_pc (tloc->address), + 1); switch (exp->elts[0].opcode) { @@ -1513,7 +1389,7 @@ encode_actions_1 (struct command_line *action, { const char *name = &exp->elts[2].string; - i = user_reg_map_name_to_regnum (tloc->gdbarch, + i = user_reg_map_name_to_regnum (target_gdbarch (), name, strlen (name)); if (i == -1) internal_error (__FILE__, __LINE__, @@ -1521,77 +1397,53 @@ encode_actions_1 (struct command_line *action, name); if (info_verbose) printf_filtered ("OP_REGISTER: "); - add_register (collect, i); + collect->add_local_register (target_gdbarch (), + i, tloc->address); break; } case UNOP_MEMVAL: /* Safe because we know it's a simple expression. */ - tempval = evaluate_expression (exp); + tempval = evaluate_expression (exp.get ()); addr = value_address (tempval); /* Initialize the TYPE_LENGTH if it is a typedef. */ check_typedef (exp->elts[1].type); - add_memrange (collect, memrange_absolute, addr, - TYPE_LENGTH (exp->elts[1].type)); - append_exp (exp, &collect->computed); + collect->add_memrange (target_gdbarch (), + memrange_absolute, addr, + TYPE_LENGTH (exp->elts[1].type), + tloc->address); + collect->append_exp (exp.get ()); break; case OP_VAR_VALUE: { struct symbol *sym = exp->elts[2].symbol; - char_ptr name = (char_ptr) SYMBOL_NATURAL_NAME (sym); - - collect_symbol (collect, - exp->elts[2].symbol, - tloc->gdbarch, - frame_reg, - frame_offset, - tloc->address, - trace_string); - VEC_safe_push (char_ptr, - collect->wholly_collected, - name); + const char *name = sym->natural_name (); + + collect->collect_symbol (exp->elts[2].symbol, + target_gdbarch (), + frame_reg, + frame_offset, + tloc->address, + trace_string); + collect->add_wholly_collected (name); } break; default: /* Full-fledged expression. */ - aexpr = gen_trace_for_expr (tloc->address, exp, - trace_string); - - old_chain1 = make_cleanup_free_agent_expr (aexpr); - - ax_reqs (aexpr); + agent_expr_up aexpr = gen_trace_for_expr (tloc->address, + exp.get (), + trace_string); - report_agent_reqs_errors (aexpr); - - discard_cleanups (old_chain1); - add_aexpr (collect, aexpr); + finalize_tracepoint_aexpr (aexpr.get ()); /* Take care of the registers. */ - if (aexpr->reg_mask_len > 0) - { - int ndx1; - int ndx2; - - for (ndx1 = 0; ndx1 < aexpr->reg_mask_len; ndx1++) - { - QUIT; /* Allow user to bail out with ^C. */ - if (aexpr->reg_mask[ndx1] != 0) - { - /* Assume chars have 8 bits. */ - for (ndx2 = 0; ndx2 < 8; ndx2++) - if (aexpr->reg_mask[ndx1] & (1 << ndx2)) - /* It's used -- record it. */ - add_register (collect, - ndx1 * 8 + ndx2); - } - } - } + collect->add_ax_registers (aexpr.get ()); - append_exp (exp, &collect->computed); + collect->add_aexpr (std::move (aexpr)); + collect->append_exp (exp.get ()); break; } /* switch */ - do_cleanups (old_chain); } /* do */ } while (action_exp && *action_exp++ == ','); @@ -1601,28 +1453,21 @@ encode_actions_1 (struct command_line *action, do { /* Repeat over a comma-separated list. */ QUIT; /* Allow user to bail out with ^C. */ - action_exp = skip_spaces_const (action_exp); + action_exp = skip_spaces (action_exp); { - struct cleanup *old_chain = NULL; - struct cleanup *old_chain1 = NULL; - - exp = parse_exp_1 (&action_exp, tloc->address, - block_for_pc (tloc->address), 1); - old_chain = make_cleanup (free_current_contents, &exp); + expression_up exp = parse_exp_1 (&action_exp, tloc->address, + block_for_pc (tloc->address), + 1); - aexpr = gen_eval_for_expr (tloc->address, exp); - old_chain1 = make_cleanup_free_agent_expr (aexpr); + agent_expr_up aexpr = gen_eval_for_expr (tloc->address, + exp.get ()); - ax_reqs (aexpr); - report_agent_reqs_errors (aexpr); + finalize_tracepoint_aexpr (aexpr.get ()); - discard_cleanups (old_chain1); /* Even though we're not officially collecting, add to the collect list anyway. */ - add_aexpr (collect, aexpr); - - do_cleanups (old_chain); + collect->add_aexpr (std::move (aexpr)); } /* do */ } while (action_exp && *action_exp++ == ','); @@ -1634,7 +1479,7 @@ encode_actions_1 (struct command_line *action, here. */ gdb_assert (stepping_list); - encode_actions_1 (action->body_list[0], tloc, frame_reg, + encode_actions_1 (action->body_list_0.get (), tloc, frame_reg, frame_offset, stepping_list, NULL); } else @@ -1643,91 +1488,58 @@ encode_actions_1 (struct command_line *action, } /* Encode actions of tracepoint TLOC->owner and fill TRACEPOINT_LIST - and STEPPING_LIST. Return a cleanup pointer to clean up both - TRACEPOINT_LIST and STEPPING_LIST. */ + and STEPPING_LIST. */ -struct cleanup * -encode_actions_and_make_cleanup (struct bp_location *tloc, - struct collection_list *tracepoint_list, - struct collection_list *stepping_list) +void +encode_actions (struct bp_location *tloc, + struct collection_list *tracepoint_list, + struct collection_list *stepping_list) { - char *default_collect_line = NULL; - struct command_line *actions; - struct command_line *default_collect_action = NULL; int frame_reg; LONGEST frame_offset; - struct cleanup *back_to, *return_chain; - - return_chain = make_cleanup (null_cleanup, NULL); - init_collection_list (tracepoint_list); - init_collection_list (stepping_list); - make_cleanup (do_clear_collection_list, tracepoint_list); - make_cleanup (do_clear_collection_list, stepping_list); - - back_to = make_cleanup (null_cleanup, NULL); gdbarch_virtual_frame_pointer (tloc->gdbarch, tloc->address, &frame_reg, &frame_offset); - actions = all_tracepoint_actions_and_cleanup (tloc->owner); - - encode_actions_1 (actions, tloc, frame_reg, frame_offset, + counted_command_line actions = all_tracepoint_actions (tloc->owner); + encode_actions_1 (actions.get (), tloc, frame_reg, frame_offset, tracepoint_list, stepping_list); + encode_actions_1 (breakpoint_commands (tloc->owner), tloc, + frame_reg, frame_offset, tracepoint_list, stepping_list); - memrange_sortmerge (tracepoint_list); - memrange_sortmerge (stepping_list); - - do_cleanups (back_to); - return return_chain; + tracepoint_list->finish (); + stepping_list->finish (); } /* Render all actions into gdb protocol. */ void -encode_actions_rsp (struct bp_location *tloc, char ***tdp_actions, - char ***stepping_actions) +encode_actions_rsp (struct bp_location *tloc, + std::vector *tdp_actions, + std::vector *stepping_actions) { struct collection_list tracepoint_list, stepping_list; - struct cleanup *cleanup; - - *tdp_actions = NULL; - *stepping_actions = NULL; - - cleanup = encode_actions_and_make_cleanup (tloc, &tracepoint_list, - &stepping_list); - *tdp_actions = stringify_collection_list (&tracepoint_list); - *stepping_actions = stringify_collection_list (&stepping_list); + encode_actions (tloc, &tracepoint_list, &stepping_list); - do_cleanups (cleanup); + *tdp_actions = tracepoint_list.stringify (); + *stepping_actions = stepping_list.stringify (); } -static void -add_aexpr (struct collection_list *collect, struct agent_expr *aexpr) +void +collection_list::add_aexpr (agent_expr_up aexpr) { - if (collect->next_aexpr_elt >= collect->aexpr_listsize) - { - collect->aexpr_list = XRESIZEVEC (struct agent_expr *, - collect->aexpr_list, - 2 * collect->aexpr_listsize); - collect->aexpr_listsize *= 2; - } - collect->aexpr_list[collect->next_aexpr_elt] = aexpr; - collect->next_aexpr_elt++; + m_aexprs.push_back (std::move (aexpr)); } static void process_tracepoint_on_disconnect (void) { - VEC(breakpoint_p) *tp_vec = NULL; - int ix; - struct breakpoint *b; int has_pending_p = 0; /* Check whether we still have pending tracepoint. If we have, warn the user that pending tracepoint will no longer work. */ - tp_vec = all_tracepoints (); - for (ix = 0; VEC_iterate (breakpoint_p, tp_vec, ix, b); ix++) + for (breakpoint *b : all_tracepoints ()) { if (b->loc == NULL) { @@ -1751,7 +1563,6 @@ process_tracepoint_on_disconnect (void) break; } } - VEC_free (breakpoint_p, tp_vec); if (has_pending_p) warning (_("Pending tracepoints will not be resolved while" @@ -1770,29 +1581,19 @@ trace_reset_local_state (void) } void -start_tracing (char *notes) +start_tracing (const char *notes) { - VEC(breakpoint_p) *tp_vec = NULL; - int ix; - struct breakpoint *b; - struct trace_state_variable *tsv; int any_enabled = 0, num_to_download = 0; int ret; - tp_vec = all_tracepoints (); + std::vector tp_vec = all_tracepoints (); /* No point in tracing without any tracepoints... */ - if (VEC_length (breakpoint_p, tp_vec) == 0) - { - VEC_free (breakpoint_p, tp_vec); - error (_("No tracepoints defined, not starting trace")); - } + if (tp_vec.empty ()) + error (_("No tracepoints defined, not starting trace")); - for (ix = 0; VEC_iterate (breakpoint_p, tp_vec, ix, b); ix++) + for (breakpoint *b : tp_vec) { - struct tracepoint *t = (struct tracepoint *) b; - struct bp_location *loc; - if (b->enable_state == bp_enabled) any_enabled = 1; @@ -1813,20 +1614,16 @@ start_tracing (char *notes) { /* No point in tracing with only disabled tracepoints that cannot be re-enabled. */ - VEC_free (breakpoint_p, tp_vec); error (_("No tracepoints enabled, not starting trace")); } } if (num_to_download <= 0) - { - VEC_free (breakpoint_p, tp_vec); - error (_("No tracepoints that may be downloaded, not starting trace")); - } + error (_("No tracepoints that may be downloaded, not starting trace")); target_trace_init (); - for (ix = 0; VEC_iterate (breakpoint_p, tp_vec, ix, b); ix++) + for (breakpoint *b : tp_vec) { struct tracepoint *t = (struct tracepoint *) b; struct bp_location *loc; @@ -1858,22 +1655,17 @@ start_tracing (char *notes) t->number_on_target = b->number; for (loc = b->loc; loc; loc = loc->next) - if (loc->probe.probe != NULL - && loc->probe.probe->pops->set_semaphore != NULL) - loc->probe.probe->pops->set_semaphore (loc->probe.probe, - loc->probe.objfile, - loc->gdbarch); + if (loc->probe.prob != NULL) + loc->probe.prob->set_semaphore (loc->probe.objfile, + loc->gdbarch); if (bp_location_downloaded) - observer_notify_breakpoint_modified (b); + gdb::observers::breakpoint_modified.notify (b); } - VEC_free (breakpoint_p, tp_vec); /* Send down all the trace state variables too. */ - for (ix = 0; VEC_iterate (tsv_s, tvariables, ix, tsv); ++ix) - { - target_download_trace_state_variable (tsv); - } + for (const trace_state_variable &tsv : tvariables) + target_download_trace_state_variable (tsv); /* Tell target to treat text-like sections as transparent. */ target_trace_set_readonly_regions (); @@ -1904,7 +1696,7 @@ start_tracing (char *notes) anybody else messing with the target. */ static void -trace_start_command (char *args, int from_tty) +tstart_command (const char *args, int from_tty) { dont_repeat (); /* Like "run", dangerous to repeat accidentally. */ @@ -1924,7 +1716,7 @@ trace_start_command (char *args, int from_tty) of the trace run's status. */ static void -trace_stop_command (char *args, int from_tty) +tstop_command (const char *args, int from_tty) { if (!current_trace_status ()->running) error (_("Trace is not running.")); @@ -1933,17 +1725,13 @@ trace_stop_command (char *args, int from_tty) } void -stop_tracing (char *note) +stop_tracing (const char *note) { int ret; - VEC(breakpoint_p) *tp_vec = NULL; - int ix; - struct breakpoint *t; target_trace_stop (); - tp_vec = all_tracepoints (); - for (ix = 0; VEC_iterate (breakpoint_p, tp_vec, ix, t); ix++) + for (breakpoint *t : all_tracepoints ()) { struct bp_location *loc; @@ -1958,16 +1746,12 @@ stop_tracing (char *note) but we don't really care if this semaphore goes out of sync. That's why we are decrementing it here, but not taking care in other places. */ - if (loc->probe.probe != NULL - && loc->probe.probe->pops->clear_semaphore != NULL) - loc->probe.probe->pops->clear_semaphore (loc->probe.probe, - loc->probe.objfile, - loc->gdbarch); + if (loc->probe.prob != NULL) + loc->probe.prob->clear_semaphore (loc->probe.objfile, + loc->gdbarch); } } - VEC_free (breakpoint_p, tp_vec); - if (!note) note = trace_stop_notes; ret = target_set_trace_notes (NULL, NULL, note); @@ -1981,12 +1765,10 @@ stop_tracing (char *note) /* tstatus command */ static void -trace_status_command (char *args, int from_tty) +tstatus_command (const char *args, int from_tty) { struct trace_status *ts = current_trace_status (); - int status, ix; - VEC(breakpoint_p) *tp_vec = NULL; - struct breakpoint *t; + int status; status = target_get_trace_status (ts); @@ -2016,7 +1798,7 @@ trace_status_command (char *args, int from_tty) case trace_never_run: printf_filtered (_("No trace has been run on the target.\n")); break; - case tstop_command: + case trace_stop_command: if (ts->stop_desc) printf_filtered (_("Trace stopped by a tstop command (%s).\n"), ts->stop_desc); @@ -2129,12 +1911,8 @@ trace_status_command (char *args, int from_tty) (long int) (ts->stop_time % 1000000)); /* Now report any per-tracepoint status available. */ - tp_vec = all_tracepoints (); - - for (ix = 0; VEC_iterate (breakpoint_p, tp_vec, ix, t); ix++) + for (breakpoint *t : all_tracepoints ()) target_get_tracepoint_status (t, NULL); - - VEC_free (breakpoint_p, tp_vec); } /* Report the trace status to uiout, in a way suitable for MI, and not @@ -2154,23 +1932,23 @@ trace_status_mi (int on_stop) if (status == -1 && ts->filename == NULL) { - ui_out_field_string (uiout, "supported", "0"); + uiout->field_string ("supported", "0"); return; } if (ts->filename != NULL) - ui_out_field_string (uiout, "supported", "file"); + uiout->field_string ("supported", "file"); else if (!on_stop) - ui_out_field_string (uiout, "supported", "1"); + uiout->field_string ("supported", "1"); if (ts->filename != NULL) - ui_out_field_string (uiout, "trace-file", ts->filename); + uiout->field_string ("trace-file", ts->filename); gdb_assert (ts->running_known); if (ts->running) { - ui_out_field_string (uiout, "running", "1"); + uiout->field_string ("running", "1"); /* Unlike CLI, do not show the state of 'disconnected-tracing' variable. Given that the frontend gets the status either on -trace-stop, or from @@ -2183,17 +1961,17 @@ trace_status_mi (int on_stop) } else { - char *stop_reason = NULL; + const char *stop_reason = NULL; int stopping_tracepoint = -1; if (!on_stop) - ui_out_field_string (uiout, "running", "0"); + uiout->field_string ("running", "0"); if (ts->stop_reason != trace_stop_reason_unknown) { switch (ts->stop_reason) { - case tstop_command: + case trace_stop_command: stop_reason = "request"; break; case trace_buffer_full: @@ -2214,31 +1992,31 @@ trace_status_mi (int on_stop) if (stop_reason) { - ui_out_field_string (uiout, "stop-reason", stop_reason); + uiout->field_string ("stop-reason", stop_reason); if (stopping_tracepoint != -1) - ui_out_field_int (uiout, "stopping-tracepoint", - stopping_tracepoint); + uiout->field_signed ("stopping-tracepoint", + stopping_tracepoint); if (ts->stop_reason == tracepoint_error) - ui_out_field_string (uiout, "error-description", + uiout->field_string ("error-description", ts->stop_desc); } } } if (ts->traceframe_count != -1) - ui_out_field_int (uiout, "frames", ts->traceframe_count); + uiout->field_signed ("frames", ts->traceframe_count); if (ts->traceframes_created != -1) - ui_out_field_int (uiout, "frames-created", ts->traceframes_created); + uiout->field_signed ("frames-created", ts->traceframes_created); if (ts->buffer_size != -1) - ui_out_field_int (uiout, "buffer-size", ts->buffer_size); + uiout->field_signed ("buffer-size", ts->buffer_size); if (ts->buffer_free != -1) - ui_out_field_int (uiout, "buffer-free", ts->buffer_free); + uiout->field_signed ("buffer-free", ts->buffer_free); - ui_out_field_int (uiout, "disconnected", ts->disconnected_tracing); - ui_out_field_int (uiout, "circular", ts->circular_buffer); + uiout->field_signed ("disconnected", ts->disconnected_tracing); + uiout->field_signed ("circular", ts->circular_buffer); - ui_out_field_string (uiout, "user-name", ts->user_name); - ui_out_field_string (uiout, "notes", ts->notes); + uiout->field_string ("user-name", ts->user_name); + uiout->field_string ("notes", ts->notes); { char buf[100]; @@ -2246,11 +2024,11 @@ trace_status_mi (int on_stop) xsnprintf (buf, sizeof buf, "%ld.%06ld", (long int) (ts->start_time / 1000000), (long int) (ts->start_time % 1000000)); - ui_out_field_string (uiout, "start-time", buf); + uiout->field_string ("start-time", buf); xsnprintf (buf, sizeof buf, "%ld.%06ld", (long int) (ts->stop_time / 1000000), (long int) (ts->stop_time % 1000000)); - ui_out_field_string (uiout, "stop-time", buf); + uiout->field_string ("stop-time", buf); } } @@ -2352,7 +2130,7 @@ tfind_1 (enum trace_find_type type, int num, DON'T give an error, but DO change the state of traceframe_number etc. to invalid. - The rationalle is that if you typed the command, you + The rationale is that if you typed the command, you might just have committed a typo or something, and you'd like to NOT lose your current debugging state. However if you're in a user-defined command or especially in a @@ -2370,7 +2148,7 @@ tfind_1 (enum trace_find_type type, int num, #if 0 /* dubious now? */ /* The following will not recurse, since it's special-cased. */ - trace_find_command ("-1", from_tty); + tfind_command ("-1", from_tty); #endif } } @@ -2380,10 +2158,10 @@ tfind_1 (enum trace_find_type type, int num, reinit_frame_cache (); target_dcache_invalidate (); - set_tracepoint_num (tp ? tp->base.number : target_tracept); + set_tracepoint_num (tp ? tp->number : target_tracept); if (target_frameno != get_traceframe_number ()) - observer_notify_traceframe_changed (target_frameno, tracepoint_number); + gdb::observers::traceframe_changed.notify (target_frameno, tracepoint_number); set_current_traceframe (target_frameno); @@ -2396,11 +2174,11 @@ tfind_1 (enum trace_find_type type, int num, { /* Use different branches for MI and CLI to make CLI messages i18n-eable. */ - if (ui_out_is_mi_like_p (uiout)) + if (uiout->is_mi_like_p ()) { - ui_out_field_string (uiout, "found", "1"); - ui_out_field_int (uiout, "tracepoint", tracepoint_number); - ui_out_field_int (uiout, "traceframe", traceframe_number); + uiout->field_string ("found", "1"); + uiout->field_signed ("tracepoint", tracepoint_number); + uiout->field_signed ("traceframe", traceframe_number); } else { @@ -2410,8 +2188,8 @@ tfind_1 (enum trace_find_type type, int num, } else { - if (ui_out_is_mi_like_p (uiout)) - ui_out_field_string (uiout, "found", "0"); + if (uiout->is_mi_like_p ()) + uiout->field_string ("found", "0"); else if (type == tfind_number && num == -1) printf_unfiltered (_("No longer looking at any trace frame\n")); else /* This case may never occur, check. */ @@ -2468,7 +2246,7 @@ check_trace_running (struct trace_status *status) /* tfind command */ static void -trace_find_command (char *args, int from_tty) +tfind_command_1 (const char *args, int from_tty) { /* This should only be called with a numeric argument. */ int frameno = -1; @@ -2502,23 +2280,29 @@ trace_find_command (char *args, int from_tty) tfind_1 (tfind_number, frameno, 0, 0, from_tty); } +static void +tfind_command (const char *args, int from_tty) +{ + tfind_command_1 (args, from_tty); +} + /* tfind end */ static void -trace_find_end_command (char *args, int from_tty) +tfind_end_command (const char *args, int from_tty) { - trace_find_command ("-1", from_tty); + tfind_command_1 ("-1", from_tty); } /* tfind start */ static void -trace_find_start_command (char *args, int from_tty) +tfind_start_command (const char *args, int from_tty) { - trace_find_command ("0", from_tty); + tfind_command_1 ("0", from_tty); } /* tfind pc command */ static void -trace_find_pc_command (char *args, int from_tty) +tfind_pc_command (const char *args, int from_tty) { CORE_ADDR pc; @@ -2534,7 +2318,7 @@ trace_find_pc_command (char *args, int from_tty) /* tfind tracepoint command */ static void -trace_find_tracepoint_command (char *args, int from_tty) +tfind_tracepoint_command (const char *args, int from_tty) { int tdp; struct tracepoint *tp; @@ -2570,32 +2354,26 @@ trace_find_tracepoint_command (char *args, int from_tty) corresponding to a source line OTHER THAN THE CURRENT ONE. */ static void -trace_find_line_command (char *args, int from_tty) +tfind_line_command (const char *args, int from_tty) { - static CORE_ADDR start_pc, end_pc; - struct symtabs_and_lines sals; - struct symtab_and_line sal; - struct cleanup *old_chain; - check_trace_running (current_trace_status ()); + symtab_and_line sal; if (args == 0 || *args == 0) { sal = find_pc_line (get_frame_pc (get_current_frame ()), 0); - sals.nelts = 1; - sals.sals = XNEW (struct symtab_and_line); - sals.sals[0] = sal; } else { - sals = decode_line_with_current_source (args, DECODE_LINE_FUNFIRSTLINE); - sal = sals.sals[0]; + std::vector sals + = decode_line_with_current_source (args, DECODE_LINE_FUNFIRSTLINE); + sal = sals[0]; } - - old_chain = make_cleanup (xfree, sals.sals); + if (sal.symtab == 0) error (_("No line number information available.")); + CORE_ADDR start_pc, end_pc; if (sal.line > 0 && find_line_pc_range (sal, &start_pc, &end_pc)) { if (start_pc == end_pc) @@ -2630,29 +2408,29 @@ trace_find_line_command (char *args, int from_tty) tfind_1 (tfind_range, 0, start_pc, end_pc - 1, from_tty); else tfind_1 (tfind_outside, 0, start_pc, end_pc - 1, from_tty); - do_cleanups (old_chain); } /* tfind range command */ static void -trace_find_range_command (char *args, int from_tty) +tfind_range_command (const char *args, int from_tty) { static CORE_ADDR start, stop; - char *tmp; + const char *tmp; check_trace_running (current_trace_status ()); if (args == 0 || *args == 0) { /* XXX FIXME: what should default behavior be? */ - printf_filtered ("Usage: tfind range ,\n"); + printf_filtered ("Usage: tfind range STARTADDR, ENDADDR\n"); return; } if (0 != (tmp = strchr (args, ','))) { - *tmp++ = '\0'; /* Terminate start address. */ + std::string start_addr (args, tmp); + ++tmp; tmp = skip_spaces (tmp); - start = parse_and_eval_address (args); + start = parse_and_eval_address (start_addr.c_str ()); stop = parse_and_eval_address (tmp); } else @@ -2666,10 +2444,10 @@ trace_find_range_command (char *args, int from_tty) /* tfind outside command */ static void -trace_find_outside_command (char *args, int from_tty) +tfind_outside_command (const char *args, int from_tty) { CORE_ADDR start, stop; - char *tmp; + const char *tmp; if (current_trace_status ()->running && current_trace_status ()->filename == NULL) @@ -2677,15 +2455,16 @@ trace_find_outside_command (char *args, int from_tty) if (args == 0 || *args == 0) { /* XXX FIXME: what should default behavior be? */ - printf_filtered ("Usage: tfind outside ,\n"); + printf_filtered ("Usage: tfind outside STARTADDR, ENDADDR\n"); return; } if (0 != (tmp = strchr (args, ','))) { - *tmp++ = '\0'; /* Terminate start address. */ + std::string start_addr (args, tmp); + ++tmp; tmp = skip_spaces (tmp); - start = parse_and_eval_address (args); + start = parse_and_eval_address (start_addr.c_str ()); stop = parse_and_eval_address (tmp); } else @@ -2699,38 +2478,37 @@ trace_find_outside_command (char *args, int from_tty) /* info scope command: list the locals for a scope. */ static void -scope_info (char *args, int from_tty) +info_scope_command (const char *args_in, int from_tty) { - struct symtabs_and_lines sals; struct symbol *sym; struct bound_minimal_symbol msym; const struct block *block; const char *symname; - char *save_args = args; + const char *save_args = args_in; struct block_iterator iter; int j, count = 0; struct gdbarch *gdbarch; int regno; - struct event_location *location; - struct cleanup *back_to; + const char *args = args_in; if (args == 0 || *args == 0) error (_("requires an argument (function, " "line or *addr) to define a scope")); - location = string_to_event_location (&args, current_language); - back_to = make_cleanup_delete_event_location (location); - sals = decode_line_1 (location, DECODE_LINE_FUNFIRSTLINE, NULL, NULL, 0); - if (sals.nelts == 0) + event_location_up location = string_to_event_location (&args, + current_language); + std::vector sals + = decode_line_1 (location.get (), DECODE_LINE_FUNFIRSTLINE, + NULL, NULL, 0); + if (sals.empty ()) { /* Presumably decode_line_1 has already warned. */ - do_cleanups (back_to); return; } /* Resolve line numbers to PC. */ - resolve_sal_pc (&sals.sals[0]); - block = block_for_pc (sals.sals[0].pc); + resolve_sal_pc (&sals[0]); + block = block_for_pc (sals[0].pc); while (block != 0) { @@ -2742,7 +2520,7 @@ scope_info (char *args, int from_tty) printf_filtered ("Scope for %s:\n", save_args); count++; - symname = SYMBOL_PRINT_NAME (sym); + symname = sym->print_name (); if (symname == NULL || *symname == '\0') continue; /* Probably botched, certainly useless. */ @@ -2752,7 +2530,7 @@ scope_info (char *args, int from_tty) if (SYMBOL_COMPUTED_OPS (sym) != NULL) SYMBOL_COMPUTED_OPS (sym)->describe_location (sym, - BLOCK_START (block), + BLOCK_ENTRY_PC (block), gdb_stdout); else { @@ -2829,10 +2607,10 @@ scope_info (char *args, int from_tty) case LOC_BLOCK: printf_filtered ("a function at address "); printf_filtered ("%s", - paddress (gdbarch, BLOCK_START (SYMBOL_BLOCK_VALUE (sym)))); + paddress (gdbarch, BLOCK_ENTRY_PC (SYMBOL_BLOCK_VALUE (sym)))); break; case LOC_UNRESOLVED: - msym = lookup_minimal_symbol (SYMBOL_LINKAGE_NAME (sym), + msym = lookup_minimal_symbol (sym->linkage_name (), NULL, NULL); if (msym.minsym == NULL) printf_filtered ("Unresolved Static"); @@ -2852,8 +2630,11 @@ scope_info (char *args, int from_tty) } } if (SYMBOL_TYPE (sym)) - printf_filtered (", length %d.\n", - TYPE_LENGTH (check_typedef (SYMBOL_TYPE (sym)))); + { + struct type *t = check_typedef (SYMBOL_TYPE (sym)); + + printf_filtered (", length %s.\n", pulongest (TYPE_LENGTH (t))); + } } if (BLOCK_FUNCTION (block)) break; @@ -2863,7 +2644,6 @@ scope_info (char *args, int from_tty) if (count <= 0) printf_filtered ("Scope for %s contains no locals or arguments.\n", save_args); - do_cleanups (back_to); } /* Helper for trace_dump_command. Dump the action list starting at @@ -2885,7 +2665,7 @@ trace_dump_actions (struct command_line *action, QUIT; /* Allow user to bail out with ^C. */ action_exp = action->line; - action_exp = skip_spaces_const (action_exp); + action_exp = skip_spaces (action_exp); /* The collection actions to be done while stepping are bracketed by the commands "while-stepping" and "end". */ @@ -2899,11 +2679,9 @@ trace_dump_actions (struct command_line *action, if (cmd_cfunc_eq (cmd, while_stepping_pseudocommand)) { - int i; - - for (i = 0; i < action->body_count; ++i) - trace_dump_actions (action->body_list[i], - 1, stepping_frame, from_tty); + gdb_assert (action->body_list_1 == nullptr); + trace_dump_actions (action->body_list_0.get (), + 1, stepping_frame, from_tty); } else if (cmd_cfunc_eq (cmd, collect_pseudocommand)) { @@ -2915,9 +2693,6 @@ trace_dump_actions (struct command_line *action, STEPPING_ACTIONS should be equal. */ if (stepping_frame == stepping_actions) { - char *cmd = NULL; - struct cleanup *old_chain - = make_cleanup (free_current_contents, &cmd); int trace_string = 0; if (*action_exp == '/') @@ -2928,7 +2703,7 @@ trace_dump_actions (struct command_line *action, QUIT; /* Allow user to bail out with ^C. */ if (*action_exp == ',') action_exp++; - action_exp = skip_spaces_const (action_exp); + action_exp = skip_spaces (action_exp); next_comma = strchr (action_exp, ','); @@ -2937,36 +2712,27 @@ trace_dump_actions (struct command_line *action, else if (0 == strncasecmp (action_exp, "$_ret", 5)) ; else if (0 == strncasecmp (action_exp, "$loc", 4)) - locals_info (NULL, from_tty); + info_locals_command (NULL, from_tty); else if (0 == strncasecmp (action_exp, "$arg", 4)) - args_info (NULL, from_tty); + info_args_command (NULL, from_tty); else { /* variable */ + std::string contents; + const char *exp = action_exp; if (next_comma != NULL) { size_t len = next_comma - action_exp; - - cmd = (char *) xrealloc (cmd, len + 1); - memcpy (cmd, action_exp, len); - cmd[len] = 0; + contents = std::string (action_exp, len); + exp = contents.c_str (); } - else - { - size_t len = strlen (action_exp); - cmd = (char *) xrealloc (cmd, len + 1); - memcpy (cmd, action_exp, len + 1); - } - - printf_filtered ("%s = ", cmd); - output_command_const (cmd, from_tty); + printf_filtered ("%s = ", exp); + output_command (exp, from_tty); printf_filtered ("\n"); } action_exp = next_comma; } while (action_exp && *action_exp == ','); - - do_cleanups (old_chain); } } } @@ -3001,7 +2767,7 @@ get_traceframe_location (int *stepping_frame_p) locations, assume it is a direct hit rather than a while-stepping frame. (FIXME this is not reliable, should record each frame's type.) */ - for (tloc = t->base.loc; tloc; tloc = tloc->next) + for (tloc = t->loc; tloc; tloc = tloc->next) if (tloc->address == regcache_read_pc (regcache)) { *stepping_frame_p = 0; @@ -3011,19 +2777,15 @@ get_traceframe_location (int *stepping_frame_p) /* If this is a stepping frame, we don't know which location triggered. The first is as good (or bad) a guess as any... */ *stepping_frame_p = 1; - return t->base.loc; + return t->loc; } -/* Return all the actions, including default collect, of a tracepoint - T. It constructs cleanups into the chain, and leaves the caller to - handle them (call do_cleanups). */ +/* Return the default collect actions of a tracepoint T. */ -static struct command_line * -all_tracepoint_actions_and_cleanup (struct breakpoint *t) +static counted_command_line +all_tracepoint_actions (struct breakpoint *t) { - struct command_line *actions; - - actions = breakpoint_commands (t); + counted_command_line actions (nullptr, command_lines_deleter ()); /* If there are default expressions to collect, make up a collect action and prepend to the action list to encode. Note that since @@ -3032,18 +2794,13 @@ all_tracepoint_actions_and_cleanup (struct breakpoint *t) the fly, and don't cache it. */ if (*default_collect) { - struct command_line *default_collect_action; - char *default_collect_line; - - default_collect_line = xstrprintf ("collect %s", default_collect); - make_cleanup (xfree, default_collect_line); - - validate_actionline (default_collect_line, t); - default_collect_action = XNEW (struct command_line); - make_cleanup (xfree, default_collect_action); - default_collect_action->next = actions; - default_collect_action->line = default_collect_line; - actions = default_collect_action; + gdb::unique_xmalloc_ptr default_collect_line + (xstrprintf ("collect %s", default_collect)); + + validate_actionline (default_collect_line.get (), t); + actions.reset (new struct command_line (simple_control, + default_collect_line.release ()), + command_lines_deleter ()); } return actions; @@ -3052,12 +2809,10 @@ all_tracepoint_actions_and_cleanup (struct breakpoint *t) /* The tdump command. */ static void -trace_dump_command (char *args, int from_tty) +tdump_command (const char *args, int from_tty) { int stepping_frame = 0; struct bp_location *loc; - struct cleanup *old_chain; - struct command_line *actions; /* This throws an error is not inspecting a trace frame. */ loc = get_traceframe_location (&stepping_frame); @@ -3065,18 +2820,17 @@ trace_dump_command (char *args, int from_tty) printf_filtered ("Data collected at tracepoint %d, trace frame %d:\n", tracepoint_number, traceframe_number); - old_chain = make_cleanup (null_cleanup, NULL); - /* This command only makes sense for the current frame, not the selected frame. */ - make_cleanup_restore_current_thread (); - select_frame (get_current_frame ()); + scoped_restore_current_thread restore_thread; - actions = all_tracepoint_actions_and_cleanup (loc->owner); + select_frame (get_current_frame ()); - trace_dump_actions (actions, 0, stepping_frame, from_tty); + counted_command_line actions = all_tracepoint_actions (loc->owner); - do_cleanups (old_chain); + trace_dump_actions (actions.get (), 0, stepping_frame, from_tty); + trace_dump_actions (breakpoint_commands (loc->owner), 0, stepping_frame, + from_tty); } /* Encode a piece of a tracepoint's source-level definition in a form @@ -3084,9 +2838,10 @@ trace_dump_command (char *args, int from_tty) /* This version does not do multiple encodes for long strings; it should return an offset to the next piece to encode. FIXME */ -extern int +int encode_source_string (int tpnum, ULONGEST addr, - char *srctype, const char *src, char *buf, int buf_size) + const char *srctype, const char *src, + char *buf, int buf_size) { if (80 + strlen (srctype) > buf_size) error (_("Buffer too small for source encoding")); @@ -3103,28 +2858,28 @@ encode_source_string (int tpnum, ULONGEST addr, disconnects for some reason. */ static void -set_disconnected_tracing (char *args, int from_tty, +set_disconnected_tracing (const char *args, int from_tty, struct cmd_list_element *c) { target_set_disconnected_tracing (disconnected_tracing); } static void -set_circular_trace_buffer (char *args, int from_tty, +set_circular_trace_buffer (const char *args, int from_tty, struct cmd_list_element *c) { target_set_circular_trace_buffer (circular_trace_buffer); } static void -set_trace_buffer_size (char *args, int from_tty, +set_trace_buffer_size (const char *args, int from_tty, struct cmd_list_element *c) { target_set_trace_buffer_size (trace_buffer_size); } static void -set_trace_user (char *args, int from_tty, +set_trace_user (const char *args, int from_tty, struct cmd_list_element *c) { int ret; @@ -3136,7 +2891,7 @@ set_trace_user (char *args, int from_tty, } static void -set_trace_notes (char *args, int from_tty, +set_trace_notes (const char *args, int from_tty, struct cmd_list_element *c) { int ret; @@ -3148,7 +2903,7 @@ set_trace_notes (char *args, int from_tty, } static void -set_trace_stop_notes (char *args, int from_tty, +set_trace_stop_notes (const char *args, int from_tty, struct cmd_list_element *c) { int ret; @@ -3224,43 +2979,9 @@ set_current_traceframe (int num) clear_traceframe_info (); } -/* A cleanup used when switching away and back from tfind mode. */ - -struct current_traceframe_cleanup -{ - /* The traceframe we were inspecting. */ - int traceframe_number; -}; - -static void -do_restore_current_traceframe_cleanup (void *arg) -{ - struct current_traceframe_cleanup *old - = (struct current_traceframe_cleanup *) arg; - - set_current_traceframe (old->traceframe_number); -} - -static void -restore_current_traceframe_cleanup_dtor (void *arg) -{ - struct current_traceframe_cleanup *old - = (struct current_traceframe_cleanup *) arg; - - xfree (old); -} - -struct cleanup * -make_cleanup_restore_current_traceframe (void) -{ - struct current_traceframe_cleanup *old = - XNEW (struct current_traceframe_cleanup); - - old->traceframe_number = traceframe_number; - - return make_cleanup_dtor (do_restore_current_traceframe_cleanup, old, - restore_current_traceframe_cleanup_dtor); -} +scoped_restore_current_traceframe::scoped_restore_current_traceframe () +: m_traceframe_number (traceframe_number) +{} /* Given a number and address, return an uploaded tracepoint with that number, creating if necessary. */ @@ -3274,12 +2995,9 @@ get_uploaded_tp (int num, ULONGEST addr, struct uploaded_tp **utpp) if (utp->number == num && utp->addr == addr) return utp; - utp = XCNEW (struct uploaded_tp); + utp = new uploaded_tp; utp->number = num; utp->addr = addr; - utp->actions = NULL; - utp->step_actions = NULL; - utp->cmd_strings = NULL; utp->next = *utpp; *utpp = utp; @@ -3294,7 +3012,7 @@ free_uploaded_tps (struct uploaded_tp **utpp) while (*utpp) { next_one = (*utpp)->next; - xfree (*utpp); + delete *utpp; *utpp = next_one; } } @@ -3353,19 +3071,17 @@ cond_string_is_same (char *str1, char *str2) static struct bp_location * find_matching_tracepoint_location (struct uploaded_tp *utp) { - VEC(breakpoint_p) *tp_vec = all_tracepoints (); - int ix; - struct breakpoint *b; struct bp_location *loc; - for (ix = 0; VEC_iterate (breakpoint_p, tp_vec, ix, b); ix++) + for (breakpoint *b : all_tracepoints ()) { struct tracepoint *t = (struct tracepoint *) b; if (b->type == utp->type && t->step_count == utp->step && t->pass_count == utp->pass - && cond_string_is_same (t->base.cond_string, utp->cond_string) + && cond_string_is_same (t->cond_string, + utp->cond_string.get ()) /* FIXME also test actions. */ ) { @@ -3389,9 +3105,7 @@ merge_uploaded_tracepoints (struct uploaded_tp **uploaded_tps) { struct uploaded_tp *utp; /* A set of tracepoints which are modified. */ - VEC(breakpoint_p) *modified_tp = NULL; - int ix; - struct breakpoint *b; + std::vector modified_tp; /* Look for GDB tracepoints that match up with our uploaded versions. */ for (utp = *uploaded_tps; utp; utp = utp->next) @@ -3417,16 +3131,14 @@ merge_uploaded_tracepoints (struct uploaded_tp **uploaded_tps) MODIFIED_TP if not there yet. The 'breakpoint-modified' observers will be notified later once for each tracepoint saved in MODIFIED_TP. */ - for (ix = 0; - VEC_iterate (breakpoint_p, modified_tp, ix, b); - ix++) + for (breakpoint *b : modified_tp) if (b == loc->owner) { found = 1; break; } if (!found) - VEC_safe_push (breakpoint_p, modified_tp, loc->owner); + modified_tp.push_back (loc->owner); } else { @@ -3434,7 +3146,7 @@ merge_uploaded_tracepoints (struct uploaded_tp **uploaded_tps) if (t) printf_filtered (_("Created tracepoint %d for " "target's tracepoint %d at %s.\n"), - t->base.number, utp->number, + t->number, utp->number, paddress (get_current_arch (), utp->addr)); else printf_filtered (_("Failed to create tracepoint for target's " @@ -3451,10 +3163,9 @@ merge_uploaded_tracepoints (struct uploaded_tp **uploaded_tps) /* Notify 'breakpoint-modified' observer that at least one of B's locations was changed. */ - for (ix = 0; VEC_iterate (breakpoint_p, modified_tp, ix, b); ix++) - observer_notify_breakpoint_modified (b); + for (breakpoint *b : modified_tp) + gdb::observers::breakpoint_modified.notify (b); - VEC_free (breakpoint_p, modified_tp); free_uploaded_tps (uploaded_tps); } @@ -3474,40 +3185,32 @@ static struct trace_state_variable * create_tsv_from_upload (struct uploaded_tsv *utsv) { const char *namebase; - char *buf; + std::string buf; int try_num = 0; struct trace_state_variable *tsv; - struct cleanup *old_chain; if (utsv->name) { namebase = utsv->name; - buf = xstrprintf ("%s", namebase); + buf = namebase; } else { namebase = "__tsv"; - buf = xstrprintf ("%s_%d", namebase, try_num++); + buf = string_printf ("%s_%d", namebase, try_num++); } /* Fish for a name that is not in use. */ /* (should check against all internal vars?) */ - while (find_trace_state_variable (buf)) - { - xfree (buf); - buf = xstrprintf ("%s_%d", namebase, try_num++); - } - - old_chain = make_cleanup (xfree, buf); + while (find_trace_state_variable (buf.c_str ())) + buf = string_printf ("%s_%d", namebase, try_num++); /* We have an available name, create the variable. */ - tsv = create_trace_state_variable (buf); + tsv = create_trace_state_variable (buf.c_str ()); tsv->initial_value = utsv->initial_value; tsv->builtin = utsv->builtin; - observer_notify_tsv_created (tsv); - - do_cleanups (old_chain); + gdb::observers::tsv_created.notify (tsv); return tsv; } @@ -3518,25 +3221,23 @@ create_tsv_from_upload (struct uploaded_tsv *utsv) void merge_uploaded_trace_state_variables (struct uploaded_tsv **uploaded_tsvs) { - int ix; struct uploaded_tsv *utsv; - struct trace_state_variable *tsv; int highest; /* Most likely some numbers will have to be reassigned as part of the merge, so clear them all in anticipation. */ - for (ix = 0; VEC_iterate (tsv_s, tvariables, ix, tsv); ++ix) - tsv->number = 0; + for (trace_state_variable &tsv : tvariables) + tsv.number = 0; for (utsv = *uploaded_tsvs; utsv; utsv = utsv->next) { - tsv = find_matching_tsv (utsv); + struct trace_state_variable *tsv = find_matching_tsv (utsv); if (tsv) { if (info_verbose) printf_filtered (_("Assuming trace state variable $%s " "is same as target's variable %d.\n"), - tsv->name, utsv->number); + tsv->name.c_str (), utsv->number); } else { @@ -3544,7 +3245,7 @@ merge_uploaded_trace_state_variables (struct uploaded_tsv **uploaded_tsvs) if (info_verbose) printf_filtered (_("Created trace state variable " "$%s for target's variable %d.\n"), - tsv->name, utsv->number); + tsv->name.c_str (), utsv->number); } /* Give precedence to numberings that come from the target. */ if (tsv) @@ -3553,14 +3254,13 @@ merge_uploaded_trace_state_variables (struct uploaded_tsv **uploaded_tsvs) /* Renumber everything that didn't get a target-assigned number. */ highest = 0; - for (ix = 0; VEC_iterate (tsv_s, tvariables, ix, tsv); ++ix) - if (tsv->number > highest) - highest = tsv->number; + for (const trace_state_variable &tsv : tvariables) + highest = std::max (tsv.number, highest); ++highest; - for (ix = 0; VEC_iterate (tsv_s, tvariables, ix, tsv); ++ix) - if (tsv->number == 0) - tsv->number = highest++; + for (trace_state_variable &tsv : tvariables) + if (tsv.number == 0) + tsv.number = highest++; free_uploaded_tsvs (uploaded_tsvs); } @@ -3569,9 +3269,9 @@ merge_uploaded_trace_state_variables (struct uploaded_tsv **uploaded_tsvs) the remote protocol and the trace file reader. */ void -parse_trace_status (char *line, struct trace_status *ts) +parse_trace_status (const char *line, struct trace_status *ts) { - char *p = line, *p1, *p2, *p3, *p_temp; + const char *p = line, *p1, *p2, *p3, *p_temp; int end; ULONGEST val; @@ -3618,7 +3318,7 @@ Status line: '%s'\n"), p, line); ts->stop_reason = tracepoint_passcount; ts->stopping_tracepoint = val; } - else if (strncmp (p, stop_reason_names[tstop_command], p1 - p) == 0) + else if (strncmp (p, stop_reason_names[trace_stop_command], p1 - p) == 0) { p2 = strchr (++p1, ':'); if (!p2 || p2 > p3) @@ -3636,7 +3336,7 @@ Status line: '%s'\n"), p, line); ts->stop_desc = xstrdup (""); p = unpack_varlen_hex (++p2, &val); - ts->stop_reason = tstop_command; + ts->stop_reason = trace_stop_command; } else if (strncmp (p, stop_reason_names[trace_disconnected], p1 - p) == 0) { @@ -3729,7 +3429,7 @@ Status line: '%s'\n"), p, line); } void -parse_tracepoint_status (char *p, struct breakpoint *bp, +parse_tracepoint_status (const char *p, struct breakpoint *bp, struct uploaded_tp *utp) { ULONGEST uval; @@ -3737,7 +3437,7 @@ parse_tracepoint_status (char *p, struct breakpoint *bp, p = unpack_varlen_hex (p, &uval); if (tp) - tp->base.hit_count += uval; + tp->hit_count += uval; else utp->hit_count += uval; p = unpack_varlen_hex (p + 1, &uval); @@ -3752,14 +3452,15 @@ parse_tracepoint_status (char *p, struct breakpoint *bp, an "uploaded tracepoint". */ void -parse_tracepoint_definition (char *line, struct uploaded_tp **utpp) +parse_tracepoint_definition (const char *line, struct uploaded_tp **utpp) { - char *p; + const char *p; char piece; ULONGEST num, addr, step, pass, orig_size, xlen, start; int enabled, end; enum bptype type; - char *cond, *srctype, *buf; + const char *srctype; + char *buf; struct uploaded_tp *utp = NULL; p = line; @@ -3772,13 +3473,14 @@ parse_tracepoint_definition (char *line, struct uploaded_tp **utpp) p++; /* skip a colon */ if (piece == 'T') { + gdb::unique_xmalloc_ptr cond; + enabled = (*p++ == 'E'); p++; /* skip a colon */ p = unpack_varlen_hex (p, &step); p++; /* skip a colon */ p = unpack_varlen_hex (p, &pass); type = bp_tracepoint; - cond = NULL; /* Thumb through optional fields. */ while (*p == ':') { @@ -3799,8 +3501,8 @@ parse_tracepoint_definition (char *line, struct uploaded_tp **utpp) p++; p = unpack_varlen_hex (p, &xlen); p++; /* skip a comma */ - cond = (char *) xmalloc (2 * xlen + 1); - strncpy (cond, p, 2 * xlen); + cond.reset ((char *) xmalloc (2 * xlen + 1)); + strncpy (&cond[0], p, 2 * xlen); cond[2 * xlen] = '\0'; p += 2 * xlen; } @@ -3813,17 +3515,17 @@ parse_tracepoint_definition (char *line, struct uploaded_tp **utpp) utp->enabled = enabled; utp->step = step; utp->pass = pass; - utp->cond = cond; + utp->cond = std::move (cond); } else if (piece == 'A') { utp = get_uploaded_tp (num, addr, utpp); - VEC_safe_push (char_ptr, utp->actions, xstrdup (p)); + utp->actions.emplace_back (xstrdup (p)); } else if (piece == 'S') { utp = get_uploaded_tp (num, addr, utpp); - VEC_safe_push (char_ptr, utp->step_actions, xstrdup (p)); + utp->step_actions.emplace_back (xstrdup (p)); } else if (piece == 'Z') { @@ -3843,11 +3545,11 @@ parse_tracepoint_definition (char *line, struct uploaded_tp **utpp) buf[end] = '\0'; if (startswith (srctype, "at:")) - utp->at_string = xstrdup (buf); + utp->at_string.reset (xstrdup (buf)); else if (startswith (srctype, "cond:")) - utp->cond_string = xstrdup (buf); + utp->cond_string.reset (xstrdup (buf)); else if (startswith (srctype, "cmd:")) - VEC_safe_push (char_ptr, utp->cmd_strings, xstrdup (buf)); + utp->cmd_strings.emplace_back (xstrdup (buf)); } else if (piece == 'V') { @@ -3867,9 +3569,10 @@ parse_tracepoint_definition (char *line, struct uploaded_tp **utpp) uploaded object. */ void -parse_tsv_definition (char *line, struct uploaded_tsv **utsvp) +parse_tsv_definition (const char *line, struct uploaded_tsv **utsvp) { - char *p, *buf; + const char *p; + char *buf; ULONGEST num, initval, builtin; int end; struct uploaded_tsv *utsv = NULL; @@ -3892,33 +3595,17 @@ parse_tsv_definition (char *line, struct uploaded_tsv **utsvp) utsv->name = xstrdup (buf); } -void -free_current_marker (void *arg) -{ - struct static_tracepoint_marker **marker_p - = (struct static_tracepoint_marker **) arg; - - if (*marker_p != NULL) - { - release_static_tracepoint_marker (*marker_p); - xfree (*marker_p); - } - else - *marker_p = NULL; -} - /* Given a line of text defining a static tracepoint marker, parse it into a "static tracepoint marker" object. Throws an error is parsing fails. If PP is non-null, it points to one past the end of the parsed marker definition. */ void -parse_static_tracepoint_marker_definition (char *line, char **pp, - struct static_tracepoint_marker *marker) +parse_static_tracepoint_marker_definition (const char *line, const char **pp, + static_tracepoint_marker *marker) { - char *p, *endp; + const char *p, *endp; ULONGEST addr; - int end; p = line; p = unpack_varlen_hex (p, &addr); @@ -3931,160 +3618,140 @@ parse_static_tracepoint_marker_definition (char *line, char **pp, if (endp == NULL) error (_("bad marker definition: %s"), line); - marker->str_id = (char *) xmalloc (endp - p + 1); - end = hex2bin (p, (gdb_byte *) marker->str_id, (endp - p + 1) / 2); - marker->str_id[end] = '\0'; + marker->str_id = hex2str (p, (endp - p) / 2); - p += 2 * end; - p++; /* skip a colon */ - - marker->extra = (char *) xmalloc (strlen (p) + 1); - end = hex2bin (p, (gdb_byte *) marker->extra, strlen (p) / 2); - marker->extra[end] = '\0'; + p = endp; + p++; /* skip a colon */ - if (pp) - *pp = p; -} + /* This definition may be followed by another one, separated by a comma. */ + int hex_len; + endp = strchr (p, ','); + if (endp != nullptr) + hex_len = endp - p; + else + hex_len = strlen (p); -/* Release a static tracepoint marker's contents. Note that the - object itself isn't released here. There objects are usually on - the stack. */ + marker->extra = hex2str (p, hex_len / 2); -void -release_static_tracepoint_marker (struct static_tracepoint_marker *marker) -{ - xfree (marker->str_id); - marker->str_id = NULL; + if (pp != nullptr) + *pp = p + hex_len; } /* Print MARKER to gdb_stdout. */ static void print_one_static_tracepoint_marker (int count, - struct static_tracepoint_marker *marker) + const static_tracepoint_marker &marker) { - struct command_line *l; struct symbol *sym; char wrap_indent[80]; char extra_field_indent[80]; struct ui_out *uiout = current_uiout; - struct cleanup *bkpt_chain; - VEC(breakpoint_p) *tracepoints; - - struct symtab_and_line sal; - init_sal (&sal); + symtab_and_line sal; + sal.pc = marker.address; - sal.pc = marker->address; + std::vector tracepoints + = static_tracepoints_here (marker.address); - tracepoints = static_tracepoints_here (marker->address); - - bkpt_chain = make_cleanup_ui_out_tuple_begin_end (uiout, "marker"); + ui_out_emit_tuple tuple_emitter (uiout, "marker"); /* A counter field to help readability. This is not a stable identifier! */ - ui_out_field_int (uiout, "count", count); + uiout->field_signed ("count", count); - ui_out_field_string (uiout, "marker-id", marker->str_id); + uiout->field_string ("marker-id", marker.str_id.c_str ()); - ui_out_field_fmt (uiout, "enabled", "%c", - !VEC_empty (breakpoint_p, tracepoints) ? 'y' : 'n'); - ui_out_spaces (uiout, 2); + uiout->field_fmt ("enabled", "%c", + !tracepoints.empty () ? 'y' : 'n'); + uiout->spaces (2); strcpy (wrap_indent, " "); - if (gdbarch_addr_bit (marker->gdbarch) <= 32) + if (gdbarch_addr_bit (marker.gdbarch) <= 32) strcat (wrap_indent, " "); else strcat (wrap_indent, " "); strcpy (extra_field_indent, " "); - ui_out_field_core_addr (uiout, "addr", marker->gdbarch, marker->address); + uiout->field_core_addr ("addr", marker.gdbarch, marker.address); - sal = find_pc_line (marker->address, 0); - sym = find_pc_sect_function (marker->address, NULL); + sal = find_pc_line (marker.address, 0); + sym = find_pc_sect_function (marker.address, NULL); if (sym) { - ui_out_text (uiout, "in "); - ui_out_field_string (uiout, "func", - SYMBOL_PRINT_NAME (sym)); - ui_out_wrap_hint (uiout, wrap_indent); - ui_out_text (uiout, " at "); + uiout->text ("in "); + uiout->field_string ("func", sym->print_name (), + function_name_style.style ()); + uiout->wrap_hint (wrap_indent); + uiout->text (" at "); } else - ui_out_field_skip (uiout, "func"); + uiout->field_skip ("func"); if (sal.symtab != NULL) { - ui_out_field_string (uiout, "file", - symtab_to_filename_for_display (sal.symtab)); - ui_out_text (uiout, ":"); + uiout->field_string ("file", + symtab_to_filename_for_display (sal.symtab), + file_name_style.style ()); + uiout->text (":"); - if (ui_out_is_mi_like_p (uiout)) + if (uiout->is_mi_like_p ()) { const char *fullname = symtab_to_fullname (sal.symtab); - ui_out_field_string (uiout, "fullname", fullname); + uiout->field_string ("fullname", fullname); } else - ui_out_field_skip (uiout, "fullname"); + uiout->field_skip ("fullname"); - ui_out_field_int (uiout, "line", sal.line); + uiout->field_signed ("line", sal.line); } else { - ui_out_field_skip (uiout, "fullname"); - ui_out_field_skip (uiout, "line"); + uiout->field_skip ("fullname"); + uiout->field_skip ("line"); } - ui_out_text (uiout, "\n"); - ui_out_text (uiout, extra_field_indent); - ui_out_text (uiout, _("Data: \"")); - ui_out_field_string (uiout, "extra-data", marker->extra); - ui_out_text (uiout, "\"\n"); + uiout->text ("\n"); + uiout->text (extra_field_indent); + uiout->text (_("Data: \"")); + uiout->field_string ("extra-data", marker.extra.c_str ()); + uiout->text ("\"\n"); - if (!VEC_empty (breakpoint_p, tracepoints)) + if (!tracepoints.empty ()) { - struct cleanup *cleanup_chain; int ix; - struct breakpoint *b; - cleanup_chain = make_cleanup_ui_out_tuple_begin_end (uiout, - "tracepoints-at"); - - ui_out_text (uiout, extra_field_indent); - ui_out_text (uiout, _("Probed by static tracepoints: ")); - for (ix = 0; VEC_iterate(breakpoint_p, tracepoints, ix, b); ix++) - { - if (ix > 0) - ui_out_text (uiout, ", "); - ui_out_text (uiout, "#"); - ui_out_field_int (uiout, "tracepoint-id", b->number); - } + { + ui_out_emit_tuple inner_tuple_emitter (uiout, "tracepoints-at"); - do_cleanups (cleanup_chain); + uiout->text (extra_field_indent); + uiout->text (_("Probed by static tracepoints: ")); + for (ix = 0; ix < tracepoints.size (); ix++) + { + if (ix > 0) + uiout->text (", "); + uiout->text ("#"); + uiout->field_signed ("tracepoint-id", tracepoints[ix]->number); + } + } - if (ui_out_is_mi_like_p (uiout)) - ui_out_field_int (uiout, "number-of-tracepoints", - VEC_length(breakpoint_p, tracepoints)); + if (uiout->is_mi_like_p ()) + uiout->field_signed ("number-of-tracepoints", tracepoints.size ()); else - ui_out_text (uiout, "\n"); + uiout->text ("\n"); } - VEC_free (breakpoint_p, tracepoints); - - do_cleanups (bkpt_chain); } static void -info_static_tracepoint_markers_command (char *arg, int from_tty) +info_static_tracepoint_markers_command (const char *arg, int from_tty) { - VEC(static_tracepoint_marker_p) *markers; - struct cleanup *old_chain; - struct static_tracepoint_marker *marker; struct ui_out *uiout = current_uiout; - int i; + std::vector markers + = target_static_tracepoint_markers_by_strid (NULL); /* We don't have to check target_can_use_agent and agent's capability on static tracepoint here, in order to be compatible with older GDBserver. @@ -4092,36 +3759,24 @@ info_static_tracepoint_markers_command (char *arg, int from_tty) don't work without in-process agent, so we don't bother users to type `set agent on' when to use static tracepoint. */ - old_chain - = make_cleanup_ui_out_table_begin_end (uiout, 5, -1, - "StaticTracepointMarkersTable"); + ui_out_emit_table table_emitter (uiout, 5, -1, + "StaticTracepointMarkersTable"); - ui_out_table_header (uiout, 7, ui_left, "counter", "Cnt"); + uiout->table_header (7, ui_left, "counter", "Cnt"); - ui_out_table_header (uiout, 40, ui_left, "marker-id", "ID"); + uiout->table_header (40, ui_left, "marker-id", "ID"); - ui_out_table_header (uiout, 3, ui_left, "enabled", "Enb"); + uiout->table_header (3, ui_left, "enabled", "Enb"); if (gdbarch_addr_bit (target_gdbarch ()) <= 32) - ui_out_table_header (uiout, 10, ui_left, "addr", "Address"); + uiout->table_header (10, ui_left, "addr", "Address"); else - ui_out_table_header (uiout, 18, ui_left, "addr", "Address"); - ui_out_table_header (uiout, 40, ui_noalign, "what", "What"); + uiout->table_header (18, ui_left, "addr", "Address"); + uiout->table_header (40, ui_noalign, "what", "What"); - ui_out_table_body (uiout); + uiout->table_body (); - markers = target_static_tracepoint_markers_by_strid (NULL); - make_cleanup (VEC_cleanup (static_tracepoint_marker_p), &markers); - - for (i = 0; - VEC_iterate (static_tracepoint_marker_p, - markers, i, marker); - i++) - { - print_one_static_tracepoint_marker (i + 1, marker); - release_static_tracepoint_marker (marker); - } - - do_cleanups (old_chain); + for (int i = 0; i < markers.size (); i++) + print_one_static_tracepoint_marker (i + 1, markers[i]); } /* The $_sdata convenience variable is a bit special. We don't know @@ -4138,23 +3793,19 @@ static struct value * sdata_make_value (struct gdbarch *gdbarch, struct internalvar *var, void *ignore) { - LONGEST size; - gdb_byte *buf; - /* We need to read the whole object before we know its size. */ - size = target_read_alloc (¤t_target, - TARGET_OBJECT_STATIC_TRACE_DATA, - NULL, &buf); - if (size >= 0) + gdb::optional buf + = target_read_alloc (current_top_target (), TARGET_OBJECT_STATIC_TRACE_DATA, + NULL); + if (buf) { struct value *v; struct type *type; type = init_vector_type (builtin_type (gdbarch)->builtin_true_char, - size); + buf->size ()); v = allocate_value (type); - memcpy (value_contents_raw (v), buf, size); - xfree (buf); + memcpy (value_contents_raw (v), buf->data (), buf->size ()); return v; } else @@ -4163,7 +3814,7 @@ sdata_make_value (struct gdbarch *gdbarch, struct internalvar *var, #if !defined(HAVE_LIBEXPAT) -struct traceframe_info * +struct std::unique_ptr parse_traceframe_info (const char *tframe_info) { static int have_warned; @@ -4187,19 +3838,18 @@ parse_traceframe_info (const char *tframe_info) static void traceframe_info_start_memory (struct gdb_xml_parser *parser, const struct gdb_xml_element *element, - void *user_data, VEC(gdb_xml_value_s) *attributes) + void *user_data, + std::vector &attributes) { struct traceframe_info *info = (struct traceframe_info *) user_data; - struct mem_range *r = VEC_safe_push (mem_range_s, info->memory, NULL); ULONGEST *start_p, *length_p; start_p - = (ULONGEST *) xml_find_attribute (attributes, "start")->value; + = (ULONGEST *) xml_find_attribute (attributes, "start")->value.get (); length_p - = (ULONGEST *) xml_find_attribute (attributes, "length")->value; + = (ULONGEST *) xml_find_attribute (attributes, "length")->value.get (); - r->start = *start_p; - r->length = *length_p; + info->memory.emplace_back (*start_p, *length_p); } /* Handle the start of a element. */ @@ -4208,24 +3858,14 @@ static void traceframe_info_start_tvar (struct gdb_xml_parser *parser, const struct gdb_xml_element *element, void *user_data, - VEC(gdb_xml_value_s) *attributes) + std::vector &attributes) { struct traceframe_info *info = (struct traceframe_info *) user_data; const char *id_attrib - = (const char *) xml_find_attribute (attributes, "id")->value; + = (const char *) xml_find_attribute (attributes, "id")->value.get (); int id = gdb_xml_parse_ulongest (parser, id_attrib); - VEC_safe_push (int, info->tvars, id); -} - -/* Discard the constructed trace frame info (if an error occurs). */ - -static void -free_result (void *p) -{ - struct traceframe_info *result = (struct traceframe_info *) p; - - free_traceframe_info (result); + info->tvars.push_back (id); } /* The allowed elements and attributes for an XML memory map. */ @@ -4259,26 +3899,16 @@ static const struct gdb_xml_element traceframe_info_elements[] = { /* Parse a traceframe-info XML document. */ -struct traceframe_info * +traceframe_info_up parse_traceframe_info (const char *tframe_info) { - struct traceframe_info *result; - struct cleanup *back_to; - - result = XCNEW (struct traceframe_info); - back_to = make_cleanup (free_result, result); + traceframe_info_up result (new traceframe_info); if (gdb_xml_parse_quick (_("trace frame info"), "traceframe-info.dtd", traceframe_info_elements, - tframe_info, result) == 0) - { - /* Parsed successfully, keep the result. */ - discard_cleanups (back_to); + tframe_info, result.get ()) == 0) + return result; - return result; - } - - do_cleanups (back_to); return NULL; } @@ -4291,10 +3921,10 @@ parse_traceframe_info (const char *tframe_info) struct traceframe_info * get_traceframe_info (void) { - if (traceframe_info == NULL) - traceframe_info = target_traceframe_info (); + if (current_traceframe_info == NULL) + current_traceframe_info = target_traceframe_info (); - return traceframe_info; + return current_traceframe_info.get (); } /* If the target supports the query, return in RESULT the set of @@ -4304,37 +3934,33 @@ get_traceframe_info (void) undefined. */ int -traceframe_available_memory (VEC(mem_range_s) **result, +traceframe_available_memory (std::vector *result, CORE_ADDR memaddr, ULONGEST len) { struct traceframe_info *info = get_traceframe_info (); if (info != NULL) { - struct mem_range *r; - int i; + result->clear (); - *result = NULL; - - for (i = 0; VEC_iterate (mem_range_s, info->memory, i, r); i++) - if (mem_ranges_overlap (r->start, r->length, memaddr, len)) + for (mem_range &r : info->memory) + if (mem_ranges_overlap (r.start, r.length, memaddr, len)) { ULONGEST lo1, hi1, lo2, hi2; - struct mem_range *nr; lo1 = memaddr; hi1 = memaddr + len; - lo2 = r->start; - hi2 = r->start + r->length; + lo2 = r.start; + hi2 = r.start + r.length; - nr = VEC_safe_push (mem_range_s, *result, NULL); + CORE_ADDR start = std::max (lo1, lo2); + int length = std::min (hi1, hi2) - start; - nr->start = max (lo1, lo2); - nr->length = min (hi1, hi2) - nr->start; + result->emplace_back (start, length); } - normalize_mem_ranges (*result); + normalize_mem_ranges (result); return 1; } @@ -4350,6 +3976,9 @@ static const struct internalvar_funcs sdata_funcs = NULL }; +/* See tracepoint.h. */ +cmd_list_element *while_stepping_cmd_element = nullptr; + /* module initialization */ void _initialize_tracepoint (void) @@ -4365,14 +3994,14 @@ _initialize_tracepoint (void) traceframe_number = -1; tracepoint_number = -1; - add_info ("scope", scope_info, - _("List the variables local to a scope")); + add_info ("scope", info_scope_command, + _("List the variables local to a scope.")); - add_cmd ("tracepoints", class_trace, NULL, + add_cmd ("tracepoints", class_trace, _("Tracing of program execution without stopping the program."), &cmdlist); - add_com ("tdump", class_trace, trace_dump_command, + add_com ("tdump", class_trace, tdump_command, _("Print everything collected at the current tracepoint.")); c = add_com ("tvariable", class_trace, trace_variable_command,_("\ @@ -4388,69 +4017,67 @@ Arguments are the names of the variables to delete.\n\ If no arguments are supplied, delete all variables."), &deletelist); /* FIXME add a trace variable completer. */ - add_info ("tvariables", tvariables_info, _("\ -Status of trace state variables and their values.\n\ -")); + add_info ("tvariables", info_tvariables_command, _("\ +Status of trace state variables and their values.")); add_info ("static-tracepoint-markers", info_static_tracepoint_markers_command, _("\ -List target static tracepoints markers.\n\ -")); +List target static tracepoints markers.")); - add_prefix_cmd ("tfind", class_trace, trace_find_command, _("\ -Select a trace frame;\n\ + add_prefix_cmd ("tfind", class_trace, tfind_command, _("\ +Select a trace frame.\n\ No argument means forward by one frame; '-' means backward by one frame."), &tfindlist, "tfind ", 1, &cmdlist); - add_cmd ("outside", class_trace, trace_find_outside_command, _("\ + add_cmd ("outside", class_trace, tfind_outside_command, _("\ Select a trace frame whose PC is outside the given range (exclusive).\n\ -Usage: tfind outside addr1, addr2"), +Usage: tfind outside ADDR1, ADDR2"), &tfindlist); - add_cmd ("range", class_trace, trace_find_range_command, _("\ + add_cmd ("range", class_trace, tfind_range_command, _("\ Select a trace frame whose PC is in the given range (inclusive).\n\ -Usage: tfind range addr1,addr2"), +Usage: tfind range ADDR1, ADDR2"), &tfindlist); - add_cmd ("line", class_trace, trace_find_line_command, _("\ + add_cmd ("line", class_trace, tfind_line_command, _("\ Select a trace frame by source line.\n\ Argument can be a line number (with optional source file),\n\ a function name, or '*' followed by an address.\n\ Default argument is 'the next source line that was traced'."), &tfindlist); - add_cmd ("tracepoint", class_trace, trace_find_tracepoint_command, _("\ + add_cmd ("tracepoint", class_trace, tfind_tracepoint_command, _("\ Select a trace frame by tracepoint number.\n\ Default is the tracepoint for the current trace frame."), &tfindlist); - add_cmd ("pc", class_trace, trace_find_pc_command, _("\ + add_cmd ("pc", class_trace, tfind_pc_command, _("\ Select a trace frame by PC.\n\ Default is the current PC, or the PC of the current trace frame."), &tfindlist); - add_cmd ("end", class_trace, trace_find_end_command, _("\ + add_cmd ("end", class_trace, tfind_end_command, _("\ De-select any trace frame and resume 'live' debugging."), &tfindlist); add_alias_cmd ("none", "end", class_trace, 0, &tfindlist); - add_cmd ("start", class_trace, trace_find_start_command, + add_cmd ("start", class_trace, tfind_start_command, _("Select the first trace frame in the trace buffer."), &tfindlist); - add_com ("tstatus", class_trace, trace_status_command, + add_com ("tstatus", class_trace, tstatus_command, _("Display the status of the current trace data collection.")); - add_com ("tstop", class_trace, trace_stop_command, _("\ + add_com ("tstop", class_trace, tstop_command, _("\ Stop trace data collection.\n\ -Usage: tstop [ ... ]\n\ +Usage: tstop [NOTES]...\n\ Any arguments supplied are recorded with the trace as a stop reason and\n\ reported by tstatus (if the target supports trace notes).")); - add_com ("tstart", class_trace, trace_start_command, _("\ + add_com ("tstart", class_trace, tstart_command, _("\ Start trace data collection.\n\ -Usage: tstart [ ... ]\n\ +Usage: tstart [NOTES]...\n\ Any arguments supplied are recorded with the trace as a note and\n\ reported by tstatus (if the target supports trace notes).")); @@ -4461,7 +4088,8 @@ Entering \"end\" on a line by itself is the normal way to terminate\n\ such a list.\n\n\ Note: the \"end\" command cannot be used at the gdb prompt.")); - add_com ("while-stepping", class_trace, while_stepping_pseudocommand, _("\ + while_stepping_cmd_element = add_com ("while-stepping", class_trace, + while_stepping_pseudocommand, _("\ Specify single-stepping behavior at a tracepoint.\n\ Argument is number of instructions to trace in single-step mode\n\ following the tracepoint. This command is normally followed by\n\ @@ -4489,7 +4117,7 @@ Accepts a comma-separated list of (one or more) expressions.\n\ The result of each evaluation will be discarded.\n\ Note: this command can only be used in a tracepoint \"actions\" list.")); - add_com ("actions", class_trace, trace_actions_command, _("\ + add_com ("actions", class_trace, actions_command, _("\ Specify the actions to be taken at a tracepoint.\n\ Tracepoint actions may include collecting of specified data,\n\ single-stepping, or enabling/disabling other tracepoints,\n\ @@ -4498,8 +4126,8 @@ depending on target's capabilities.")); default_collect = xstrdup (""); add_setshow_string_cmd ("default-collect", class_trace, &default_collect, _("\ -Set the list of expressions to collect by default"), _("\ -Show the list of expressions to collect by default"), NULL, +Set the list of expressions to collect by default."), _("\ +Show the list of expressions to collect by default."), NULL, NULL, NULL, &setlist, &showlist); @@ -4539,22 +4167,22 @@ disables any attempt to set the buffer size and lets the target choose."), add_setshow_string_cmd ("trace-user", class_trace, &trace_user, _("\ -Set the user name to use for current and future trace runs"), _("\ -Show the user name to use for current and future trace runs"), NULL, +Set the user name to use for current and future trace runs."), _("\ +Show the user name to use for current and future trace runs."), NULL, set_trace_user, NULL, &setlist, &showlist); add_setshow_string_cmd ("trace-notes", class_trace, &trace_notes, _("\ -Set notes string to use for current and future trace runs"), _("\ -Show the notes string to use for current and future trace runs"), NULL, +Set notes string to use for current and future trace runs."), _("\ +Show the notes string to use for current and future trace runs."), NULL, set_trace_notes, NULL, &setlist, &showlist); add_setshow_string_cmd ("trace-stop-notes", class_trace, &trace_stop_notes, _("\ -Set notes string to use for future tstop commands"), _("\ -Show the notes string to use for future tstop commands"), NULL, +Set notes string to use for future tstop commands."), _("\ +Show the notes string to use for future tstop commands."), NULL, set_trace_stop_notes, NULL, &setlist, &showlist); }