/* Tracing functionality for remote targets in custom GDB protocol
- Copyright (C) 1997-2019 Free Software Foundation, Inc.
+ Copyright (C) 1997-2021 Free Software Foundation, Inc.
This file is part of GDB.
#include "memrange.h"
#include "cli/cli-utils.h"
#include "probe.h"
-#include "ctf.h"
-#include "common/filestuff.h"
-#include "common/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 <unistd.h>
/* List of expressions to collect by default at each tracepoint hit. */
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. */
/* Textual notes applying to the current and/or future trace runs. */
-char *trace_user = NULL;
+static char *trace_user = NULL;
/* Textual notes applying to the current and/or future trace runs. */
-char *trace_notes = NULL;
+static char *trace_notes = NULL;
/* Textual notes applying to the stopping of a trace. */
-char *trace_stop_notes = NULL;
+static char *trace_stop_notes = NULL;
/* support routines */
/* 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. */
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 ())
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>";
+ {
+ /* 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>";
+ {
+ /* It is not meaningful to ask about the value. */
+ c = "<undefined>";
+ style = metadata_style.style ();
+ }
if (c)
- uiout->field_string ("current", c);
+ uiout->field_string ("current", c, style);
uiout->text ("\n");
}
}
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);
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 ());
}
}
{
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, scope);
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));
+ 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_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, scope);
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, scope);
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, scope);
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:
if (!aexpr)
{
printf_filtered ("%s has been optimized out of existence.\n",
- SYMBOL_PRINT_NAME (sym));
+ sym->print_name ());
return;
}
}
{
- 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);
}
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);
{
unsigned long addr;
+ 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));
}
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),
- tloc->address);
- 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;
- const char *name = 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,
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 */
{
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
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
{
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, "-"))
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. */
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");
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);
/* 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.c_str ());
if (sym)
{
uiout->text ("in ");
- uiout->field_string ("func", SYMBOL_PRINT_NAME (sym),
- ui_out_style_kind::FUNCTION);
+ uiout->field_string ("func", sym->print_name (),
+ function_name_style.style ());
uiout->wrap_hint (wrap_indent);
uiout->text (" at ");
}
{
uiout->field_string ("file",
symtab_to_filename_for_display (sal.symtab),
- ui_out_style_kind::FILE);
+ 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
{
if (ix > 0)
uiout->text (", ");
uiout->text ("#");
- uiout->field_int ("tracepoint-id", tracepoints[ix]->number);
+ uiout->field_signed ("tracepoint-id", tracepoints[ix]->number);
}
}
if (uiout->is_mi_like_p ())
- uiout->field_int ("number-of-tracepoints", tracepoints.size ());
+ uiout->field_signed ("number-of-tracepoints", tracepoints.size ());
else
uiout->text ("\n");
}
{
/* We need to read the whole object before we know its size. */
gdb::optional<gdb::byte_vector> buf
- = target_read_alloc (current_top_target (), TARGET_OBJECT_STATIC_TRACE_DATA,
+ = target_read_alloc (current_inferior ()->top_target (),
+ TARGET_OBJECT_STATIC_TRACE_DATA,
NULL);
if (buf)
{
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."),
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\
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", class_trace, 0);
+ add_com_alias ("stepping", "while-stepping", class_trace, 0);
add_com ("collect", class_trace, collect_pseudocommand, _("\
Specify one or more data items to be collected at a tracepoint.\n\
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);
}