/* Tracing functionality for remote targets in custom GDB protocol
- Copyright (C) 1997-2017 Free Software Foundation, Inc.
+ Copyright (C) 1997-2022 Free Software Foundation, Inc.
This file is part of GDB.
#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"
#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"
#include <algorithm>
-
-/* readline include files */
-#include "readline/readline.h"
-#include "readline/history.h"
-
-/* readline defines this. */
-#undef savestring
+#include "cli/cli-style.h"
+#include "expop.h"
+#include "gdbsupport/buildargv.h"
#include <unistd.h>
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<trace_state_variable> tvariables;
/* The next integer to assign to a variable. */
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;
+std::string 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. */
/* Textual notes applying to the current and/or future trace runs. */
-char *trace_user = NULL;
+static std::string trace_user;
/* Textual notes applying to the current and/or future trace runs. */
-char *trace_notes = NULL;
+static std::string trace_notes;
/* Textual notes applying to the stopping of a trace. */
-char *trace_stop_notes = NULL;
-
-/* ======= Important command functions: ======= */
-static void actions_command (char *, int);
-static void tstart_command (char *, int);
-static void tstop_command (char *, int);
-static void tstatus_command (char *, int);
-static void tfind_pc_command (char *, int);
-static void tfind_tracepoint_command (char *, int);
-static void tfind_line_command (char *, int);
-static void tfind_range_command (char *, int);
-static void tfind_outside_command (char *, int);
-static void tdump_command (char *, int);
+static std::string trace_stop_notes;
/* support routines */
struct collection_list;
static char *mem2hex (gdb_byte *, char *, int);
-static struct command_line *
- all_tracepoint_actions_and_cleanup (struct breakpoint *t);
+static counted_command_line all_tracepoint_actions (struct breakpoint *);
static struct trace_status trace_status;
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. */
/* 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. */
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. */
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;
}
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;
}
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;
}
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 ]"));
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)
{
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;
}
void
tvariables_info_1 (void)
{
- struct trace_state_variable *tsv;
- int ix;
- int count = 0;
struct ui_out *uiout = current_uiout;
- if (VEC_length (tsv_s, tvariables) == 0 && !uiout->is_mi_like_p ())
- {
- 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);
- ui_out_emit_table table_emitter (uiout, 3, count, "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_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");
- uiout->table_body ();
+ uiout->table_body ();
- for (ix = 0; VEC_iterate (tsv_s, tvariables, ix, tsv); ++ix)
- {
- const char *c;
-
- ui_out_emit_tuple tuple_emitter (uiout, "variable");
-
- std::string name = std::string ("$") + tsv->name;
- uiout->field_string ("name", name.c_str ());
- uiout->field_string ("initial", plongest (tsv->initial_value));
-
- 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 = "<unknown>";
- else
- /* It is not meaningful to ask about the value. */
- c = "<undefined>";
- if (c)
- uiout->field_string ("current", c);
- uiout->text ("\n");
- }
+ 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 = "<unknown>";
+ style = metadata_style.style ();
+ }
+ else
+ {
+ /* It is not meaningful to ask about the value. */
+ c = "<undefined>";
+ style = metadata_style.style ();
+ }
+ if (c)
+ uiout->field_string ("current", c, style);
+ uiout->text ("\n");
+ }
+ }
+
+ if (tvariables.empty ())
+ uiout->text (_("No trace state variables.\n"));
}
/* List all the trace state variables. */
static void
-info_tvariables_command (char *args, int from_tty)
+info_tvariables_command (const char *args, int from_tty)
{
tvariables_info_1 ();
}
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");
}
}
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."));
}
/* Enter a list of actions for a tracepoint. */
static void
-actions_command (char *args, int from_tty)
+actions_command (const char *args, int from_tty)
{
struct tracepoint *t;
string_printf ("Enter actions for tracepoint %d, one per line.",
t->number);
- command_line_up l = read_command_lines (&tmpbuf[0], from_tty, 1,
- check_tracepoint_command, t);
+ 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 */
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 cleanup *old_chain = NULL;
const char *tmp_p;
const char *p;
- struct bp_location *loc;
struct tracepoint *t = (struct tracepoint *) b;
/* If EOF is typed, *line is NULL. */
if (*p == '#') /* comment line */
return;
- c = lookup_cmd (&p, cmdlist, "", -1, 1);
+ c = lookup_cmd (&p, cmdlist, "", NULL, -1, 1);
if (c == 0)
error (_("`%s' is not a tracepoint action, or is ambiguous."), p);
- if (cmd_cfunc_eq (c, collect_pseudocommand))
+ if (cmd_simple_func_eq (c, collect_pseudocommand))
{
int trace_string = 0;
/* else fall thru, treat p as an expression and parse it! */
}
tmp_p = p;
- for (loc = t->loc; loc; loc = loc->next)
+ for (bp_location *loc : t->locations ())
{
p = tmp_p;
expression_up exp = parse_exp_1 (&p, loc->address,
block_for_pc (loc->address), 1);
- if (exp->elts[0].opcode == OP_VAR_VALUE)
+ if (exp->first_opcode () == OP_VAR_VALUE)
{
- if (SYMBOL_CLASS (exp->elts[2].symbol) == LOC_CONST)
+ symbol *sym;
+ expr::var_value_operation *vvop
+ = (dynamic_cast<expr::var_value_operation *>
+ (exp->op.get ()));
+ sym = vvop->get_symbol ();
+
+ if (SYMBOL_CLASS (sym) == LOC_CONST)
{
error (_("constant `%s' (value %s) "
"will not be collected."),
- SYMBOL_PRINT_NAME (exp->elts[2].symbol),
- plongest (SYMBOL_VALUE (exp->elts[2].symbol)));
+ sym->print_name (),
+ plongest (SYMBOL_VALUE (sym)));
}
- else if (SYMBOL_CLASS (exp->elts[2].symbol)
- == LOC_OPTIMIZED_OUT)
+ else if (SYMBOL_CLASS (sym) == LOC_OPTIMIZED_OUT)
{
error (_("`%s' is optimized away "
"and cannot be collected."),
- SYMBOL_PRINT_NAME (exp->elts[2].symbol));
+ sym->print_name ());
}
}
exp.get (),
trace_string);
- if (aexpr->len > MAX_AGENT_EXPR_LEN)
- error (_("Expression is too complicated."));
-
- ax_reqs (aexpr.get ());
-
- report_agent_reqs_errors (aexpr.get ());
+ finalize_tracepoint_aexpr (aexpr.get ());
}
}
while (p && *p++ == ',');
}
- else if (cmd_cfunc_eq (c, teval_pseudocommand))
+ else if (cmd_simple_func_eq (c, teval_pseudocommand))
{
do
{ /* Repeat over a comma-separated list. */
p = skip_spaces (p);
tmp_p = p;
- for (loc = t->loc; loc; loc = loc->next)
+ for (bp_location *loc : t->locations ())
{
p = tmp_p;
long. */
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.get ());
- report_agent_reqs_errors (aexpr.get ());
+ finalize_tracepoint_aexpr (aexpr.get ());
}
}
while (p && *p++ == ',');
}
- else if (cmd_cfunc_eq (c, while_stepping_pseudocommand))
+ else if (cmd_simple_func_eq (c, while_stepping_pseudocommand))
{
char *endp;
p = endp;
}
- else if (cmd_cfunc_eq (c, end_actions_pseudocommand))
+ else if (cmd_simple_func_eq (c, end_actions_pseudocommand))
;
else
}
}
-/* Add a register to a collection list. */
+/* Add remote register number REGNO to the collection list mask. */
void
-collection_list::add_register (unsigned int regno)
+collection_list::add_remote_register (unsigned int regno)
{
if (info_verbose)
printf_filtered ("collect register %d\n", regno);
- if (regno >= (8 * sizeof (m_regs_mask)))
- error (_("Internal: register number %d too large for tracepoint"),
- regno);
- m_regs_mask[regno / 8] |= 1 << (regno % 8);
+
+ m_regs_mask.at (regno / 8) |= 1 << (regno % 8);
+}
+
+/* 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 (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
+ {
+ 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)
+ unsigned long len, CORE_ADDR scope)
{
if (info_verbose)
printf_filtered ("(%d,%s,%ld)\n", type, paddress (gdbarch, base), len);
m_memranges.emplace_back (type, base, base + len);
if (type != memrange_absolute) /* Better collect the base register! */
- add_register (type);
+ add_local_register (gdbarch, type, scope);
}
/* Add a symbol to a collection list. */
{
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)
{
printf_filtered ("LOC_STATIC %s: collect %ld bytes at %s.\n",
- SYMBOL_PRINT_NAME (sym), len,
+ 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)
+ if (SYMBOL_TYPE (sym)->code () == TYPE_CODE_STRUCT)
treat_as_expr = 1;
else
- add_memrange (gdbarch, 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 (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 &&
+ if (SYMBOL_TYPE (sym)->code () == TYPE_CODE_FLT &&
len > register_size (gdbarch, reg))
- add_register (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;
if (info_verbose)
{
printf_filtered ("LOC_LOCAL %s: Collect %ld bytes at offset %s"
- " from frame ptr reg %d\n",
- SYMBOL_PRINT_NAME (sym), len,
+ " from frame ptr reg %d\n", sym->print_name (), len,
paddress (gdbarch, offset), reg);
}
- add_memrange (gdbarch, reg, offset, len);
+ add_memrange (gdbarch, reg, offset, len, scope);
break;
case LOC_REGPARM_ADDR:
reg = SYMBOL_VALUE (sym);
if (info_verbose)
{
printf_filtered ("LOC_REGPARM_ADDR %s: Collect %ld bytes at offset %s"
- " from reg %d\n",
- SYMBOL_PRINT_NAME (sym), len,
+ " from reg %d\n", sym->print_name (), len,
paddress (gdbarch, offset), reg);
}
- add_memrange (gdbarch, reg, offset, len);
+ add_memrange (gdbarch, reg, offset, len, scope);
break;
case LOC_LOCAL:
reg = frame_regno;
if (info_verbose)
{
printf_filtered ("LOC_LOCAL %s: Collect %ld bytes at offset %s"
- " from frame ptr reg %d\n",
- SYMBOL_PRINT_NAME (sym), len,
+ " from frame ptr reg %d\n", sym->print_name (), len,
paddress (gdbarch, offset), reg);
}
- add_memrange (gdbarch, reg, offset, len);
+ add_memrange (gdbarch, reg, offset, len, scope);
break;
case LOC_UNRESOLVED:
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:
/* Expressions are the most general case. */
if (treat_as_expr)
{
- struct cleanup *old_chain1 = NULL;
-
agent_expr_up aexpr = gen_trace_for_var (scope, gdbarch,
sym, trace_string);
if (!aexpr)
{
printf_filtered ("%s has been optimized out of existence.\n",
- SYMBOL_PRINT_NAME (sym));
+ sym->print_name ());
return;
}
- ax_reqs (aexpr.get ());
-
- report_agent_reqs_errors (aexpr.get ());
+ finalize_tracepoint_aexpr (aexpr.get ());
/* Take care of the registers. */
- 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_register (ndx1 * 8 + ndx2);
- }
- }
- }
+ add_ax_registers (aexpr.get ());
add_aexpr (std::move (aexpr));
}
}
collection_list::collection_list ()
- : m_regs_mask (),
- m_strace_data (false)
+ : m_strace_data (false)
{
+ int max_remote_regno = 0;
+ for (int i = 0; i < gdbarch_num_regs (target_gdbarch ()); i++)
+ {
+ int remote_regno = (gdbarch_remote_register_number
+ (target_gdbarch (), i));
+
+ if (remote_regno >= 0 && remote_regno > max_remote_regno)
+ max_remote_regno = remote_regno;
+ }
+
+ m_regs_mask.resize ((max_remote_regno / 8) + 1);
+
m_memranges.reserve (128);
m_aexprs.reserve (128);
}
/* Reduce a collection list to string form (for gdb protocol). */
-char **
+std::vector<std::string>
collection_list::stringify ()
{
- char temp_buf[2048];
+ gdb::char_vector temp_buf (2048);
+
int count;
- int ndx = 0;
- char *(*str_list)[];
char *end;
long i;
-
- count = 1 + 1 + m_memranges.size () + m_aexprs.size () + 1;
- str_list = (char *(*)[]) xmalloc (count * sizeof (char *));
+ std::vector<std::string> str_list;
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 (m_regs_mask) - 1; i > 0; i--)
+ for (i = m_regs_mask.size () - 1; i > 0; i--)
if (m_regs_mask[i] != 0) /* Skip leading zeroes in regs_mask. */
break;
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", m_regs_mask[i]);
- sprintf (end, "%02X", m_regs_mask[i]);
- end += 2;
+
+ 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 (!m_memranges.empty () && info_verbose)
printf_filtered ("Collecting memranges: \n");
- for (i = 0, count = 0, end = temp_buf; i < m_memranges.size (); i++)
+ for (i = 0, count = 0, end = temp_buf.data ();
+ i < m_memranges.size (); i++)
{
QUIT; /* Allow user to bail out with ^C. */
if (info_verbose)
}
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
+ 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 (m_memranges[i].type == memrange_absolute)
- sprintf (end, "M-1,%s,%lX", phex_nz (m_memranges[i].start, 0),
+ /* 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 (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", m_memranges[i].type,
+ else
+ 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 < m_aexprs.size (); i++)
QUIT; /* Allow user to bail out with ^C. */
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,", m_aexprs[i]->len);
end += 10; /* 'X' + 8 hex digits + ',' */
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. */
+/* Add the expression STR to M_COMPUTED. */
void
-collection_list::append_exp (struct expression *exp)
+collection_list::append_exp (std::string &&str)
{
- string_file tmp_stream;
-
- print_expression (exp, &tmp_stream);
-
- m_computed.push_back (std::move (tmp_stream.string ()));
+ m_computed.push_back (std::move (str));
}
void
action_exp = action->line;
action_exp = skip_spaces (action_exp);
- cmd = lookup_cmd (&action_exp, cmdlist, "", -1, 1);
+ cmd = lookup_cmd (&action_exp, cmdlist, "", NULL, -1, 1);
if (cmd == 0)
error (_("Bad action list item: %s"), action_exp);
- if (cmd_cfunc_eq (cmd, collect_pseudocommand))
+ if (cmd_simple_func_eq (cmd, collect_pseudocommand))
{
int trace_string = 0;
if (0 == strncasecmp ("$reg", action_exp, 4))
{
- for (i = 0; i < gdbarch_num_regs (target_gdbarch ()); i++)
- collect->add_register (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))
target_gdbarch (),
trace_string);
- ax_reqs (aexpr.get ());
- report_agent_reqs_errors (aexpr.get ());
+ finalize_tracepoint_aexpr (aexpr.get ());
/* take care of the registers */
- 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. */
- collect->add_register (ndx1 * 8 + ndx2);
- }
- }
- }
- }
+ collect->add_ax_registers (aexpr.get ());
collect->add_aexpr (std::move (aexpr));
action_exp = strchr (action_exp, ','); /* more? */
else
{
unsigned long addr;
- struct cleanup *old_chain1 = NULL;
+ const char *exp_start = action_exp;
expression_up exp = parse_exp_1 (&action_exp, tloc->address,
block_for_pc (tloc->address),
1);
- switch (exp->elts[0].opcode)
+ switch (exp->first_opcode ())
{
case OP_REGISTER:
{
- const char *name = &exp->elts[2].string;
+ expr::register_operation *regop
+ = (dynamic_cast<expr::register_operation *>
+ (exp->op.get ()));
+ const char *name = regop->get_name ();
i = user_reg_map_name_to_regnum (target_gdbarch (),
name, strlen (name));
name);
if (info_verbose)
printf_filtered ("OP_REGISTER: ");
- collect->add_register (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.get ());
- addr = value_address (tempval);
- /* Initialize the TYPE_LENGTH if it is a typedef. */
- check_typedef (exp->elts[1].type);
- collect->add_memrange (target_gdbarch (),
- memrange_absolute, addr,
- TYPE_LENGTH (exp->elts[1].type));
- collect->append_exp (exp.get ());
+ {
+ /* Safe because we know it's a simple expression. */
+ tempval = evaluate_expression (exp.get ());
+ addr = value_address (tempval);
+ expr::unop_memval_operation *memop
+ = (dynamic_cast<expr::unop_memval_operation *>
+ (exp->op.get ()));
+ struct type *type = memop->get_type ();
+ /* Initialize the TYPE_LENGTH if it is a typedef. */
+ check_typedef (type);
+ collect->add_memrange (target_gdbarch (),
+ memrange_absolute, addr,
+ TYPE_LENGTH (type),
+ tloc->address);
+ collect->append_exp (std::string (exp_start,
+ action_exp));
+ }
break;
case OP_VAR_VALUE:
{
- struct symbol *sym = exp->elts[2].symbol;
- char_ptr name = (char_ptr) SYMBOL_NATURAL_NAME (sym);
+ expr::var_value_operation *vvo
+ = (dynamic_cast<expr::var_value_operation *>
+ (exp->op.get ()));
+ struct symbol *sym = vvo->get_symbol ();
+ const char *name = sym->natural_name ();
- collect->collect_symbol (exp->elts[2].symbol,
+ collect->collect_symbol (sym,
target_gdbarch (),
frame_reg,
frame_offset,
exp.get (),
trace_string);
- ax_reqs (aexpr.get ());
-
- report_agent_reqs_errors (aexpr.get ());
+ finalize_tracepoint_aexpr (aexpr.get ());
/* Take care of the registers. */
- 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. */
- collect->add_register (ndx1 * 8 + ndx2);
- }
- }
- }
- }
+ collect->add_ax_registers (aexpr.get ());
collect->add_aexpr (std::move (aexpr));
- collect->append_exp (exp.get ());
+ collect->append_exp (std::string (exp_start,
+ action_exp));
break;
} /* switch */
} /* do */
}
while (action_exp && *action_exp++ == ',');
} /* if */
- else if (cmd_cfunc_eq (cmd, teval_pseudocommand))
+ else if (cmd_simple_func_eq (cmd, teval_pseudocommand))
{
do
{ /* Repeat over a comma-separated list. */
action_exp = skip_spaces (action_exp);
{
- struct cleanup *old_chain1 = NULL;
-
expression_up exp = parse_exp_1 (&action_exp, tloc->address,
block_for_pc (tloc->address),
1);
agent_expr_up aexpr = gen_eval_for_expr (tloc->address,
exp.get ());
- ax_reqs (aexpr.get ());
- report_agent_reqs_errors (aexpr.get ());
+ finalize_tracepoint_aexpr (aexpr.get ());
/* Even though we're not officially collecting, add
to the collect list anyway. */
}
while (action_exp && *action_exp++ == ',');
} /* if */
- else if (cmd_cfunc_eq (cmd, while_stepping_pseudocommand))
+ else if (cmd_simple_func_eq (cmd, while_stepping_pseudocommand))
{
/* We check against nested while-stepping when setting
breakpoint action, so no way to run into nested
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
struct collection_list *tracepoint_list,
struct collection_list *stepping_list)
{
- struct command_line *actions;
int frame_reg;
LONGEST frame_offset;
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);
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<std::string> *tdp_actions,
+ std::vector<std::string> *stepping_actions)
{
struct collection_list tracepoint_list, stepping_list;
- *tdp_actions = NULL;
- *stepping_actions = NULL;
-
encode_actions (tloc, &tracepoint_list, &stepping_list);
*tdp_actions = tracepoint_list.stringify ();
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)
{
}
else
{
- struct bp_location *loc1;
-
- for (loc1 = b->loc; loc1; loc1 = loc1->next)
+ for (bp_location *loc1 : b->locations ())
{
if (loc1->shlib_disabled)
{
break;
}
}
- VEC_free (breakpoint_p, tp_vec);
if (has_pending_p)
warning (_("Pending tracepoints will not be resolved while"
}
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 ();
+ auto tracepoint_range = 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 (tracepoint_range.begin () == tracepoint_range.end ())
+ error (_("No tracepoints defined, not starting trace"));
- for (ix = 0; VEC_iterate (breakpoint_p, tp_vec, ix, b); ix++)
+ for (breakpoint *b : tracepoint_range)
{
if (b->enable_state == bp_enabled)
any_enabled = 1;
{
/* 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 : tracepoint_range)
{
struct tracepoint *t = (struct tracepoint *) b;
- struct bp_location *loc;
int bp_location_downloaded = 0;
/* Clear `inserted' flag. */
- for (loc = b->loc; loc; loc = loc->next)
+ for (bp_location *loc : b->locations ())
loc->inserted = 0;
if ((b->type == bp_fast_tracepoint
t->number_on_target = 0;
- for (loc = b->loc; loc; loc = loc->next)
+ for (bp_location *loc : b->locations ())
{
/* Since tracepoint locations are never duplicated, `inserted'
flag should be zero. */
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);
+ for (bp_location *loc : b->locations ())
+ 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 ();
target_set_trace_buffer_size (trace_buffer_size);
if (!notes)
- notes = trace_notes;
- ret = target_set_trace_notes (trace_user, notes, NULL);
+ notes = trace_notes.c_str ();
- if (!ret && (trace_user || notes))
+ ret = target_set_trace_notes (trace_user.c_str (), notes, NULL);
+
+ if (!ret && (!trace_user.empty () || notes))
warning (_("Target does not support trace user/notes, info ignored"));
/* Now insert traps and begin collecting data. */
anybody else messing with the target. */
static void
-tstart_command (char *args, int from_tty)
+tstart_command (const char *args, int from_tty)
{
dont_repeat (); /* Like "run", dangerous to repeat accidentally. */
of the trace run's status. */
static void
-tstop_command (char *args, int from_tty)
+tstop_command (const char *args, int from_tty)
{
if (!current_trace_status ()->running)
error (_("Trace is not running."));
}
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;
-
if ((t->type == bp_fast_tracepoint
? !may_insert_fast_tracepoints
: !may_insert_tracepoints))
continue;
- for (loc = t->loc; loc; loc = loc->next)
+ for (bp_location *loc : t->locations ())
{
/* GDB can be totally absent in some disconnected trace scenarios,
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;
+ note = trace_stop_notes.c_str ();
+
ret = target_set_trace_notes (NULL, NULL, note);
if (!ret && note)
/* tstatus command */
static void
-tstatus_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);
(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
{
uiout->field_string ("stop-reason", stop_reason);
if (stopping_tracepoint != -1)
- uiout->field_int ("stopping-tracepoint",
- stopping_tracepoint);
+ uiout->field_signed ("stopping-tracepoint",
+ stopping_tracepoint);
if (ts->stop_reason == tracepoint_error)
uiout->field_string ("error-description",
ts->stop_desc);
}
if (ts->traceframe_count != -1)
- uiout->field_int ("frames", ts->traceframe_count);
+ uiout->field_signed ("frames", ts->traceframe_count);
if (ts->traceframes_created != -1)
- uiout->field_int ("frames-created", ts->traceframes_created);
+ uiout->field_signed ("frames-created", ts->traceframes_created);
if (ts->buffer_size != -1)
- uiout->field_int ("buffer-size", ts->buffer_size);
+ uiout->field_signed ("buffer-size", ts->buffer_size);
if (ts->buffer_free != -1)
- uiout->field_int ("buffer-free", ts->buffer_free);
+ uiout->field_signed ("buffer-free", ts->buffer_free);
- uiout->field_int ("disconnected", ts->disconnected_tracing);
- uiout->field_int ("circular", ts->circular_buffer);
+ uiout->field_signed ("disconnected", ts->disconnected_tracing);
+ uiout->field_signed ("circular", ts->circular_buffer);
uiout->field_string ("user-name", ts->user_name);
uiout->field_string ("notes", ts->notes);
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
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);
if (uiout->is_mi_like_p ())
{
uiout->field_string ("found", "1");
- uiout->field_int ("tracepoint", tracepoint_number);
- uiout->field_int ("traceframe", traceframe_number);
+ uiout->field_signed ("tracepoint", tracepoint_number);
+ uiout->field_signed ("traceframe", traceframe_number);
}
else
{
- printf_unfiltered (_("Found trace frame %d, tracepoint %d\n"),
- traceframe_number, tracepoint_number);
+ printf_filtered (_("Found trace frame %d, tracepoint %d\n"),
+ traceframe_number, tracepoint_number);
}
}
else
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"));
+ printf_filtered (_("No longer looking at any trace frame\n"));
else /* This case may never occur, check. */
- printf_unfiltered (_("No trace frame found\n"));
+ printf_filtered (_("No trace frame found\n"));
}
/* If we're in nonstop mode and getting out of looking at trace
enum print_what print_what;
/* NOTE: in imitation of the step command, try to determine
- whether we have made a transition from one function to
- another. If so, we'll print the "stack frame" (ie. the new
- function and it's arguments) -- otherwise we'll just show the
- new source line. */
+ whether we have made a transition from one function to
+ another. If so, we'll print the "stack frame" (ie. the new
+ function and it's arguments) -- otherwise we'll just show the
+ new source line. */
if (frame_id_eq (old_frame_id,
get_frame_id (get_current_frame ())))
{ /* TFIND with no args means find NEXT trace frame. */
if (traceframe_number == -1)
frameno = 0; /* "next" is first one. */
- else
+ else
frameno = traceframe_number + 1;
}
else if (0 == strcmp (args, "-"))
}
static void
-tfind_command (char *args, int from_tty)
+tfind_command (const char *args, int from_tty)
{
- tfind_command_1 (const_cast<char *> (args), from_tty);
+ tfind_command_1 (args, from_tty);
}
/* tfind end */
static void
-tfind_end_command (char *args, int from_tty)
+tfind_end_command (const char *args, int from_tty)
{
tfind_command_1 ("-1", from_tty);
}
/* tfind start */
static void
-tfind_start_command (char *args, int from_tty)
+tfind_start_command (const char *args, int from_tty)
{
tfind_command_1 ("0", from_tty);
}
/* tfind pc command */
static void
-tfind_pc_command (char *args, int from_tty)
+tfind_pc_command (const char *args, int from_tty)
{
CORE_ADDR pc;
/* tfind tracepoint command */
static void
-tfind_tracepoint_command (char *args, int from_tty)
+tfind_tracepoint_command (const char *args, int from_tty)
{
int tdp;
struct tracepoint *tp;
corresponding to a source line OTHER THAN THE CURRENT ONE. */
static void
-tfind_line_command (char *args, int from_tty)
+tfind_line_command (const char *args, int from_tty)
{
check_trace_running (current_trace_status ());
if (sal.line > 0 && find_line_pc_range (sal, &start_pc, &end_pc))
{
if (start_pc == end_pc)
- {
+ {
printf_filtered ("Line %d of \"%s\"",
sal.line,
symtab_to_filename_for_display (sal.symtab));
&& start_pc != end_pc)
printf_filtered ("Attempting to find line %d instead.\n",
sal.line);
- else
+ else
error (_("Cannot find a good line."));
- }
+ }
}
else
- /* Is there any case in which we get here, and have an address
- which the user would want to see? If we have debugging
- symbols and no line numbers? */
- error (_("Line number %d is out of range for \"%s\"."),
- sal.line, symtab_to_filename_for_display (sal.symtab));
+ {
+ /* Is there any case in which we get here, and have an address
+ which the user would want to see? If we have debugging
+ symbols and no line numbers? */
+ error (_("Line number %d is out of range for \"%s\"."),
+ sal.line, symtab_to_filename_for_display (sal.symtab));
+ }
/* Find within range of stated line. */
if (args && *args)
/* tfind range command */
static void
-tfind_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 <startaddr>,<endaddr>\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
/* tfind outside command */
static void
-tfind_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)
if (args == 0 || *args == 0)
{ /* XXX FIXME: what should default behavior be? */
- printf_filtered ("Usage: tfind outside <startaddr>,<endaddr>\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
/* info scope command: list the locals for a scope. */
static void
-info_scope_command (char *args, int from_tty)
+info_scope_command (const char *args_in, int from_tty)
{
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;
+ const char *args = args_in;
if (args == 0 || *args == 0)
error (_("requires an argument (function, "
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. */
if (SYMBOL_COMPUTED_OPS (sym) != NULL)
SYMBOL_COMPUTED_OPS (sym)->describe_location (sym,
- BLOCK_START (block),
+ BLOCK_ENTRY_PC (block),
gdb_stdout);
else
{
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");
printf_filtered ("optimized out.\n");
continue;
case LOC_COMPUTED:
- gdb_assert_not_reached (_("LOC_COMPUTED variable missing a method"));
+ gdb_assert_not_reached ("LOC_COMPUTED variable missing a method");
}
}
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;
action_exp = skip_spaces (action_exp);
/* The collection actions to be done while stepping are
- bracketed by the commands "while-stepping" and "end". */
+ bracketed by the commands "while-stepping" and "end". */
if (*action_exp == '#') /* comment line */
continue;
- cmd = lookup_cmd (&action_exp, cmdlist, "", -1, 1);
+ cmd = lookup_cmd (&action_exp, cmdlist, "", NULL, -1, 1);
if (cmd == 0)
error (_("Bad action list item: %s"), action_exp);
- if (cmd_cfunc_eq (cmd, while_stepping_pseudocommand))
+ if (cmd_simple_func_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))
+ else if (cmd_simple_func_eq (cmd, collect_pseudocommand))
{
/* Display the collected data.
For the trap frame, display only what was collected at
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 == '/')
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;
- }
- else
- {
- size_t len = strlen (action_exp);
-
- cmd = (char *) xrealloc (cmd, len + 1);
- memcpy (cmd, action_exp, len + 1);
+ contents = std::string (action_exp, len);
+ exp = contents.c_str ();
}
- 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);
}
}
}
get_traceframe_location (int *stepping_frame_p)
{
struct tracepoint *t;
- struct bp_location *tloc;
struct regcache *regcache;
if (tracepoint_number == -1)
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->loc; tloc; tloc = tloc->next)
+ for (bp_location *tloc : t->locations ())
if (tloc->address == regcache_read_pc (regcache))
{
*stepping_frame_p = 0;
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
validation is per-tracepoint (local var "xyz" might be valid for
one tracepoint and not another, etc), we make up the action on
the fly, and don't cache it. */
- if (*default_collect)
+ if (!default_collect.empty ())
{
- 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<char> default_collect_line
+ = xstrprintf ("collect %s", default_collect.c_str ());
+
+ validate_actionline (default_collect_line.get (), t);
+ actions.reset (new struct command_line (simple_control,
+ default_collect_line.release ()),
+ command_lines_deleter ());
}
return actions;
/* The tdump command. */
static void
-tdump_command (char *args, int from_tty)
+tdump_command (const char *args, int from_tty)
{
int stepping_frame = 0;
struct bp_location *loc;
- struct command_line *actions;
/* This throws an error is not inspecting a trace frame. */
loc = get_traceframe_location (&stepping_frame);
select_frame (get_current_frame ());
- actions = all_tracepoint_actions_and_cleanup (loc->owner);
+ counted_command_line actions = all_tracepoint_actions (loc->owner);
- trace_dump_actions (actions, 0, stepping_frame, from_tty);
+ 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
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;
- ret = target_set_trace_notes (trace_user, NULL, NULL);
+ ret = target_set_trace_notes (trace_user.c_str (), NULL, NULL);
if (!ret)
warning (_("Target does not support trace notes, user ignored"));
}
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;
- ret = target_set_trace_notes (NULL, trace_notes, NULL);
+ ret = target_set_trace_notes (NULL, trace_notes.c_str (), NULL);
if (!ret)
warning (_("Target does not support trace notes, note ignored"));
}
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;
- ret = target_set_trace_notes (NULL, NULL, trace_stop_notes);
+ ret = target_set_trace_notes (NULL, NULL, trace_stop_notes.c_str ());
if (!ret)
warning (_("Target does not support trace notes, stop note ignored"));
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. */
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;
while (*utpp)
{
next_one = (*utpp)->next;
- xfree (*utpp);
+ delete *utpp;
*utpp = next_one;
}
}
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->cond_string, utp->cond_string)
+ && cond_string_is_same (t->cond_string.get (),
+ utp->cond_string.get ())
/* FIXME also test actions. */
)
{
{
struct uploaded_tp *utp;
/* A set of tracepoints which are modified. */
- VEC(breakpoint_p) *modified_tp = NULL;
- int ix;
- struct breakpoint *b;
+ std::vector<breakpoint *> modified_tp;
/* Look for GDB tracepoints that match up with our uploaded versions. */
for (utp = *uploaded_tps; utp; utp = utp->next)
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
{
/* 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);
}
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;
}
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
{
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)
/* 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);
}
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;
}
void
-parse_tracepoint_status (char *p, struct breakpoint *bp,
+parse_tracepoint_status (const char *p, struct breakpoint *bp,
struct uploaded_tp *utp)
{
ULONGEST uval;
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;
p++; /* skip a colon */
if (piece == 'T')
{
+ gdb::unique_xmalloc_ptr<char[]> 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 == ':')
{
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;
}
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')
{
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')
{
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;
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);
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';
-
- p += 2 * end;
- p++; /* skip a colon */
+ marker->str_id = hex2str (p, (endp - p) / 2);
- 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 symbol *sym;
char wrap_indent[80];
char extra_field_indent[80];
struct ui_out *uiout = current_uiout;
- VEC(breakpoint_p) *tracepoints;
symtab_and_line sal;
- sal.pc = marker->address;
+ sal.pc = marker.address;
- tracepoints = static_tracepoints_here (marker->address);
+ std::vector<breakpoint *> tracepoints
+ = static_tracepoints_here (marker.address);
ui_out_emit_tuple tuple_emitter (uiout, "marker");
/* A counter field to help readability. This is not a stable
identifier! */
- uiout->field_int ("count", count);
+ uiout->field_signed ("count", count);
- uiout->field_string ("marker-id", marker->str_id);
+ uiout->field_string ("marker-id", marker.str_id);
uiout->field_fmt ("enabled", "%c",
- !VEC_empty (breakpoint_p, tracepoints) ? 'y' : 'n');
+ !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, " ");
- uiout->field_core_addr ("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)
{
uiout->text ("in ");
- uiout->field_string ("func",
- SYMBOL_PRINT_NAME (sym));
+ uiout->field_string ("func", sym->print_name (),
+ function_name_style.style ());
uiout->wrap_hint (wrap_indent);
uiout->text (" at ");
}
if (sal.symtab != NULL)
{
uiout->field_string ("file",
- symtab_to_filename_for_display (sal.symtab));
+ symtab_to_filename_for_display (sal.symtab),
+ file_name_style.style ());
uiout->text (":");
if (uiout->is_mi_like_p ())
else
uiout->field_skip ("fullname");
- uiout->field_int ("line", sal.line);
+ uiout->field_signed ("line", sal.line);
}
else
{
uiout->text ("\n");
uiout->text (extra_field_indent);
uiout->text (_("Data: \""));
- uiout->field_string ("extra-data", marker->extra);
+ uiout->field_string ("extra-data", marker.extra);
uiout->text ("\"\n");
- if (!VEC_empty (breakpoint_p, tracepoints))
+ if (!tracepoints.empty ())
{
int ix;
- struct breakpoint *b;
{
- ui_out_emit_tuple tuple_emitter (uiout, "tracepoints-at");
+ ui_out_emit_tuple inner_tuple_emitter (uiout, "tracepoints-at");
uiout->text (extra_field_indent);
uiout->text (_("Probed by static tracepoints: "));
- for (ix = 0; VEC_iterate(breakpoint_p, tracepoints, ix, b); ix++)
+ for (ix = 0; ix < tracepoints.size (); ix++)
{
if (ix > 0)
uiout->text (", ");
uiout->text ("#");
- uiout->field_int ("tracepoint-id", b->number);
+ uiout->field_signed ("tracepoint-id", tracepoints[ix]->number);
}
}
if (uiout->is_mi_like_p ())
- uiout->field_int ("number-of-tracepoints",
- VEC_length(breakpoint_p, tracepoints));
+ uiout->field_signed ("number-of-tracepoints", tracepoints.size ());
else
uiout->text ("\n");
}
- VEC_free (breakpoint_p, tracepoints);
}
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<static_tracepoint_marker> 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.
uiout->table_body ();
- markers = target_static_tracepoint_markers_by_strid (NULL);
- old_chain = 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
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<gdb::byte_vector> buf
+ = target_read_alloc (current_inferior ()->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).data (), buf->data (), buf->size ());
return v;
}
else
#if !defined(HAVE_LIBEXPAT)
-struct traceframe_info *
+struct std::unique_ptr<traceframe_info>
parse_traceframe_info (const char *tframe_info)
{
static int have_warned;
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<gdb_xml_value> &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 <tvar> element. */
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<gdb_xml_value> &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. */
/* 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);
-
- return result;
- }
+ tframe_info, result.get ()) == 0)
+ return result;
- do_cleanups (back_to);
return NULL;
}
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
undefined. */
int
-traceframe_available_memory (VEC(mem_range_s) **result,
+traceframe_available_memory (std::vector<mem_range> *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 = std::max (lo1, lo2);
- nr->length = std::min (hi1, hi2) - nr->start;
+ result->emplace_back (start, length);
}
- normalize_mem_ranges (*result);
+ normalize_mem_ranges (result);
return 1;
}
NULL
};
+/* See tracepoint.h. */
+cmd_list_element *while_stepping_cmd_element = nullptr;
+
/* module initialization */
+void _initialize_tracepoint ();
void
-_initialize_tracepoint (void)
+_initialize_tracepoint ()
{
struct cmd_list_element *c;
tracepoint_number = -1;
add_info ("scope", info_scope_command,
- _("List the variables local to a scope"));
+ _("List the variables local to a scope."));
add_cmd ("tracepoints", class_trace,
_("Tracing of program execution without stopping the program."),
/* FIXME add a trace variable completer. */
add_info ("tvariables", info_tvariables_command, _("\
-Status of trace state variables and their values.\n\
-"));
+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, tfind_command, _("\
-Select a trace frame;\n\
+Select a trace frame.\n\
No argument means forward by one frame; '-' means backward by one frame."),
- &tfindlist, "tfind ", 1, &cmdlist);
+ &tfindlist, 1, &cmdlist);
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, 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, tfind_line_command, _("\
Default is the current PC, or the PC of the current trace frame."),
&tfindlist);
- add_cmd ("end", class_trace, tfind_end_command, _("\
-De-select any trace frame and resume 'live' debugging."),
- &tfindlist);
+ cmd_list_element *tfind_end_cmd
+ = 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_alias_cmd ("none", tfind_end_cmd, class_trace, 0, &tfindlist);
add_cmd ("start", class_trace, tfind_start_command,
_("Select the first trace frame in the trace buffer."),
add_com ("tstop", class_trace, tstop_command, _("\
Stop trace data collection.\n\
-Usage: tstop [ <notes> ... ]\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, tstart_command, _("\
Start trace data collection.\n\
-Usage: tstart [ <notes> ... ]\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)."));
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\
while single-stepping.\n\n\
Note: this command can only be used in a tracepoint \"actions\" list."));
- add_com_alias ("ws", "while-stepping", class_alias, 0);
- add_com_alias ("stepping", "while-stepping", class_alias, 0);
+ add_com_alias ("ws", while_stepping_cmd_element, class_trace, 0);
+ add_com_alias ("stepping", while_stepping_cmd_element, class_trace, 0);
add_com ("collect", class_trace, collect_pseudocommand, _("\
Specify one or more data items to be collected at a tracepoint.\n\
single-stepping, or enabling/disabling other tracepoints,\n\
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);
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);
}