/* Tracing functionality for remote targets in custom GDB protocol
- Copyright (C) 1997-2017 Free Software Foundation, Inc.
+ Copyright (C) 1997-2018 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"
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;
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. */
for (ix = 0; VEC_iterate (tsv_s, tvariables, ix, tsv); ++ix)
if (strcmp (name, tsv->name) == 0)
{
- observer_notify_tsv_deleted (tsv);
+ gdb::observers::tsv_deleted.notify (tsv);
xfree ((void *)tsv->name);
VEC_unordered_remove (tsv_s, tvariables, ix);
evaluate into an initial value. */
static void
-trace_variable_command (char *args, int from_tty)
+trace_variable_command (const char *args, int from_tty)
{
LONGEST initval = 0;
struct trace_state_variable *tsv;
- char *name_start, *p;
+ const char *name_start, *p;
if (!args || !*args)
error_no_arg (_("Syntax is $NAME [ = EXPR ]"));
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 = 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"),
if (query (_("Delete all trace state variables? ")))
VEC_free (tsv_s, tvariables);
dont_repeat ();
- observer_notify_tsv_deleted (NULL);
+ gdb::observers::tsv_deleted.notify (NULL);
return;
}
/* 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 ();
}
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;
/* Reduce a collection list to string form (for gdb protocol). */
-char **
+std::vector<std::string>
collection_list::stringify ()
{
char 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)
{
printf_filtered ("\nCollecting static trace data\n");
end = temp_buf;
*end++ = 'L';
- (*str_list)[ndx] = savestring (temp_buf, end - temp_buf);
- ndx++;
+ str_list.emplace_back (temp_buf, end - temp_buf);
}
for (i = sizeof (m_regs_mask) - 1; i > 0; i--)
sprintf (end, "%02X", m_regs_mask[i]);
end += 2;
}
- (*str_list)[ndx] = xstrdup (temp_buf);
- ndx++;
+ str_list.emplace_back (temp_buf);
}
if (info_verbose)
printf_filtered ("\n");
}
if (count + 27 > MAX_AGENT_EXPR_LEN)
{
- (*str_list)[ndx] = savestring (temp_buf, count);
- ndx++;
+ str_list.emplace_back (temp_buf, count);
count = 0;
end = temp_buf;
}
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, count);
count = 0;
end = temp_buf;
}
if (count != 0)
{
- (*str_list)[ndx] = savestring (temp_buf, count);
- ndx++;
+ str_list.emplace_back (temp_buf, count);
count = 0;
end = temp_buf;
}
- (*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. */
/* 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 ();
}
void
-start_tracing (char *notes)
+start_tracing (const char *notes)
{
VEC(breakpoint_p) *tp_vec = NULL;
int ix;
t->number_on_target = b->number;
for (loc = b->loc; loc; loc = loc->next)
- if (loc->probe.probe != NULL
- && loc->probe.probe->pops->set_semaphore != NULL)
- loc->probe.probe->pops->set_semaphore (loc->probe.probe,
- loc->probe.objfile,
- loc->gdbarch);
+ if (loc->probe.prob != NULL)
+ loc->probe.prob->set_semaphore (loc->probe.objfile,
+ loc->gdbarch);
if (bp_location_downloaded)
- observer_notify_breakpoint_modified (b);
+ gdb::observers::breakpoint_modified.notify (b);
}
VEC_free (breakpoint_p, tp_vec);
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;
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);
}
}
/* 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;
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);
}
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 */
/* info scope command: list the locals for a scope. */
static void
-info_scope_command (char *args_in, int from_tty)
+info_scope_command (const char *args_in, int from_tty)
{
struct symbol *sym;
struct bound_minimal_symbol msym;
/* 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;
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;
}
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;
}
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;
/* 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);
+ gdb::observers::breakpoint_modified.notify (b);
VEC_free (breakpoint_p, modified_tp);
free_uploaded_tps (uploaded_tps);
std::string buf;
int try_num = 0;
struct trace_state_variable *tsv;
- struct cleanup *old_chain;
if (utsv->name)
{
tsv->initial_value = utsv->initial_value;
tsv->builtin = utsv->builtin;
- observer_notify_tsv_created (tsv);
+ gdb::observers::tsv_created.notify (tsv);
return tsv;
}
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
void
parse_static_tracepoint_marker_definition (const char *line, const char **pp,
- struct static_tracepoint_marker *marker)
+ static_tracepoint_marker *marker)
{
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;
VEC(breakpoint_p) *tracepoints;
symtab_and_line sal;
- sal.pc = marker->address;
+ sal.pc = marker.address;
- tracepoints = static_tracepoints_here (marker->address);
+ tracepoints = static_tracepoints_here (marker.address);
ui_out_emit_tuple tuple_emitter (uiout, "marker");
identifier! */
uiout->field_int ("count", count);
- uiout->field_string ("marker-id", marker->str_id);
+ uiout->field_string ("marker-id", marker.str_id.c_str ());
uiout->field_fmt ("enabled", "%c",
!VEC_empty (breakpoint_p, tracepoints) ? 'y' : 'n');
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->text ("\n");
uiout->text (extra_field_indent);
uiout->text (_("Data: \""));
- uiout->field_string ("extra-data", marker->extra);
+ uiout->field_string ("extra-data", marker.extra.c_str ());
uiout->text ("\"\n");
if (!VEC_empty (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
#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);
+ tframe_info, result.get ()) == 0)
+ return result;
- 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 = NULL;
+ result->clear ();
- 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;
}