X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=gdb%2Ftracepoint.c;h=075bd4c977b75a1463530bcccc47e3e15487c34b;hb=381befeedf9316991d47f4213850545a96593d23;hp=7e173ce75df269d769337b0d2d7d6564143e3a80;hpb=c252925ccc8c3c2ce2a65d12a50acfee53914ce3;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/tracepoint.c b/gdb/tracepoint.c index 7e173ce75d..075bd4c977 100644 --- a/gdb/tracepoint.c +++ b/gdb/tracepoint.c @@ -1,6 +1,6 @@ /* Tracing functionality for remote targets in custom GDB protocol - Copyright (C) 1997-2018 Free Software Foundation, Inc. + Copyright (C) 1997-2019 Free Software Foundation, Inc. This file is part of GDB. @@ -52,8 +52,8 @@ #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 @@ -167,8 +167,7 @@ char *trace_stop_notes = NULL; 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; @@ -420,51 +419,50 @@ tvariables_info_1 (void) { struct ui_out *uiout = current_uiout; - if (tvariables.empty () && !uiout->is_mi_like_p ()) - { - printf_filtered (_("No trace state variables.\n")); - return; - } - /* Try to acquire values from the target. */ 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, tvariables.size (), - "trace-variables"); - uiout->table_header (15, ui_left, "name", "Name"); - uiout->table_header (11, ui_left, "initial", "Initial"); - uiout->table_header (11, ui_left, "current", "Current"); + { + ui_out_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 (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)); - - 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 = ""; - else - /* It is not meaningful to ask about the value. */ - c = ""; - 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)); + + 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 = ""; + else + /* It is not meaningful to ask about the value. */ + c = ""; + if (c) + uiout->field_string ("current", c); + uiout->text ("\n"); + } + } + + if (tvariables.empty ()) + uiout->text (_("No trace state variables.\n")); } /* List all the trace state variables. */ @@ -579,8 +577,12 @@ actions_command (const char *args, int from_tty) 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 */ @@ -613,6 +615,19 @@ report_agent_reqs_errors (struct agent_expr *aexpr) error (_("Expression is too complicated.")); } +/* Call ax_reqs on AEXPR and raise an error if something is wrong. */ + +static void +finalize_tracepoint_aexpr (struct agent_expr *aexpr) +{ + ax_reqs (aexpr); + + if (aexpr->len > MAX_AGENT_EXPR_LEN) + error (_("Expression is too complicated.")); + + report_agent_reqs_errors (aexpr); +} + /* worker function */ void validate_actionline (const char *line, struct breakpoint *b) @@ -697,12 +712,7 @@ validate_actionline (const char *line, struct breakpoint *b) 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++ == ','); @@ -729,11 +739,7 @@ validate_actionline (const char *line, struct breakpoint *b) 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++ == ','); @@ -809,17 +815,77 @@ memrange_sortmerge (std::vector &memranges) } } -/* 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. */ @@ -827,7 +893,7 @@ collection_list::add_register (unsigned int regno) 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); @@ -838,7 +904,7 @@ collection_list::add_memrange (struct gdbarch *gdbarch, 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. */ @@ -880,19 +946,19 @@ collection_list::collect_symbol (struct symbol *sym, if (TYPE_CODE (SYMBOL_TYPE (sym)) == 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); + add_local_register (gdbarch, reg, scope); /* Check for doubles stored in two registers. */ /* FIXME: how about larger types stored in 3 or more regs? */ if (TYPE_CODE (SYMBOL_TYPE (sym)) == TYPE_CODE_FLT && len > register_size (gdbarch, reg)) - add_register (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"); @@ -909,7 +975,7 @@ collection_list::collect_symbol (struct symbol *sym, SYMBOL_PRINT_NAME (sym), 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); @@ -921,7 +987,7 @@ collection_list::collect_symbol (struct symbol *sym, SYMBOL_PRINT_NAME (sym), 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; @@ -933,7 +999,7 @@ collection_list::collect_symbol (struct symbol *sym, SYMBOL_PRINT_NAME (sym), len, paddress (gdbarch, offset), reg); } - add_memrange (gdbarch, reg, offset, len); + add_memrange (gdbarch, reg, offset, len, scope); break; case LOC_UNRESOLVED: @@ -966,26 +1032,10 @@ collection_list::collect_symbol (struct symbol *sym, 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)); } @@ -1084,9 +1134,20 @@ collection_list::add_static_trace_data () } 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); } @@ -1096,7 +1157,8 @@ collection_list::collection_list () std::vector collection_list::stringify () { - char temp_buf[2048]; + gdb::char_vector temp_buf (2048); + int count; char *end; long i; @@ -1106,35 +1168,45 @@ collection_list::stringify () { if (info_verbose) printf_filtered ("\nCollecting static trace data\n"); - end = temp_buf; + end = temp_buf.data (); *end++ = 'L'; - str_list.emplace_back (temp_buf, end - temp_buf); + 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.emplace_back (temp_buf); + *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) @@ -1148,9 +1220,9 @@ collection_list::stringify () } if (count + 27 > MAX_AGENT_EXPR_LEN) { - str_list.emplace_back (temp_buf, count); + str_list.emplace_back (temp_buf.data (), count); count = 0; - end = temp_buf; + end = temp_buf.data (); } { @@ -1170,7 +1242,7 @@ collection_list::stringify () } count += strlen (end); - end = temp_buf + count; + end = temp_buf.data () + count; } for (i = 0; i < m_aexprs.size (); i++) @@ -1178,9 +1250,9 @@ collection_list::stringify () QUIT; /* Allow user to bail out with ^C. */ if ((count + 10 + 2 * m_aexprs[i]->len) > MAX_AGENT_EXPR_LEN) { - str_list.emplace_back (temp_buf, count); + 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 + ',' */ @@ -1192,9 +1264,9 @@ collection_list::stringify () if (count != 0) { - str_list.emplace_back (temp_buf, count); + str_list.emplace_back (temp_buf.data (), count); count = 0; - end = temp_buf; + end = temp_buf.data (); } return str_list; @@ -1255,8 +1327,18 @@ encode_actions_1 (struct command_line *action, 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)) @@ -1286,27 +1368,10 @@ encode_actions_1 (struct command_line *action, 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? */ @@ -1338,7 +1403,8 @@ encode_actions_1 (struct command_line *action, name); if (info_verbose) printf_filtered ("OP_REGISTER: "); - collect->add_register (i); + collect->add_local_register (target_gdbarch (), + i, tloc->address); break; } @@ -1350,7 +1416,8 @@ encode_actions_1 (struct command_line *action, check_typedef (exp->elts[1].type); collect->add_memrange (target_gdbarch (), memrange_absolute, addr, - TYPE_LENGTH (exp->elts[1].type)); + TYPE_LENGTH (exp->elts[1].type), + tloc->address); collect->append_exp (exp.get ()); break; @@ -1374,28 +1441,10 @@ encode_actions_1 (struct command_line *action, 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 ()); @@ -1420,8 +1469,7 @@ encode_actions_1 (struct command_line *action, 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. */ @@ -1437,7 +1485,7 @@ encode_actions_1 (struct command_line *action, here. */ gdb_assert (stepping_list); - encode_actions_1 (action->body_list[0], tloc, frame_reg, + encode_actions_1 (action->body_list_0.get (), tloc, frame_reg, frame_offset, stepping_list, NULL); } else @@ -1453,17 +1501,17 @@ encode_actions (struct bp_location *tloc, 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 (); @@ -1493,15 +1541,11 @@ collection_list::add_aexpr (agent_expr_up aexpr) static void process_tracepoint_on_disconnect (void) { - VEC(breakpoint_p) *tp_vec = NULL; - int ix; - struct breakpoint *b; int has_pending_p = 0; /* Check whether we still have pending tracepoint. If we have, warn the user that pending tracepoint will no longer work. */ - tp_vec = all_tracepoints (); - for (ix = 0; VEC_iterate (breakpoint_p, tp_vec, ix, b); ix++) + for (breakpoint *b : all_tracepoints ()) { if (b->loc == NULL) { @@ -1525,7 +1569,6 @@ process_tracepoint_on_disconnect (void) break; } } - VEC_free (breakpoint_p, tp_vec); if (has_pending_p) warning (_("Pending tracepoints will not be resolved while" @@ -1546,23 +1589,16 @@ trace_reset_local_state (void) void start_tracing (const char *notes) { - VEC(breakpoint_p) *tp_vec = NULL; - int ix; - struct breakpoint *b; - struct trace_state_variable *tsv; int any_enabled = 0, num_to_download = 0; int ret; - tp_vec = all_tracepoints (); + std::vector tp_vec = all_tracepoints (); /* No point in tracing without any tracepoints... */ - if (VEC_length (breakpoint_p, tp_vec) == 0) - { - VEC_free (breakpoint_p, tp_vec); - error (_("No tracepoints defined, not starting trace")); - } + if (tp_vec.empty ()) + error (_("No tracepoints defined, not starting trace")); - for (ix = 0; VEC_iterate (breakpoint_p, tp_vec, ix, b); ix++) + for (breakpoint *b : tp_vec) { if (b->enable_state == bp_enabled) any_enabled = 1; @@ -1584,20 +1620,16 @@ start_tracing (const char *notes) { /* No point in tracing with only disabled tracepoints that cannot be re-enabled. */ - VEC_free (breakpoint_p, tp_vec); error (_("No tracepoints enabled, not starting trace")); } } if (num_to_download <= 0) - { - VEC_free (breakpoint_p, tp_vec); - error (_("No tracepoints that may be downloaded, not starting trace")); - } + error (_("No tracepoints that may be downloaded, not starting trace")); target_trace_init (); - for (ix = 0; VEC_iterate (breakpoint_p, tp_vec, ix, b); ix++) + for (breakpoint *b : tp_vec) { struct tracepoint *t = (struct tracepoint *) b; struct bp_location *loc; @@ -1636,7 +1668,6 @@ start_tracing (const char *notes) if (bp_location_downloaded) gdb::observers::breakpoint_modified.notify (b); } - VEC_free (breakpoint_p, tp_vec); /* Send down all the trace state variables too. */ for (const trace_state_variable &tsv : tvariables) @@ -1703,14 +1734,10 @@ void 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; @@ -1731,8 +1758,6 @@ stop_tracing (const char *note) } } - VEC_free (breakpoint_p, tp_vec); - if (!note) note = trace_stop_notes; ret = target_set_trace_notes (NULL, NULL, note); @@ -1749,9 +1774,7 @@ static void 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); @@ -1894,12 +1917,8 @@ tstatus_command (const char *args, int from_tty) (long int) (ts->stop_time % 1000000)); /* Now report any per-tracepoint status available. */ - tp_vec = all_tracepoints (); - - for (ix = 0; VEC_iterate (breakpoint_p, tp_vec, ix, t); ix++) + for (breakpoint *t : all_tracepoints ()) target_get_tracepoint_status (t, NULL); - - VEC_free (breakpoint_p, tp_vec); } /* Report the trace status to uiout, in a way suitable for MI, and not @@ -1981,8 +2000,8 @@ trace_status_mi (int on_stop) { 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); @@ -1991,16 +2010,16 @@ trace_status_mi (int on_stop) } 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); @@ -2164,8 +2183,8 @@ tfind_1 (enum trace_find_type type, int num, 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 { @@ -2408,7 +2427,7 @@ tfind_range_command (const char *args, int from_tty) if (args == 0 || *args == 0) { /* XXX FIXME: what should default behavior be? */ - printf_filtered ("Usage: tfind range ,\n"); + printf_filtered ("Usage: tfind range STARTADDR, ENDADDR\n"); return; } @@ -2442,7 +2461,7 @@ tfind_outside_command (const char *args, int from_tty) if (args == 0 || *args == 0) { /* XXX FIXME: what should default behavior be? */ - printf_filtered ("Usage: tfind outside ,\n"); + printf_filtered ("Usage: tfind outside STARTADDR, ENDADDR\n"); return; } @@ -2517,7 +2536,7 @@ info_scope_command (const char *args_in, int from_tty) if (SYMBOL_COMPUTED_OPS (sym) != NULL) SYMBOL_COMPUTED_OPS (sym)->describe_location (sym, - BLOCK_START (block), + BLOCK_ENTRY_PC (block), gdb_stdout); else { @@ -2594,7 +2613,7 @@ info_scope_command (const char *args_in, int from_tty) case LOC_BLOCK: printf_filtered ("a function at address "); printf_filtered ("%s", - paddress (gdbarch, BLOCK_START (SYMBOL_BLOCK_VALUE (sym)))); + paddress (gdbarch, BLOCK_ENTRY_PC (SYMBOL_BLOCK_VALUE (sym)))); break; case LOC_UNRESOLVED: msym = lookup_minimal_symbol (SYMBOL_LINKAGE_NAME (sym), @@ -2617,8 +2636,11 @@ info_scope_command (const char *args_in, int from_tty) } } if (SYMBOL_TYPE (sym)) - printf_filtered (", length %d.\n", - TYPE_LENGTH (check_typedef (SYMBOL_TYPE (sym)))); + { + struct type *t = check_typedef (SYMBOL_TYPE (sym)); + + printf_filtered (", length %s.\n", pulongest (TYPE_LENGTH (t))); + } } if (BLOCK_FUNCTION (block)) break; @@ -2663,11 +2685,9 @@ trace_dump_actions (struct command_line *action, if (cmd_cfunc_eq (cmd, while_stepping_pseudocommand)) { - int i; - - for (i = 0; i < action->body_count; ++i) - trace_dump_actions (action->body_list[i], - 1, stepping_frame, from_tty); + gdb_assert (action->body_list_1 == nullptr); + trace_dump_actions (action->body_list_0.get (), + 1, stepping_frame, from_tty); } else if (cmd_cfunc_eq (cmd, collect_pseudocommand)) { @@ -2679,9 +2699,6 @@ trace_dump_actions (struct command_line *action, STEPPING_ACTIONS should be equal. */ if (stepping_frame == stepping_actions) { - char *cmd = NULL; - struct cleanup *old_chain - = make_cleanup (free_current_contents, &cmd); int trace_string = 0; if (*action_exp == '/') @@ -2706,31 +2723,22 @@ trace_dump_actions (struct command_line *action, 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); } } } @@ -2778,16 +2786,12 @@ get_traceframe_location (int *stepping_frame_p) 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 @@ -2796,18 +2800,13 @@ all_tracepoint_actions_and_cleanup (struct breakpoint *t) the fly, and don't cache it. */ if (*default_collect) { - struct command_line *default_collect_action; - char *default_collect_line; - - default_collect_line = xstrprintf ("collect %s", default_collect); - make_cleanup (xfree, default_collect_line); - - validate_actionline (default_collect_line, t); - default_collect_action = XNEW (struct command_line); - make_cleanup (xfree, default_collect_action); - default_collect_action->next = actions; - default_collect_action->line = default_collect_line; - actions = default_collect_action; + gdb::unique_xmalloc_ptr default_collect_line + (xstrprintf ("collect %s", default_collect)); + + validate_actionline (default_collect_line.get (), t); + actions.reset (new struct command_line (simple_control, + default_collect_line.release ()), + command_lines_deleter ()); } return actions; @@ -2820,7 +2819,6 @@ 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); @@ -2834,9 +2832,11 @@ tdump_command (const char *args, int from_tty) 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 @@ -3077,19 +3077,17 @@ cond_string_is_same (char *str1, char *str2) static struct bp_location * find_matching_tracepoint_location (struct uploaded_tp *utp) { - VEC(breakpoint_p) *tp_vec = all_tracepoints (); - int ix; - struct breakpoint *b; struct bp_location *loc; - for (ix = 0; VEC_iterate (breakpoint_p, tp_vec, ix, b); ix++) + for (breakpoint *b : all_tracepoints ()) { struct tracepoint *t = (struct tracepoint *) b; if (b->type == utp->type && t->step_count == utp->step && t->pass_count == utp->pass - && cond_string_is_same (t->cond_string, utp->cond_string) + && cond_string_is_same (t->cond_string, + utp->cond_string.get ()) /* FIXME also test actions. */ ) { @@ -3113,9 +3111,7 @@ merge_uploaded_tracepoints (struct uploaded_tp **uploaded_tps) { struct uploaded_tp *utp; /* A set of tracepoints which are modified. */ - VEC(breakpoint_p) *modified_tp = NULL; - int ix; - struct breakpoint *b; + std::vector modified_tp; /* Look for GDB tracepoints that match up with our uploaded versions. */ for (utp = *uploaded_tps; utp; utp = utp->next) @@ -3141,16 +3137,14 @@ merge_uploaded_tracepoints (struct uploaded_tp **uploaded_tps) MODIFIED_TP if not there yet. The 'breakpoint-modified' observers will be notified later once for each tracepoint saved in MODIFIED_TP. */ - for (ix = 0; - VEC_iterate (breakpoint_p, modified_tp, ix, b); - ix++) + for (breakpoint *b : modified_tp) if (b == loc->owner) { found = 1; break; } if (!found) - VEC_safe_push (breakpoint_p, modified_tp, loc->owner); + modified_tp.push_back (loc->owner); } else { @@ -3175,10 +3169,9 @@ merge_uploaded_tracepoints (struct uploaded_tp **uploaded_tps) /* Notify 'breakpoint-modified' observer that at least one of B's locations was changed. */ - for (ix = 0; VEC_iterate (breakpoint_p, modified_tp, ix, b); ix++) + for (breakpoint *b : modified_tp) gdb::observers::breakpoint_modified.notify (b); - VEC_free (breakpoint_p, modified_tp); free_uploaded_tps (uploaded_tps); } @@ -3234,9 +3227,7 @@ create_tsv_from_upload (struct uploaded_tsv *utsv) void merge_uploaded_trace_state_variables (struct uploaded_tsv **uploaded_tsvs) { - int ix; struct uploaded_tsv *utsv; - struct trace_state_variable *tsv; int highest; /* Most likely some numbers will have to be reassigned as part of @@ -3246,7 +3237,7 @@ merge_uploaded_trace_state_variables (struct uploaded_tsv **uploaded_tsvs) 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) @@ -3475,7 +3466,7 @@ parse_tracepoint_definition (const char *line, struct uploaded_tp **utpp) int enabled, end; enum bptype type; const char *srctype; - char *cond, *buf; + char *buf; struct uploaded_tp *utp = NULL; p = line; @@ -3488,13 +3479,14 @@ parse_tracepoint_definition (const char *line, struct uploaded_tp **utpp) p++; /* skip a colon */ if (piece == 'T') { + gdb::unique_xmalloc_ptr cond; + enabled = (*p++ == 'E'); p++; /* skip a colon */ p = unpack_varlen_hex (p, &step); p++; /* skip a colon */ p = unpack_varlen_hex (p, &pass); type = bp_tracepoint; - cond = NULL; /* Thumb through optional fields. */ while (*p == ':') { @@ -3515,8 +3507,8 @@ parse_tracepoint_definition (const char *line, struct uploaded_tp **utpp) p++; p = unpack_varlen_hex (p, &xlen); p++; /* skip a comma */ - cond = (char *) xmalloc (2 * xlen + 1); - strncpy (cond, p, 2 * xlen); + cond.reset ((char *) xmalloc (2 * xlen + 1)); + strncpy (&cond[0], p, 2 * xlen); cond[2 * xlen] = '\0'; p += 2 * xlen; } @@ -3529,17 +3521,17 @@ parse_tracepoint_definition (const char *line, struct uploaded_tp **utpp) utp->enabled = enabled; utp->step = step; utp->pass = pass; - utp->cond = cond; + utp->cond = std::move (cond); } else if (piece == 'A') { utp = get_uploaded_tp (num, addr, utpp); - utp->actions.push_back (xstrdup (p)); + utp->actions.emplace_back (xstrdup (p)); } else if (piece == 'S') { utp = get_uploaded_tp (num, addr, utpp); - utp->step_actions.push_back (xstrdup (p)); + utp->step_actions.emplace_back (xstrdup (p)); } else if (piece == 'Z') { @@ -3559,11 +3551,11 @@ parse_tracepoint_definition (const char *line, struct uploaded_tp **utpp) buf[end] = '\0'; if (startswith (srctype, "at:")) - utp->at_string = xstrdup (buf); + utp->at_string.reset (xstrdup (buf)); else if (startswith (srctype, "cond:")) - utp->cond_string = xstrdup (buf); + utp->cond_string.reset (xstrdup (buf)); else if (startswith (srctype, "cmd:")) - utp->cmd_strings.push_back (xstrdup (buf)); + utp->cmd_strings.emplace_back (xstrdup (buf)); } else if (piece == 'V') { @@ -3662,23 +3654,23 @@ print_one_static_tracepoint_marker (int count, 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; - tracepoints = static_tracepoints_here (marker.address); + std::vector 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.c_str ()); uiout->field_fmt ("enabled", "%c", - !VEC_empty (breakpoint_p, tracepoints) ? 'y' : 'n'); + !tracepoints.empty () ? 'y' : 'n'); uiout->spaces (2); strcpy (wrap_indent, " "); @@ -3697,8 +3689,8 @@ print_one_static_tracepoint_marker (int count, if (sym) { uiout->text ("in "); - uiout->field_string ("func", - SYMBOL_PRINT_NAME (sym)); + uiout->field_string ("func", SYMBOL_PRINT_NAME (sym), + ui_out_style_kind::FUNCTION); uiout->wrap_hint (wrap_indent); uiout->text (" at "); } @@ -3708,7 +3700,8 @@ print_one_static_tracepoint_marker (int count, if (sal.symtab != NULL) { uiout->field_string ("file", - symtab_to_filename_for_display (sal.symtab)); + symtab_to_filename_for_display (sal.symtab), + ui_out_style_kind::FILE); uiout->text (":"); if (uiout->is_mi_like_p ()) @@ -3720,7 +3713,7 @@ print_one_static_tracepoint_marker (int count, else uiout->field_skip ("fullname"); - uiout->field_int ("line", sal.line); + uiout->field_signed ("line", sal.line); } else { @@ -3734,32 +3727,29 @@ print_one_static_tracepoint_marker (int count, uiout->field_string ("extra-data", marker.extra.c_str ()); 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 @@ -3811,7 +3801,7 @@ sdata_make_value (struct gdbarch *gdbarch, struct internalvar *var, { /* We need to read the whole object before we know its size. */ gdb::optional buf - = target_read_alloc (¤t_target, TARGET_OBJECT_STATIC_TRACE_DATA, + = target_read_alloc (current_top_target (), TARGET_OBJECT_STATIC_TRACE_DATA, NULL); if (buf) { @@ -3992,6 +3982,9 @@ static const struct internalvar_funcs sdata_funcs = NULL }; +/* See tracepoint.h. */ +cmd_list_element *while_stepping_cmd_element = nullptr; + /* module initialization */ void _initialize_tracepoint (void) @@ -4031,13 +4024,11 @@ If no arguments are supplied, delete all variables."), &deletelist); /* 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\ @@ -4046,12 +4037,12 @@ No argument means forward by one frame; '-' means backward by one frame."), 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, _("\ @@ -4086,13 +4077,13 @@ De-select any trace frame and resume 'live' debugging."), add_com ("tstop", class_trace, tstop_command, _("\ Stop trace data collection.\n\ -Usage: tstop [ ... ]\n\ +Usage: tstop [NOTES]...\n\ Any arguments supplied are recorded with the trace as a stop reason and\n\ reported by tstatus (if the target supports trace notes).")); add_com ("tstart", class_trace, tstart_command, _("\ Start trace data collection.\n\ -Usage: tstart [ ... ]\n\ +Usage: tstart [NOTES]...\n\ Any arguments supplied are recorded with the trace as a note and\n\ reported by tstatus (if the target supports trace notes).")); @@ -4103,7 +4094,8 @@ Entering \"end\" on a line by itself is the normal way to terminate\n\ such a list.\n\n\ Note: the \"end\" command cannot be used at the gdb prompt.")); - add_com ("while-stepping", class_trace, while_stepping_pseudocommand, _("\ + while_stepping_cmd_element = add_com ("while-stepping", class_trace, + while_stepping_pseudocommand, _("\ Specify single-stepping behavior at a tracepoint.\n\ Argument is number of instructions to trace in single-step mode\n\ following the tracepoint. This command is normally followed by\n\