X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=gdb%2Ftracepoint.c;h=18b569e30a8954c3405763f44f7d8b4422f3f0f3;hb=eb115069323087e15210c09e3b581be0f6fb5852;hp=582c284db26b3f1ca524be59410a89b587da15b0;hpb=e26167887817eaf9d6a4db73b96ca1dde47a7ac2;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/tracepoint.c b/gdb/tracepoint.c index 582c284db2..18b569e30a 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-2014 Free Software Foundation, Inc. + Copyright (C) 1997-2017 Free Software Foundation, Inc. This file is part of GDB. @@ -28,7 +28,6 @@ #include "target.h" #include "target-dcache.h" #include "language.h" -#include #include "inferior.h" #include "breakpoint.h" #include "tracepoint.h" @@ -50,11 +49,14 @@ #include "ax.h" #include "ax-gdb.h" #include "memrange.h" -#include "exceptions.h" #include "cli/cli-utils.h" #include "probe.h" #include "ctf.h" #include "filestuff.h" +#include "rsp-low.h" +#include "tracefile.h" +#include "location.h" +#include /* readline include files */ #include "readline/readline.h" @@ -65,10 +67,6 @@ #include -#ifndef O_LARGEFILE -#define O_LARGEFILE 0 -#endif - /* Maximum length of an agent aexpression. This accounts for the fact that packets are limited to 400 bytes (which includes everything -- including the checksum), and assumes @@ -168,28 +166,22 @@ char *trace_notes = NULL; char *trace_stop_notes = NULL; /* ======= Important command functions: ======= */ -static void trace_actions_command (char *, int); -static void trace_start_command (char *, int); -static void trace_stop_command (char *, int); -static void trace_status_command (char *, int); -static void trace_find_command (char *, int); -static void trace_find_pc_command (char *, int); -static void trace_find_tracepoint_command (char *, int); -static void trace_find_line_command (char *, int); -static void trace_find_range_command (char *, int); -static void trace_find_outside_command (char *, int); -static void trace_dump_command (char *, int); +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_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); /* support routines */ struct collection_list; -static void add_aexpr (struct collection_list *, struct agent_expr *); static char *mem2hex (gdb_byte *, char *, int); -static void add_register (struct collection_list *collection, - unsigned int regno); - -static void free_uploaded_tps (struct uploaded_tp **utpp); -static void free_uploaded_tsvs (struct uploaded_tsv **utsvp); static struct command_line * all_tracepoint_actions_and_cleanup (struct breakpoint *t); @@ -198,7 +190,7 @@ extern void _initialize_tracepoint (void); static struct trace_status trace_status; -char *stop_reason_names[] = { +const char *stop_reason_names[] = { "tunknown", "tnotrun", "tstop", @@ -494,7 +486,7 @@ tvariables_info_1 (void) struct cleanup *back_to; struct ui_out *uiout = current_uiout; - if (VEC_length (tsv_s, tvariables) == 0 && !ui_out_is_mi_like_p (uiout)) + if (VEC_length (tsv_s, tvariables) == 0 && !uiout->is_mi_like_p ()) { printf_filtered (_("No trace state variables.\n")); return; @@ -507,11 +499,11 @@ tvariables_info_1 (void) back_to = make_cleanup_ui_out_table_begin_end (uiout, 3, count, "trace-variables"); - ui_out_table_header (uiout, 15, ui_left, "name", "Name"); - ui_out_table_header (uiout, 11, ui_left, "initial", "Initial"); - ui_out_table_header (uiout, 11, ui_left, "current", "Current"); + uiout->table_header (15, ui_left, "name", "Name"); + uiout->table_header (11, ui_left, "initial", "Initial"); + uiout->table_header (11, ui_left, "current", "Current"); - ui_out_table_body (uiout); + uiout->table_body (); for (ix = 0; VEC_iterate (tsv_s, tvariables, ix, tsv); ++ix) { @@ -523,12 +515,12 @@ tvariables_info_1 (void) name = concat ("$", tsv->name, (char *) NULL); make_cleanup (xfree, name); - ui_out_field_string (uiout, "name", name); - ui_out_field_string (uiout, "initial", plongest (tsv->initial_value)); + uiout->field_string ("name", name); + uiout->field_string ("initial", plongest (tsv->initial_value)); if (tsv->value_known) c = plongest (tsv->value); - else if (ui_out_is_mi_like_p (uiout)) + 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. */ @@ -540,8 +532,8 @@ tvariables_info_1 (void) /* It is not meaningful to ask about the value. */ c = ""; if (c) - ui_out_field_string (uiout, "current", c); - ui_out_text (uiout, "\n"); + uiout->field_string ("current", c); + uiout->text ("\n"); do_cleanups (back_to2); } @@ -653,12 +645,12 @@ decode_agent_options (const char *exp, int *trace_string) /* Enter a list of actions for a tracepoint. */ static void -trace_actions_command (char *args, int from_tty) +actions_command (char *args, int from_tty) { struct tracepoint *t; struct command_line *l; - t = get_tracepoint_by_number (&args, NULL, 1); + t = get_tracepoint_by_number (&args, NULL); if (t) { char *tmpbuf = @@ -706,12 +698,10 @@ void validate_actionline (const char *line, struct breakpoint *b) { struct cmd_list_element *c; - struct expression *exp = NULL; struct cleanup *old_chain = NULL; const char *tmp_p; const char *p; struct bp_location *loc; - struct agent_expr *aexpr; struct tracepoint *t = (struct tracepoint *) b; /* If EOF is typed, *line is NULL. */ @@ -760,9 +750,8 @@ validate_actionline (const char *line, struct breakpoint *b) for (loc = t->base.loc; loc; loc = loc->next) { p = tmp_p; - exp = parse_exp_1 (&p, loc->address, - block_for_pc (loc->address), 1); - old_chain = make_cleanup (free_current_contents, &exp); + expression_up exp = parse_exp_1 (&p, loc->address, + block_for_pc (loc->address), 1); if (exp->elts[0].opcode == OP_VAR_VALUE) { @@ -785,17 +774,16 @@ validate_actionline (const char *line, struct breakpoint *b) /* We have something to collect, make sure that the expr to bytecode translator can handle it and that it's not too long. */ - aexpr = gen_trace_for_expr (loc->address, exp, trace_string); - make_cleanup_free_agent_expr (aexpr); + agent_expr_up aexpr = gen_trace_for_expr (loc->address, + exp.get (), + trace_string); if (aexpr->len > MAX_AGENT_EXPR_LEN) error (_("Expression is too complicated.")); - ax_reqs (aexpr); + ax_reqs (aexpr.get ()); - report_agent_reqs_errors (aexpr); - - do_cleanups (old_chain); + report_agent_reqs_errors (aexpr.get ()); } } while (p && *p++ == ','); @@ -814,23 +802,19 @@ validate_actionline (const char *line, struct breakpoint *b) p = tmp_p; /* Only expressions are allowed for this action. */ - exp = parse_exp_1 (&p, loc->address, - block_for_pc (loc->address), 1); - old_chain = make_cleanup (free_current_contents, &exp); + expression_up exp = parse_exp_1 (&p, loc->address, + block_for_pc (loc->address), 1); /* We have something to evaluate, make sure that the expr to bytecode translator can handle it and that it's not too long. */ - aexpr = gen_eval_for_expr (loc->address, exp); - make_cleanup_free_agent_expr (aexpr); + agent_expr_up aexpr = gen_eval_for_expr (loc->address, exp.get ()); if (aexpr->len > MAX_AGENT_EXPR_LEN) error (_("Expression is too complicated.")); - ax_reqs (aexpr); - report_agent_reqs_errors (aexpr); - - do_cleanups (old_chain); + ax_reqs (aexpr.get ()); + report_agent_reqs_errors (aexpr.get ()); } } while (p && *p++ == ','); @@ -860,116 +844,92 @@ enum { /* MEMRANGE functions: */ -static int memrange_cmp (const void *, const void *); +/* Compare memranges for std::sort. */ -/* Compare memranges for qsort. */ -static int -memrange_cmp (const void *va, const void *vb) +static bool +memrange_comp (const memrange &a, const memrange &b) { - const struct memrange *a = va, *b = vb; - - if (a->type < b->type) - return -1; - if (a->type > b->type) - return 1; - if (a->type == memrange_absolute) - { - if ((bfd_vma) a->start < (bfd_vma) b->start) - return -1; - if ((bfd_vma) a->start > (bfd_vma) b->start) - return 1; - } - else + if (a.type == b.type) { - if (a->start < b->start) - return -1; - if (a->start > b->start) - return 1; + if (a.type == memrange_absolute) + return (bfd_vma) a.start < (bfd_vma) b.start; + else + return a.start < b.start; } - return 0; + + return a.type < b.type; } -/* Sort the memrange list using qsort, and merge adjacent memranges. */ +/* Sort the memrange list using std::sort, and merge adjacent memranges. */ + static void -memrange_sortmerge (struct collection_list *memranges) +memrange_sortmerge (std::vector &memranges) { - int a, b; - - qsort (memranges->list, memranges->next_memrange, - sizeof (struct memrange), memrange_cmp); - if (memranges->next_memrange > 0) + if (!memranges.empty ()) { - for (a = 0, b = 1; b < memranges->next_memrange; b++) + int a, b; + + std::sort (memranges.begin (), memranges.end (), memrange_comp); + + for (a = 0, b = 1; b < memranges.size (); b++) { /* If memrange b overlaps or is adjacent to memrange a, merge them. */ - if (memranges->list[a].type == memranges->list[b].type - && memranges->list[b].start <= memranges->list[a].end) + if (memranges[a].type == memranges[b].type + && memranges[b].start <= memranges[a].end) { - if (memranges->list[b].end > memranges->list[a].end) - memranges->list[a].end = memranges->list[b].end; + if (memranges[b].end > memranges[a].end) + memranges[a].end = memranges[b].end; continue; /* next b, same a */ } a++; /* next a */ if (a != b) - memcpy (&memranges->list[a], &memranges->list[b], - sizeof (struct memrange)); + memranges[a] = memranges[b]; } - memranges->next_memrange = a + 1; + memranges.resize (a + 1); } } /* Add a register to a collection list. */ -static void -add_register (struct collection_list *collection, unsigned int regno) + +void +collection_list::add_register (unsigned int regno) { if (info_verbose) printf_filtered ("collect register %d\n", regno); - if (regno >= (8 * sizeof (collection->regs_mask))) + if (regno >= (8 * sizeof (m_regs_mask))) error (_("Internal: register number %d too large for tracepoint"), regno); - collection->regs_mask[regno / 8] |= 1 << (regno % 8); + m_regs_mask[regno / 8] |= 1 << (regno % 8); } /* Add a memrange to a collection list. */ -static void -add_memrange (struct collection_list *memranges, - int type, bfd_signed_vma base, - unsigned long len) + +void +collection_list::add_memrange (struct gdbarch *gdbarch, + int type, bfd_signed_vma base, + unsigned long len) { if (info_verbose) - { - printf_filtered ("(%d,", type); - printf_vma (base); - printf_filtered (",%ld)\n", len); - } + printf_filtered ("(%d,%s,%ld)\n", type, paddress (gdbarch, base), len); /* type: memrange_absolute == memory, other n == basereg */ - memranges->list[memranges->next_memrange].type = type; /* base: addr if memory, offset if reg relative. */ - memranges->list[memranges->next_memrange].start = base; /* len: we actually save end (base + len) for convenience */ - memranges->list[memranges->next_memrange].end = base + len; - memranges->next_memrange++; - if (memranges->next_memrange >= memranges->listsize) - { - memranges->listsize *= 2; - memranges->list = xrealloc (memranges->list, - memranges->listsize); - } + m_memranges.emplace_back (type, base, base + len); if (type != memrange_absolute) /* Better collect the base register! */ - add_register (memranges, type); + add_register (type); } /* Add a symbol to a collection list. */ -static void -collect_symbol (struct collection_list *collect, - struct symbol *sym, - struct gdbarch *gdbarch, - long frame_regno, long frame_offset, - CORE_ADDR scope, - int trace_string) + +void +collection_list::collect_symbol (struct symbol *sym, + struct gdbarch *gdbarch, + long frame_regno, long frame_offset, + CORE_ADDR scope, + int trace_string) { unsigned long len; unsigned int reg; @@ -992,31 +952,28 @@ collect_symbol (struct collection_list *collect, offset = SYMBOL_VALUE_ADDRESS (sym); if (info_verbose) { - char tmp[40]; - - sprintf_vma (tmp, offset); printf_filtered ("LOC_STATIC %s: collect %ld bytes at %s.\n", SYMBOL_PRINT_NAME (sym), len, - tmp /* address */); + paddress (gdbarch, offset)); } /* A struct may be a C++ class with static fields, go to general expression handling. */ if (TYPE_CODE (SYMBOL_TYPE (sym)) == TYPE_CODE_STRUCT) treat_as_expr = 1; else - add_memrange (collect, memrange_absolute, offset, len); + add_memrange (gdbarch, memrange_absolute, offset, len); break; case LOC_REGISTER: reg = SYMBOL_REGISTER_OPS (sym)->register_number (sym, gdbarch); if (info_verbose) printf_filtered ("LOC_REG[parm] %s: ", SYMBOL_PRINT_NAME (sym)); - add_register (collect, reg); + add_register (reg); /* Check for doubles stored in two registers. */ /* FIXME: how about larger types stored in 3 or more regs? */ if (TYPE_CODE (SYMBOL_TYPE (sym)) == TYPE_CODE_FLT && len > register_size (gdbarch, reg)) - add_register (collect, reg + 1); + add_register (reg + 1); break; case LOC_REF_ARG: printf_filtered ("Sorry, don't know how to do LOC_REF_ARG yet.\n"); @@ -1028,36 +985,36 @@ collect_symbol (struct collection_list *collect, offset = frame_offset + SYMBOL_VALUE (sym); if (info_verbose) { - printf_filtered ("LOC_LOCAL %s: Collect %ld bytes at offset ", - SYMBOL_PRINT_NAME (sym), len); - printf_vma (offset); - printf_filtered (" from frame ptr reg %d\n", reg); + printf_filtered ("LOC_LOCAL %s: Collect %ld bytes at offset %s" + " from frame ptr reg %d\n", + SYMBOL_PRINT_NAME (sym), len, + paddress (gdbarch, offset), reg); } - add_memrange (collect, reg, offset, len); + add_memrange (gdbarch, reg, offset, len); break; case LOC_REGPARM_ADDR: reg = SYMBOL_VALUE (sym); offset = 0; if (info_verbose) { - printf_filtered ("LOC_REGPARM_ADDR %s: Collect %ld bytes at offset ", - SYMBOL_PRINT_NAME (sym), len); - printf_vma (offset); - printf_filtered (" from reg %d\n", reg); + printf_filtered ("LOC_REGPARM_ADDR %s: Collect %ld bytes at offset %s" + " from reg %d\n", + SYMBOL_PRINT_NAME (sym), len, + paddress (gdbarch, offset), reg); } - add_memrange (collect, reg, offset, len); + add_memrange (gdbarch, reg, offset, len); break; case LOC_LOCAL: reg = frame_regno; offset = frame_offset + SYMBOL_VALUE (sym); if (info_verbose) { - printf_filtered ("LOC_LOCAL %s: Collect %ld bytes at offset ", - SYMBOL_PRINT_NAME (sym), len); - printf_vma (offset); - printf_filtered (" from frame ptr reg %d\n", reg); + printf_filtered ("LOC_LOCAL %s: Collect %ld bytes at offset %s" + " from frame ptr reg %d\n", + SYMBOL_PRINT_NAME (sym), len, + paddress (gdbarch, offset), reg); } - add_memrange (collect, reg, offset, len); + add_memrange (gdbarch, reg, offset, len); break; case LOC_UNRESOLVED: @@ -1077,10 +1034,10 @@ collect_symbol (struct collection_list *collect, /* Expressions are the most general case. */ if (treat_as_expr) { - struct agent_expr *aexpr; struct cleanup *old_chain1 = NULL; - aexpr = gen_trace_for_var (scope, gdbarch, sym, trace_string); + agent_expr_up aexpr = gen_trace_for_var (scope, gdbarch, + sym, trace_string); /* It can happen that the symbol is recorded as a computed location, but it's been optimized away and doesn't actually @@ -1092,33 +1049,28 @@ collect_symbol (struct collection_list *collect, return; } - old_chain1 = make_cleanup_free_agent_expr (aexpr); - - ax_reqs (aexpr); + ax_reqs (aexpr.get ()); - report_agent_reqs_errors (aexpr); - - discard_cleanups (old_chain1); - add_aexpr (collect, aexpr); + report_agent_reqs_errors (aexpr.get ()); /* Take care of the registers. */ if (aexpr->reg_mask_len > 0) { - int ndx1, ndx2; - - for (ndx1 = 0; ndx1 < aexpr->reg_mask_len; ndx1++) + 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 (ndx2 = 0; ndx2 < 8; ndx2++) + for (int ndx2 = 0; ndx2 < 8; ndx2++) if (aexpr->reg_mask[ndx1] & (1 << ndx2)) /* It's used -- record it. */ - add_register (collect, ndx1 * 8 + ndx2); + add_register (ndx1 * 8 + ndx2); } } } + + add_aexpr (std::move (aexpr)); } } @@ -1143,27 +1095,32 @@ do_collect_symbol (const char *print_name, struct symbol *sym, void *cb_data) { - struct add_local_symbols_data *p = cb_data; + struct add_local_symbols_data *p = (struct add_local_symbols_data *) cb_data; - collect_symbol (p->collect, sym, p->gdbarch, p->frame_regno, - p->frame_offset, p->pc, p->trace_string); + p->collect->collect_symbol (sym, p->gdbarch, p->frame_regno, + p->frame_offset, p->pc, p->trace_string); p->count++; - VEC_safe_push (char_ptr, p->collect->wholly_collected, - xstrdup (print_name)); + p->collect->add_wholly_collected (print_name); +} + +void +collection_list::add_wholly_collected (const char *print_name) +{ + m_wholly_collected.push_back (print_name); } /* Add all locals (or args) symbols to collection list. */ -static void -add_local_symbols (struct collection_list *collect, - struct gdbarch *gdbarch, CORE_ADDR pc, - long frame_regno, long frame_offset, int type, - int trace_string) + +void +collection_list::add_local_symbols (struct gdbarch *gdbarch, CORE_ADDR pc, + long frame_regno, long frame_offset, int type, + int trace_string) { - struct block *block; + const struct block *block; struct add_local_symbols_data cb_data; - cb_data.collect = collect; + cb_data.collect = this; cb_data.gdbarch = gdbarch; cb_data.pc = pc; cb_data.frame_regno = frame_regno; @@ -1201,79 +1158,38 @@ add_local_symbols (struct collection_list *collect, } } -static void -add_static_trace_data (struct collection_list *collection) +void +collection_list::add_static_trace_data () { if (info_verbose) printf_filtered ("collect static trace data\n"); - collection->strace_data = 1; -} - -/* worker function */ -static void -clear_collection_list (struct collection_list *list) -{ - int ndx; - - list->next_memrange = 0; - for (ndx = 0; ndx < list->next_aexpr_elt; ndx++) - { - free_agent_expr (list->aexpr_list[ndx]); - list->aexpr_list[ndx] = NULL; - } - list->next_aexpr_elt = 0; - memset (list->regs_mask, 0, sizeof (list->regs_mask)); - list->strace_data = 0; - - xfree (list->aexpr_list); - xfree (list->list); - - VEC_free (char_ptr, list->wholly_collected); - VEC_free (char_ptr, list->computed); -} - -/* A cleanup wrapper for function clear_collection_list. */ - -static void -do_clear_collection_list (void *list) -{ - struct collection_list *l = list; - - clear_collection_list (l); + m_strace_data = true; } -/* Initialize collection_list CLIST. */ - -static void -init_collection_list (struct collection_list *clist) +collection_list::collection_list () + : m_regs_mask (), + m_strace_data (false) { - memset (clist, 0, sizeof *clist); - - clist->listsize = 128; - clist->list = xcalloc (clist->listsize, - sizeof (struct memrange)); - - clist->aexpr_listsize = 128; - clist->aexpr_list = xcalloc (clist->aexpr_listsize, - sizeof (struct agent_expr *)); + m_memranges.reserve (128); + m_aexprs.reserve (128); } /* Reduce a collection list to string form (for gdb protocol). */ -static char ** -stringify_collection_list (struct collection_list *list) + +char ** +collection_list::stringify () { char temp_buf[2048]; - char tmp2[40]; int count; int ndx = 0; char *(*str_list)[]; char *end; long i; - count = 1 + 1 + list->next_memrange + list->next_aexpr_elt + 1; + count = 1 + 1 + m_memranges.size () + m_aexprs.size () + 1; str_list = (char *(*)[]) xmalloc (count * sizeof (char *)); - if (list->strace_data) + if (m_strace_data) { if (info_verbose) printf_filtered ("\nCollecting static trace data\n"); @@ -1283,10 +1199,10 @@ stringify_collection_list (struct collection_list *list) ndx++; } - for (i = sizeof (list->regs_mask) - 1; i > 0; i--) - if (list->regs_mask[i] != 0) /* Skip leading zeroes in regs_mask. */ + for (i = sizeof (m_regs_mask) - 1; i > 0; i--) + if (m_regs_mask[i] != 0) /* Skip leading zeroes in regs_mask. */ break; - if (list->regs_mask[i] != 0) /* Prepare to send regs_mask to the stub. */ + if (m_regs_mask[i] != 0) /* Prepare to send regs_mask to the stub. */ { if (info_verbose) printf_filtered ("\nCollecting registers (mask): 0x"); @@ -1296,8 +1212,8 @@ stringify_collection_list (struct collection_list *list) { QUIT; /* Allow user to bail out with ^C. */ if (info_verbose) - printf_filtered ("%02X", list->regs_mask[i]); - sprintf (end, "%02X", list->regs_mask[i]); + printf_filtered ("%02X", m_regs_mask[i]); + sprintf (end, "%02X", m_regs_mask[i]); end += 2; } (*str_list)[ndx] = xstrdup (temp_buf); @@ -1305,18 +1221,19 @@ stringify_collection_list (struct collection_list *list) } if (info_verbose) printf_filtered ("\n"); - if (list->next_memrange > 0 && info_verbose) + if (!m_memranges.empty () && info_verbose) printf_filtered ("Collecting memranges: \n"); - for (i = 0, count = 0, end = temp_buf; i < list->next_memrange; i++) + for (i = 0, count = 0, end = temp_buf; i < m_memranges.size (); i++) { QUIT; /* Allow user to bail out with ^C. */ - sprintf_vma (tmp2, list->list[i].start); if (info_verbose) { printf_filtered ("(%d, %s, %ld)\n", - list->list[i].type, - tmp2, - (long) (list->list[i].end - list->list[i].start)); + m_memranges[i].type, + paddress (target_gdbarch (), + m_memranges[i].start), + (long) (m_memranges[i].end + - m_memranges[i].start)); } if (count + 27 > MAX_AGENT_EXPR_LEN) { @@ -1327,39 +1244,41 @@ stringify_collection_list (struct collection_list *list) } { - bfd_signed_vma length = list->list[i].end - list->list[i].start; + bfd_signed_vma length + = m_memranges[i].end - m_memranges[i].start; /* The "%X" conversion specifier expects an unsigned argument, so passing -1 (memrange_absolute) to it directly gives you "FFFFFFFF" (or more, depending on sizeof (unsigned)). Special-case it. */ - if (list->list[i].type == memrange_absolute) - sprintf (end, "M-1,%s,%lX", tmp2, (long) length); + if (m_memranges[i].type == memrange_absolute) + sprintf (end, "M-1,%s,%lX", phex_nz (m_memranges[i].start, 0), + (long) length); else - sprintf (end, "M%X,%s,%lX", list->list[i].type, tmp2, (long) length); + sprintf (end, "M%X,%s,%lX", m_memranges[i].type, + phex_nz (m_memranges[i].start, 0), (long) length); } count += strlen (end); end = temp_buf + count; } - for (i = 0; i < list->next_aexpr_elt; i++) + for (i = 0; i < m_aexprs.size (); i++) { QUIT; /* Allow user to bail out with ^C. */ - if ((count + 10 + 2 * list->aexpr_list[i]->len) > MAX_AGENT_EXPR_LEN) + if ((count + 10 + 2 * m_aexprs[i]->len) > MAX_AGENT_EXPR_LEN) { (*str_list)[ndx] = savestring (temp_buf, count); ndx++; count = 0; end = temp_buf; } - sprintf (end, "X%08X,", list->aexpr_list[i]->len); + sprintf (end, "X%08X,", m_aexprs[i]->len); end += 10; /* 'X' + 8 hex digits + ',' */ count += 10; - end = mem2hex (list->aexpr_list[i]->buf, - end, list->aexpr_list[i]->len); - count += 2 * list->aexpr_list[i]->len; + end = mem2hex (m_aexprs[i]->buf, end, m_aexprs[i]->len); + count += 2 * m_aexprs[i]->len; } if (count != 0) @@ -1382,20 +1301,23 @@ stringify_collection_list (struct collection_list *list) /* Add the printed expression EXP to *LIST. */ -static void -append_exp (struct expression *exp, VEC(char_ptr) **list) +void +collection_list::append_exp (struct expression *exp) { struct ui_file *tmp_stream = mem_fileopen (); - char *text; print_expression (exp, tmp_stream); - text = ui_file_xstrdup (tmp_stream, NULL); - - VEC_safe_push (char_ptr, *list, text); + m_computed.push_back (ui_file_as_string (tmp_stream)); ui_file_delete (tmp_stream); } +void +collection_list::finish () +{ + memrange_sortmerge (m_memranges); +} + static void encode_actions_1 (struct command_line *action, struct bp_location *tloc, @@ -1405,11 +1327,9 @@ encode_actions_1 (struct command_line *action, struct collection_list *stepping_list) { const char *action_exp; - struct expression *exp = NULL; int i; struct value *tempval; struct cmd_list_element *cmd; - struct agent_expr *aexpr; for (; action; action = action->next) { @@ -1435,84 +1355,75 @@ encode_actions_1 (struct command_line *action, if (0 == strncasecmp ("$reg", action_exp, 4)) { - for (i = 0; i < gdbarch_num_regs (tloc->gdbarch); i++) - add_register (collect, i); + for (i = 0; i < gdbarch_num_regs (target_gdbarch ()); i++) + collect->add_register (i); action_exp = strchr (action_exp, ','); /* more? */ } else if (0 == strncasecmp ("$arg", action_exp, 4)) { - add_local_symbols (collect, - tloc->gdbarch, - tloc->address, - frame_reg, - frame_offset, - 'A', - trace_string); + collect->add_local_symbols (target_gdbarch (), + tloc->address, + frame_reg, + frame_offset, + 'A', + trace_string); action_exp = strchr (action_exp, ','); /* more? */ } else if (0 == strncasecmp ("$loc", action_exp, 4)) { - add_local_symbols (collect, - tloc->gdbarch, - tloc->address, - frame_reg, - frame_offset, - 'L', - trace_string); + collect->add_local_symbols (target_gdbarch (), + tloc->address, + frame_reg, + frame_offset, + 'L', + trace_string); action_exp = strchr (action_exp, ','); /* more? */ } else if (0 == strncasecmp ("$_ret", action_exp, 5)) { - struct cleanup *old_chain1 = NULL; - - aexpr = gen_trace_for_return_address (tloc->address, - tloc->gdbarch, - trace_string); - - old_chain1 = make_cleanup_free_agent_expr (aexpr); + agent_expr_up aexpr + = gen_trace_for_return_address (tloc->address, + target_gdbarch (), + trace_string); - ax_reqs (aexpr); - report_agent_reqs_errors (aexpr); - - discard_cleanups (old_chain1); - add_aexpr (collect, aexpr); + ax_reqs (aexpr.get ()); + report_agent_reqs_errors (aexpr.get ()); /* take care of the registers */ if (aexpr->reg_mask_len > 0) { - int ndx1, ndx2; - - for (ndx1 = 0; ndx1 < aexpr->reg_mask_len; ndx1++) + 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 (ndx2 = 0; ndx2 < 8; ndx2++) + for (int ndx2 = 0; ndx2 < 8; ndx2++) if (aexpr->reg_mask[ndx1] & (1 << ndx2)) - /* it's used -- record it */ - add_register (collect, - ndx1 * 8 + ndx2); + { + /* It's used -- record it. */ + collect->add_register (ndx1 * 8 + ndx2); + } } } } + collect->add_aexpr (std::move (aexpr)); action_exp = strchr (action_exp, ','); /* more? */ } else if (0 == strncasecmp ("$_sdata", action_exp, 7)) { - add_static_trace_data (collect); + collect->add_static_trace_data (); action_exp = strchr (action_exp, ','); /* more? */ } else { unsigned long addr; - struct cleanup *old_chain = NULL; struct cleanup *old_chain1 = NULL; - exp = parse_exp_1 (&action_exp, tloc->address, - block_for_pc (tloc->address), 1); - old_chain = make_cleanup (free_current_contents, &exp); + expression_up exp = parse_exp_1 (&action_exp, tloc->address, + block_for_pc (tloc->address), + 1); switch (exp->elts[0].opcode) { @@ -1520,7 +1431,7 @@ encode_actions_1 (struct command_line *action, { const char *name = &exp->elts[2].string; - i = user_reg_map_name_to_regnum (tloc->gdbarch, + i = user_reg_map_name_to_regnum (target_gdbarch (), name, strlen (name)); if (i == -1) internal_error (__FILE__, __LINE__, @@ -1528,19 +1439,20 @@ encode_actions_1 (struct command_line *action, name); if (info_verbose) printf_filtered ("OP_REGISTER: "); - add_register (collect, i); + collect->add_register (i); break; } case UNOP_MEMVAL: /* Safe because we know it's a simple expression. */ - tempval = evaluate_expression (exp); + tempval = evaluate_expression (exp.get ()); addr = value_address (tempval); /* Initialize the TYPE_LENGTH if it is a typedef. */ check_typedef (exp->elts[1].type); - add_memrange (collect, memrange_absolute, addr, - TYPE_LENGTH (exp->elts[1].type)); - append_exp (exp, &collect->computed); + collect->add_memrange (target_gdbarch (), + memrange_absolute, addr, + TYPE_LENGTH (exp->elts[1].type)); + collect->append_exp (exp.get ()); break; case OP_VAR_VALUE: @@ -1548,57 +1460,48 @@ encode_actions_1 (struct command_line *action, struct symbol *sym = exp->elts[2].symbol; char_ptr name = (char_ptr) SYMBOL_NATURAL_NAME (sym); - collect_symbol (collect, - exp->elts[2].symbol, - tloc->gdbarch, - frame_reg, - frame_offset, - tloc->address, - trace_string); - VEC_safe_push (char_ptr, - collect->wholly_collected, - name); + collect->collect_symbol (exp->elts[2].symbol, + target_gdbarch (), + frame_reg, + frame_offset, + tloc->address, + trace_string); + collect->add_wholly_collected (name); } break; default: /* Full-fledged expression. */ - aexpr = gen_trace_for_expr (tloc->address, exp, - trace_string); + agent_expr_up aexpr = gen_trace_for_expr (tloc->address, + exp.get (), + trace_string); - old_chain1 = make_cleanup_free_agent_expr (aexpr); + ax_reqs (aexpr.get ()); - ax_reqs (aexpr); - - report_agent_reqs_errors (aexpr); - - discard_cleanups (old_chain1); - add_aexpr (collect, aexpr); + report_agent_reqs_errors (aexpr.get ()); /* Take care of the registers. */ if (aexpr->reg_mask_len > 0) { - int ndx1; - int ndx2; - - for (ndx1 = 0; ndx1 < aexpr->reg_mask_len; ndx1++) + 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 (ndx2 = 0; ndx2 < 8; ndx2++) + for (int ndx2 = 0; ndx2 < 8; ndx2++) if (aexpr->reg_mask[ndx1] & (1 << ndx2)) - /* It's used -- record it. */ - add_register (collect, - ndx1 * 8 + ndx2); + { + /* It's used -- record it. */ + collect->add_register (ndx1 * 8 + ndx2); + } } } } - append_exp (exp, &collect->computed); + collect->add_aexpr (std::move (aexpr)); + collect->append_exp (exp.get ()); break; } /* switch */ - do_cleanups (old_chain); } /* do */ } while (action_exp && *action_exp++ == ','); @@ -1611,25 +1514,21 @@ encode_actions_1 (struct command_line *action, action_exp = skip_spaces_const (action_exp); { - struct cleanup *old_chain = NULL; struct cleanup *old_chain1 = NULL; - exp = parse_exp_1 (&action_exp, tloc->address, - block_for_pc (tloc->address), 1); - old_chain = make_cleanup (free_current_contents, &exp); + expression_up exp = parse_exp_1 (&action_exp, tloc->address, + block_for_pc (tloc->address), + 1); - aexpr = gen_eval_for_expr (tloc->address, exp); - old_chain1 = make_cleanup_free_agent_expr (aexpr); + agent_expr_up aexpr = gen_eval_for_expr (tloc->address, + exp.get ()); - ax_reqs (aexpr); - report_agent_reqs_errors (aexpr); + ax_reqs (aexpr.get ()); + report_agent_reqs_errors (aexpr.get ()); - discard_cleanups (old_chain1); /* Even though we're not officially collecting, add to the collect list anyway. */ - add_aexpr (collect, aexpr); - - do_cleanups (old_chain); + collect->add_aexpr (std::move (aexpr)); } /* do */ } while (action_exp && *action_exp++ == ','); @@ -1650,29 +1549,17 @@ encode_actions_1 (struct command_line *action, } /* Encode actions of tracepoint TLOC->owner and fill TRACEPOINT_LIST - and STEPPING_LIST. Return a cleanup pointer to clean up both - TRACEPOINT_LIST and STEPPING_LIST. */ + and STEPPING_LIST. */ -struct cleanup * -encode_actions_and_make_cleanup (struct bp_location *tloc, - struct collection_list *tracepoint_list, - struct collection_list *stepping_list) +void +encode_actions (struct bp_location *tloc, + struct collection_list *tracepoint_list, + struct collection_list *stepping_list) { - char *default_collect_line = NULL; struct command_line *actions; - struct command_line *default_collect_action = NULL; int frame_reg; LONGEST frame_offset; - struct cleanup *back_to, *return_chain; - - return_chain = make_cleanup (null_cleanup, NULL); - init_collection_list (tracepoint_list); - init_collection_list (stepping_list); - - make_cleanup (do_clear_collection_list, tracepoint_list); - make_cleanup (do_clear_collection_list, stepping_list); - back_to = make_cleanup (null_cleanup, NULL); gdbarch_virtual_frame_pointer (tloc->gdbarch, tloc->address, &frame_reg, &frame_offset); @@ -1681,11 +1568,8 @@ encode_actions_and_make_cleanup (struct bp_location *tloc, encode_actions_1 (actions, tloc, frame_reg, frame_offset, tracepoint_list, stepping_list); - memrange_sortmerge (tracepoint_list); - memrange_sortmerge (stepping_list); - - do_cleanups (back_to); - return return_chain; + tracepoint_list->finish (); + stepping_list->finish (); } /* Render all actions into gdb protocol. */ @@ -1695,32 +1579,20 @@ encode_actions_rsp (struct bp_location *tloc, char ***tdp_actions, char ***stepping_actions) { struct collection_list tracepoint_list, stepping_list; - struct cleanup *cleanup; *tdp_actions = NULL; *stepping_actions = NULL; - cleanup = encode_actions_and_make_cleanup (tloc, &tracepoint_list, - &stepping_list); + encode_actions (tloc, &tracepoint_list, &stepping_list); - *tdp_actions = stringify_collection_list (&tracepoint_list); - *stepping_actions = stringify_collection_list (&stepping_list); - - do_cleanups (cleanup); + *tdp_actions = tracepoint_list.stringify (); + *stepping_actions = stepping_list.stringify (); } -static void -add_aexpr (struct collection_list *collect, struct agent_expr *aexpr) +void +collection_list::add_aexpr (agent_expr_up aexpr) { - if (collect->next_aexpr_elt >= collect->aexpr_listsize) - { - collect->aexpr_list = - xrealloc (collect->aexpr_list, - 2 * collect->aexpr_listsize * sizeof (struct agent_expr *)); - collect->aexpr_listsize *= 2; - } - collect->aexpr_list[collect->next_aexpr_elt] = aexpr; - collect->next_aexpr_elt++; + m_aexprs.push_back (std::move (aexpr)); } static void @@ -1797,9 +1669,6 @@ start_tracing (char *notes) for (ix = 0; VEC_iterate (breakpoint_p, tp_vec, ix, b); ix++) { - struct tracepoint *t = (struct tracepoint *) b; - struct bp_location *loc; - if (b->enable_state == bp_enabled) any_enabled = 1; @@ -1865,8 +1734,11 @@ start_tracing (char *notes) t->number_on_target = b->number; for (loc = b->loc; loc; loc = loc->next) - if (loc->probe != NULL) - loc->probe->pops->set_semaphore (loc->probe, loc->gdbarch); + 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 (bp_location_downloaded) observer_notify_breakpoint_modified (b); @@ -1908,7 +1780,7 @@ start_tracing (char *notes) anybody else messing with the target. */ static void -trace_start_command (char *args, int from_tty) +tstart_command (char *args, int from_tty) { dont_repeat (); /* Like "run", dangerous to repeat accidentally. */ @@ -1928,7 +1800,7 @@ trace_start_command (char *args, int from_tty) of the trace run's status. */ static void -trace_stop_command (char *args, int from_tty) +tstop_command (char *args, int from_tty) { if (!current_trace_status ()->running) error (_("Trace is not running.")); @@ -1962,8 +1834,11 @@ stop_tracing (char *note) but we don't really care if this semaphore goes out of sync. That's why we are decrementing it here, but not taking care in other places. */ - if (loc->probe != NULL) - loc->probe->pops->clear_semaphore (loc->probe, loc->gdbarch); + 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); } } @@ -1982,7 +1857,7 @@ stop_tracing (char *note) /* tstatus command */ static void -trace_status_command (char *args, int from_tty) +tstatus_command (char *args, int from_tty) { struct trace_status *ts = current_trace_status (); int status, ix; @@ -2017,7 +1892,7 @@ trace_status_command (char *args, int from_tty) case trace_never_run: printf_filtered (_("No trace has been run on the target.\n")); break; - case tstop_command: + case trace_stop_command: if (ts->stop_desc) printf_filtered (_("Trace stopped by a tstop command (%s).\n"), ts->stop_desc); @@ -2155,23 +2030,23 @@ trace_status_mi (int on_stop) if (status == -1 && ts->filename == NULL) { - ui_out_field_string (uiout, "supported", "0"); + uiout->field_string ("supported", "0"); return; } if (ts->filename != NULL) - ui_out_field_string (uiout, "supported", "file"); + uiout->field_string ("supported", "file"); else if (!on_stop) - ui_out_field_string (uiout, "supported", "1"); + uiout->field_string ("supported", "1"); if (ts->filename != NULL) - ui_out_field_string (uiout, "trace-file", ts->filename); + uiout->field_string ("trace-file", ts->filename); gdb_assert (ts->running_known); if (ts->running) { - ui_out_field_string (uiout, "running", "1"); + uiout->field_string ("running", "1"); /* Unlike CLI, do not show the state of 'disconnected-tracing' variable. Given that the frontend gets the status either on -trace-stop, or from @@ -2188,13 +2063,13 @@ trace_status_mi (int on_stop) int stopping_tracepoint = -1; if (!on_stop) - ui_out_field_string (uiout, "running", "0"); + uiout->field_string ("running", "0"); if (ts->stop_reason != trace_stop_reason_unknown) { switch (ts->stop_reason) { - case tstop_command: + case trace_stop_command: stop_reason = "request"; break; case trace_buffer_full: @@ -2215,31 +2090,31 @@ trace_status_mi (int on_stop) if (stop_reason) { - ui_out_field_string (uiout, "stop-reason", stop_reason); + uiout->field_string ("stop-reason", stop_reason); if (stopping_tracepoint != -1) - ui_out_field_int (uiout, "stopping-tracepoint", + uiout->field_int ("stopping-tracepoint", stopping_tracepoint); if (ts->stop_reason == tracepoint_error) - ui_out_field_string (uiout, "error-description", + uiout->field_string ("error-description", ts->stop_desc); } } } if (ts->traceframe_count != -1) - ui_out_field_int (uiout, "frames", ts->traceframe_count); + uiout->field_int ("frames", ts->traceframe_count); if (ts->traceframes_created != -1) - ui_out_field_int (uiout, "frames-created", ts->traceframes_created); + uiout->field_int ("frames-created", ts->traceframes_created); if (ts->buffer_size != -1) - ui_out_field_int (uiout, "buffer-size", ts->buffer_size); + uiout->field_int ("buffer-size", ts->buffer_size); if (ts->buffer_free != -1) - ui_out_field_int (uiout, "buffer-free", ts->buffer_free); + uiout->field_int ("buffer-free", ts->buffer_free); - ui_out_field_int (uiout, "disconnected", ts->disconnected_tracing); - ui_out_field_int (uiout, "circular", ts->circular_buffer); + uiout->field_int ("disconnected", ts->disconnected_tracing); + uiout->field_int ("circular", ts->circular_buffer); - ui_out_field_string (uiout, "user-name", ts->user_name); - ui_out_field_string (uiout, "notes", ts->notes); + uiout->field_string ("user-name", ts->user_name); + uiout->field_string ("notes", ts->notes); { char buf[100]; @@ -2247,11 +2122,11 @@ trace_status_mi (int on_stop) xsnprintf (buf, sizeof buf, "%ld.%06ld", (long int) (ts->start_time / 1000000), (long int) (ts->start_time % 1000000)); - ui_out_field_string (uiout, "start-time", buf); + uiout->field_string ("start-time", buf); xsnprintf (buf, sizeof buf, "%ld.%06ld", (long int) (ts->stop_time / 1000000), (long int) (ts->stop_time % 1000000)); - ui_out_field_string (uiout, "stop-time", buf); + uiout->field_string ("stop-time", buf); } } @@ -2371,7 +2246,7 @@ tfind_1 (enum trace_find_type type, int num, #if 0 /* dubious now? */ /* The following will not recurse, since it's special-cased. */ - trace_find_command ("-1", from_tty); + tfind_command ("-1", from_tty); #endif } } @@ -2397,11 +2272,11 @@ tfind_1 (enum trace_find_type type, int num, { /* Use different branches for MI and CLI to make CLI messages i18n-eable. */ - if (ui_out_is_mi_like_p (uiout)) + if (uiout->is_mi_like_p ()) { - ui_out_field_string (uiout, "found", "1"); - ui_out_field_int (uiout, "tracepoint", tracepoint_number); - ui_out_field_int (uiout, "traceframe", traceframe_number); + uiout->field_string ("found", "1"); + uiout->field_int ("tracepoint", tracepoint_number); + uiout->field_int ("traceframe", traceframe_number); } else { @@ -2411,8 +2286,8 @@ tfind_1 (enum trace_find_type type, int num, } else { - if (ui_out_is_mi_like_p (uiout)) - ui_out_field_string (uiout, "found", "0"); + if (uiout->is_mi_like_p ()) + uiout->field_string ("found", "0"); else if (type == tfind_number && num == -1) printf_unfiltered (_("No longer looking at any trace frame\n")); else /* This case may never occur, check. */ @@ -2444,6 +2319,15 @@ tfind_1 (enum trace_find_type type, int num, } } +/* Error on looking at traceframes while trace is running. */ + +void +check_trace_running (struct trace_status *status) +{ + if (status->running && status->filename == NULL) + error (_("May not look at trace frames while trace is running.")); +} + /* trace_find_command takes a trace frame number n, sends "QTFrame:" to the target, and accepts a reply that may contain several optional pieces @@ -2460,13 +2344,11 @@ tfind_1 (enum trace_find_type type, int num, /* tfind command */ static void -trace_find_command (char *args, int from_tty) +tfind_command (char *args, int from_tty) { /* This should only be called with a numeric argument. */ int frameno = -1; - if (current_trace_status ()->running - && current_trace_status ()->filename == NULL) - error (_("May not look at trace frames while trace is running.")); + check_trace_running (current_trace_status ()); if (args == 0 || *args == 0) { /* TFIND with no args means find NEXT trace frame. */ @@ -2498,27 +2380,25 @@ trace_find_command (char *args, int from_tty) /* tfind end */ static void -trace_find_end_command (char *args, int from_tty) +tfind_end_command (char *args, int from_tty) { - trace_find_command ("-1", from_tty); + tfind_command ("-1", from_tty); } /* tfind start */ static void -trace_find_start_command (char *args, int from_tty) +tfind_start_command (char *args, int from_tty) { - trace_find_command ("0", from_tty); + tfind_command ("0", from_tty); } /* tfind pc command */ static void -trace_find_pc_command (char *args, int from_tty) +tfind_pc_command (char *args, int from_tty) { CORE_ADDR pc; - if (current_trace_status ()->running - && current_trace_status ()->filename == NULL) - error (_("May not look at trace frames while trace is running.")); + check_trace_running (current_trace_status ()); if (args == 0 || *args == 0) pc = regcache_read_pc (get_current_regcache ()); @@ -2530,14 +2410,12 @@ trace_find_pc_command (char *args, int from_tty) /* tfind tracepoint command */ static void -trace_find_tracepoint_command (char *args, int from_tty) +tfind_tracepoint_command (char *args, int from_tty) { int tdp; struct tracepoint *tp; - if (current_trace_status ()->running - && current_trace_status ()->filename == NULL) - error (_("May not look at trace frames while trace is running.")); + check_trace_running (current_trace_status ()); if (args == 0 || *args == 0) { @@ -2568,23 +2446,20 @@ trace_find_tracepoint_command (char *args, int from_tty) corresponding to a source line OTHER THAN THE CURRENT ONE. */ static void -trace_find_line_command (char *args, int from_tty) +tfind_line_command (char *args, int from_tty) { static CORE_ADDR start_pc, end_pc; struct symtabs_and_lines sals; struct symtab_and_line sal; struct cleanup *old_chain; - if (current_trace_status ()->running - && current_trace_status ()->filename == NULL) - error (_("May not look at trace frames while trace is running.")); + check_trace_running (current_trace_status ()); if (args == 0 || *args == 0) { sal = find_pc_line (get_frame_pc (get_current_frame ()), 0); sals.nelts = 1; - sals.sals = (struct symtab_and_line *) - xmalloc (sizeof (struct symtab_and_line)); + sals.sals = XNEW (struct symtab_and_line); sals.sals[0] = sal; } else @@ -2636,14 +2511,12 @@ trace_find_line_command (char *args, int from_tty) /* tfind range command */ static void -trace_find_range_command (char *args, int from_tty) +tfind_range_command (char *args, int from_tty) { static CORE_ADDR start, stop; char *tmp; - if (current_trace_status ()->running - && current_trace_status ()->filename == NULL) - error (_("May not look at trace frames while trace is running.")); + check_trace_running (current_trace_status ()); if (args == 0 || *args == 0) { /* XXX FIXME: what should default behavior be? */ @@ -2669,7 +2542,7 @@ trace_find_range_command (char *args, int from_tty) /* tfind outside command */ static void -trace_find_outside_command (char *args, int from_tty) +tfind_outside_command (char *args, int from_tty) { CORE_ADDR start, stop; char *tmp; @@ -2706,22 +2579,30 @@ scope_info (char *args, int from_tty) { struct symtabs_and_lines sals; struct symbol *sym; - struct minimal_symbol *msym; - struct block *block; + struct bound_minimal_symbol msym; + const struct block *block; const char *symname; char *save_args = args; struct block_iterator iter; int j, count = 0; struct gdbarch *gdbarch; int regno; + struct event_location *location; + struct cleanup *back_to; if (args == 0 || *args == 0) error (_("requires an argument (function, " "line or *addr) to define a scope")); - sals = decode_line_1 (&args, DECODE_LINE_FUNFIRSTLINE, NULL, 0); + location = string_to_event_location (&args, current_language); + back_to = make_cleanup_delete_event_location (location); + sals = decode_line_1 (location, DECODE_LINE_FUNFIRSTLINE, NULL, NULL, 0); if (sals.nelts == 0) - return; /* Presumably decode_line_1 has already warned. */ + { + /* Presumably decode_line_1 has already warned. */ + do_cleanups (back_to); + return; + } /* Resolve line numbers to PC. */ resolve_sal_pc (&sals.sals[0]); @@ -2741,7 +2622,7 @@ scope_info (char *args, int from_tty) if (symname == NULL || *symname == '\0') continue; /* Probably botched, certainly useless. */ - gdbarch = get_objfile_arch (SYMBOL_SYMTAB (sym)->objfile); + gdbarch = symbol_arch (sym); printf_filtered ("Symbol %s is ", symname); @@ -2829,14 +2710,14 @@ scope_info (char *args, int from_tty) case LOC_UNRESOLVED: msym = lookup_minimal_symbol (SYMBOL_LINKAGE_NAME (sym), NULL, NULL); - if (msym == NULL) + if (msym.minsym == NULL) printf_filtered ("Unresolved Static"); else { printf_filtered ("static storage at address "); printf_filtered ("%s", paddress (gdbarch, - SYMBOL_VALUE_ADDRESS (msym))); + BMSYMBOL_VALUE_ADDRESS (msym))); } break; case LOC_OPTIMIZED_OUT: @@ -2858,6 +2739,7 @@ scope_info (char *args, int from_tty) if (count <= 0) printf_filtered ("Scope for %s contains no locals or arguments.\n", save_args); + do_cleanups (back_to); } /* Helper for trace_dump_command. Dump the action list starting at @@ -2940,7 +2822,7 @@ trace_dump_actions (struct command_line *action, { size_t len = next_comma - action_exp; - cmd = xrealloc (cmd, len + 1); + cmd = (char *) xrealloc (cmd, len + 1); memcpy (cmd, action_exp, len); cmd[len] = 0; } @@ -2948,7 +2830,7 @@ trace_dump_actions (struct command_line *action, { size_t len = strlen (action_exp); - cmd = xrealloc (cmd, len + 1); + cmd = (char *) xrealloc (cmd, len + 1); memcpy (cmd, action_exp, len + 1); } @@ -3033,7 +2915,7 @@ all_tracepoint_actions_and_cleanup (struct breakpoint *t) make_cleanup (xfree, default_collect_line); validate_actionline (default_collect_line, t); - default_collect_action = xmalloc (sizeof (struct command_line)); + 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; @@ -3046,7 +2928,7 @@ all_tracepoint_actions_and_cleanup (struct breakpoint *t) /* The tdump command. */ static void -trace_dump_command (char *args, int from_tty) +tdump_command (char *args, int from_tty) { int stepping_frame = 0; struct bp_location *loc; @@ -3059,11 +2941,9 @@ trace_dump_command (char *args, int from_tty) printf_filtered ("Data collected at tracepoint %d, trace frame %d:\n", tracepoint_number, traceframe_number); - old_chain = make_cleanup (null_cleanup, NULL); - /* This command only makes sense for the current frame, not the selected frame. */ - make_cleanup_restore_current_thread (); + old_chain = make_cleanup_restore_current_thread (); select_frame (get_current_frame ()); actions = all_tracepoint_actions_and_cleanup (loc->owner); @@ -3080,7 +2960,7 @@ trace_dump_command (char *args, int from_tty) extern int encode_source_string (int tpnum, ULONGEST addr, - char *srctype, char *src, char *buf, int buf_size) + char *srctype, const char *src, char *buf, int buf_size) { if (80 + strlen (srctype) > buf_size) error (_("Buffer too small for source encoding")); @@ -3089,844 +2969,173 @@ encode_source_string (int tpnum, ULONGEST addr, srctype, 0, (int) strlen (src)); if (strlen (buf) + strlen (src) * 2 >= buf_size) error (_("Source string too long for buffer")); - bin2hex ((gdb_byte *) src, buf + strlen (buf), 0); + bin2hex ((gdb_byte *) src, buf + strlen (buf), strlen (src)); return -1; } -/* Free trace file writer. */ +/* Tell the target what to do with an ongoing tracing run if GDB + disconnects for some reason. */ static void -trace_file_writer_xfree (void *arg) +set_disconnected_tracing (char *args, int from_tty, + struct cmd_list_element *c) { - struct trace_file_writer *writer = arg; - - writer->ops->dtor (writer); - xfree (writer); + target_set_disconnected_tracing (disconnected_tracing); } -/* TFILE trace writer. */ - -struct tfile_trace_file_writer +static void +set_circular_trace_buffer (char *args, int from_tty, + struct cmd_list_element *c) { - struct trace_file_writer base; - - /* File pointer to tfile trace file. */ - FILE *fp; - /* Path name of the tfile trace file. */ - char *pathname; -}; - -/* This is the implementation of trace_file_write_ops method - target_save. We just call the generic target - target_save_trace_data to do target-side saving. */ + target_set_circular_trace_buffer (circular_trace_buffer); +} -static int -tfile_target_save (struct trace_file_writer *self, - const char *filename) +static void +set_trace_buffer_size (char *args, int from_tty, + struct cmd_list_element *c) { - int err = target_save_trace_data (filename); - - return (err >= 0); + target_set_trace_buffer_size (trace_buffer_size); } -/* This is the implementation of trace_file_write_ops method - dtor. */ - static void -tfile_dtor (struct trace_file_writer *self) +set_trace_user (char *args, int from_tty, + struct cmd_list_element *c) { - struct tfile_trace_file_writer *writer - = (struct tfile_trace_file_writer *) self; + int ret; - xfree (writer->pathname); + ret = target_set_trace_notes (trace_user, NULL, NULL); - if (writer->fp != NULL) - fclose (writer->fp); + if (!ret) + warning (_("Target does not support trace notes, user ignored")); } -/* This is the implementation of trace_file_write_ops method - start. It creates the trace file FILENAME and registers some - cleanups. */ - static void -tfile_start (struct trace_file_writer *self, const char *filename) +set_trace_notes (char *args, int from_tty, + struct cmd_list_element *c) { - struct tfile_trace_file_writer *writer - = (struct tfile_trace_file_writer *) self; - - writer->pathname = tilde_expand (filename); - writer->fp = gdb_fopen_cloexec (writer->pathname, "wb"); - if (writer->fp == NULL) - error (_("Unable to open file '%s' for saving trace data (%s)"), - writer->pathname, safe_strerror (errno)); -} + int ret; -/* This is the implementation of trace_file_write_ops method - write_header. Write the TFILE header. */ + ret = target_set_trace_notes (NULL, trace_notes, NULL); -static void -tfile_write_header (struct trace_file_writer *self) -{ - struct tfile_trace_file_writer *writer - = (struct tfile_trace_file_writer *) self; - int written; - - /* Write a file header, with a high-bit-set char to indicate a - binary file, plus a hint as what this file is, and a version - number in case of future needs. */ - written = fwrite ("\x7fTRACE0\n", 8, 1, writer->fp); - if (written < 1) - perror_with_name (writer->pathname); + if (!ret) + warning (_("Target does not support trace notes, note ignored")); } -/* This is the implementation of trace_file_write_ops method - write_regblock_type. Write the size of register block. */ - static void -tfile_write_regblock_type (struct trace_file_writer *self, int size) +set_trace_stop_notes (char *args, int from_tty, + struct cmd_list_element *c) { - struct tfile_trace_file_writer *writer - = (struct tfile_trace_file_writer *) self; + int ret; + + ret = target_set_trace_notes (NULL, NULL, trace_stop_notes); - fprintf (writer->fp, "R %x\n", size); + if (!ret) + warning (_("Target does not support trace notes, stop note ignored")); } -/* This is the implementation of trace_file_write_ops method - write_status. */ +/* Convert the memory pointed to by mem into hex, placing result in buf. + * Return a pointer to the last char put in buf (null) + * "stolen" from sparc-stub.c + */ + +static const char hexchars[] = "0123456789abcdef"; -static void -tfile_write_status (struct trace_file_writer *self, - struct trace_status *ts) +static char * +mem2hex (gdb_byte *mem, char *buf, int count) { - struct tfile_trace_file_writer *writer - = (struct tfile_trace_file_writer *) self; + gdb_byte ch; - fprintf (writer->fp, "status %c;%s", - (ts->running ? '1' : '0'), stop_reason_names[ts->stop_reason]); - if (ts->stop_reason == tracepoint_error - || ts->stop_reason == tstop_command) + while (count-- > 0) { - char *buf = (char *) alloca (strlen (ts->stop_desc) * 2 + 1); + ch = *mem++; - bin2hex ((gdb_byte *) ts->stop_desc, buf, 0); - fprintf (writer->fp, ":%s", buf); - } - fprintf (writer->fp, ":%x", ts->stopping_tracepoint); - if (ts->traceframe_count >= 0) - fprintf (writer->fp, ";tframes:%x", ts->traceframe_count); - if (ts->traceframes_created >= 0) - fprintf (writer->fp, ";tcreated:%x", ts->traceframes_created); - if (ts->buffer_free >= 0) - fprintf (writer->fp, ";tfree:%x", ts->buffer_free); - if (ts->buffer_size >= 0) - fprintf (writer->fp, ";tsize:%x", ts->buffer_size); - if (ts->disconnected_tracing) - fprintf (writer->fp, ";disconn:%x", ts->disconnected_tracing); - if (ts->circular_buffer) - fprintf (writer->fp, ";circular:%x", ts->circular_buffer); - if (ts->start_time) - { - fprintf (writer->fp, ";starttime:%s", - phex_nz (ts->start_time, sizeof (ts->start_time))); - } - if (ts->stop_time) - { - fprintf (writer->fp, ";stoptime:%s", - phex_nz (ts->stop_time, sizeof (ts->stop_time))); + *buf++ = hexchars[ch >> 4]; + *buf++ = hexchars[ch & 0xf]; } - if (ts->notes != NULL) - { - char *buf = (char *) alloca (strlen (ts->notes) * 2 + 1); - bin2hex ((gdb_byte *) ts->notes, buf, 0); - fprintf (writer->fp, ";notes:%s", buf); - } - if (ts->user_name != NULL) - { - char *buf = (char *) alloca (strlen (ts->user_name) * 2 + 1); + *buf = 0; - bin2hex ((gdb_byte *) ts->user_name, buf, 0); - fprintf (writer->fp, ";username:%s", buf); - } - fprintf (writer->fp, "\n"); + return buf; +} + +int +get_traceframe_number (void) +{ + return traceframe_number; } -/* This is the implementation of trace_file_write_ops method - write_uploaded_tsv. */ +int +get_tracepoint_number (void) +{ + return tracepoint_number; +} -static void -tfile_write_uploaded_tsv (struct trace_file_writer *self, - struct uploaded_tsv *utsv) +/* Make the traceframe NUM be the current trace frame. Does nothing + if NUM is already current. */ + +void +set_current_traceframe (int num) { - char *buf = ""; - struct tfile_trace_file_writer *writer - = (struct tfile_trace_file_writer *) self; + int newnum; - if (utsv->name) + if (traceframe_number == num) { - buf = (char *) xmalloc (strlen (utsv->name) * 2 + 1); - bin2hex ((gdb_byte *) (utsv->name), buf, 0); + /* Nothing to do. */ + return; } - fprintf (writer->fp, "tsv %x:%s:%x:%s\n", - utsv->number, phex_nz (utsv->initial_value, 8), - utsv->builtin, buf); + newnum = target_trace_find (tfind_number, num, 0, 0, NULL); - if (utsv->name) - xfree (buf); -} + if (newnum != num) + warning (_("could not change traceframe")); -#define MAX_TRACE_UPLOAD 2000 + set_traceframe_num (newnum); -/* This is the implementation of trace_file_write_ops method - write_uploaded_tp. */ + /* Changing the traceframe changes our view of registers and of the + frame chain. */ + registers_changed (); -static void -tfile_write_uploaded_tp (struct trace_file_writer *self, - struct uploaded_tp *utp) -{ - struct tfile_trace_file_writer *writer - = (struct tfile_trace_file_writer *) self; - int a; - char *act; - char buf[MAX_TRACE_UPLOAD]; - - fprintf (writer->fp, "tp T%x:%s:%c:%x:%x", - utp->number, phex_nz (utp->addr, sizeof (utp->addr)), - (utp->enabled ? 'E' : 'D'), utp->step, utp->pass); - if (utp->type == bp_fast_tracepoint) - fprintf (writer->fp, ":F%x", utp->orig_size); - if (utp->cond) - fprintf (writer->fp, - ":X%x,%s", (unsigned int) strlen (utp->cond) / 2, - utp->cond); - fprintf (writer->fp, "\n"); - for (a = 0; VEC_iterate (char_ptr, utp->actions, a, act); ++a) - fprintf (writer->fp, "tp A%x:%s:%s\n", - utp->number, phex_nz (utp->addr, sizeof (utp->addr)), act); - for (a = 0; VEC_iterate (char_ptr, utp->step_actions, a, act); ++a) - fprintf (writer->fp, "tp S%x:%s:%s\n", - utp->number, phex_nz (utp->addr, sizeof (utp->addr)), act); - if (utp->at_string) - { - encode_source_string (utp->number, utp->addr, - "at", utp->at_string, buf, MAX_TRACE_UPLOAD); - fprintf (writer->fp, "tp Z%s\n", buf); - } - if (utp->cond_string) - { - encode_source_string (utp->number, utp->addr, - "cond", utp->cond_string, - buf, MAX_TRACE_UPLOAD); - fprintf (writer->fp, "tp Z%s\n", buf); - } - for (a = 0; VEC_iterate (char_ptr, utp->cmd_strings, a, act); ++a) - { - encode_source_string (utp->number, utp->addr, "cmd", act, - buf, MAX_TRACE_UPLOAD); - fprintf (writer->fp, "tp Z%s\n", buf); - } - fprintf (writer->fp, "tp V%x:%s:%x:%s\n", - utp->number, phex_nz (utp->addr, sizeof (utp->addr)), - utp->hit_count, - phex_nz (utp->traceframe_usage, - sizeof (utp->traceframe_usage))); + clear_traceframe_info (); } -/* This is the implementation of trace_file_write_ops method - write_definition_end. */ +/* 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 -tfile_write_definition_end (struct trace_file_writer *self) +do_restore_current_traceframe_cleanup (void *arg) { - struct tfile_trace_file_writer *writer - = (struct tfile_trace_file_writer *) self; + struct current_traceframe_cleanup *old + = (struct current_traceframe_cleanup *) arg; - fprintf (writer->fp, "\n"); + set_current_traceframe (old->traceframe_number); } -/* This is the implementation of trace_file_write_ops method - write_raw_data. */ - static void -tfile_write_raw_data (struct trace_file_writer *self, gdb_byte *buf, - LONGEST len) +restore_current_traceframe_cleanup_dtor (void *arg) { - struct tfile_trace_file_writer *writer - = (struct tfile_trace_file_writer *) self; + struct current_traceframe_cleanup *old + = (struct current_traceframe_cleanup *) arg; - if (fwrite (buf, len, 1, writer->fp) < 1) - perror_with_name (writer->pathname); -} - -/* This is the implementation of trace_file_write_ops method - end. */ - -static void -tfile_end (struct trace_file_writer *self) -{ - struct tfile_trace_file_writer *writer - = (struct tfile_trace_file_writer *) self; - uint32_t gotten = 0; - - /* Mark the end of trace data. */ - if (fwrite (&gotten, 4, 1, writer->fp) < 1) - perror_with_name (writer->pathname); -} - -/* Operations to write trace buffers into TFILE format. */ - -static const struct trace_file_write_ops tfile_write_ops = -{ - tfile_dtor, - tfile_target_save, - tfile_start, - tfile_write_header, - tfile_write_regblock_type, - tfile_write_status, - tfile_write_uploaded_tsv, - tfile_write_uploaded_tp, - tfile_write_definition_end, - tfile_write_raw_data, - NULL, - tfile_end, -}; - -/* Helper macros. */ - -#define TRACE_WRITE_R_BLOCK(writer, buf, size) \ - writer->ops->frame_ops->write_r_block ((writer), (buf), (size)) -#define TRACE_WRITE_M_BLOCK_HEADER(writer, addr, size) \ - writer->ops->frame_ops->write_m_block_header ((writer), (addr), \ - (size)) -#define TRACE_WRITE_M_BLOCK_MEMORY(writer, buf, size) \ - writer->ops->frame_ops->write_m_block_memory ((writer), (buf), \ - (size)) -#define TRACE_WRITE_V_BLOCK(writer, num, val) \ - writer->ops->frame_ops->write_v_block ((writer), (num), (val)) - -/* Save tracepoint data to file named FILENAME through WRITER. WRITER - determines the trace file format. If TARGET_DOES_SAVE is non-zero, - the save is performed on the target, otherwise GDB obtains all trace - data and saves it locally. */ - -static void -trace_save (const char *filename, struct trace_file_writer *writer, - int target_does_save) -{ - struct trace_status *ts = current_trace_status (); - int status; - struct uploaded_tp *uploaded_tps = NULL, *utp; - struct uploaded_tsv *uploaded_tsvs = NULL, *utsv; - - ULONGEST offset = 0; - gdb_byte buf[MAX_TRACE_UPLOAD]; -#define MAX_TRACE_UPLOAD 2000 - int written; - enum bfd_endian byte_order = gdbarch_byte_order (target_gdbarch ()); - - /* If the target is to save the data to a file on its own, then just - send the command and be done with it. */ - if (target_does_save) - { - if (!writer->ops->target_save (writer, filename)) - error (_("Target failed to save trace data to '%s'."), - filename); - return; - } - - /* Get the trace status first before opening the file, so if the - target is losing, we can get out without touching files. */ - status = target_get_trace_status (ts); - - writer->ops->start (writer, filename); - - writer->ops->write_header (writer); - - /* Write descriptive info. */ - - /* Write out the size of a register block. */ - writer->ops->write_regblock_type (writer, trace_regblock_size); - - /* Write out status of the tracing run (aka "tstatus" info). */ - writer->ops->write_status (writer, ts); - - /* Note that we want to upload tracepoints and save those, rather - than simply writing out the local ones, because the user may have - changed tracepoints in GDB in preparation for a future tracing - run, or maybe just mass-deleted all types of breakpoints as part - of cleaning up. So as not to contaminate the session, leave the - data in its uploaded form, don't make into real tracepoints. */ - - /* Get trace state variables first, they may be checked when parsing - uploaded commands. */ - - target_upload_trace_state_variables (&uploaded_tsvs); - - for (utsv = uploaded_tsvs; utsv; utsv = utsv->next) - writer->ops->write_uploaded_tsv (writer, utsv); - - free_uploaded_tsvs (&uploaded_tsvs); - - target_upload_tracepoints (&uploaded_tps); - - for (utp = uploaded_tps; utp; utp = utp->next) - target_get_tracepoint_status (NULL, utp); - - for (utp = uploaded_tps; utp; utp = utp->next) - writer->ops->write_uploaded_tp (writer, utp); - - free_uploaded_tps (&uploaded_tps); - - /* Mark the end of the definition section. */ - writer->ops->write_definition_end (writer); - - /* Get and write the trace data proper. */ - while (1) - { - LONGEST gotten = 0; - - /* The writer supports writing the contents of trace buffer - directly to trace file. Don't parse the contents of trace - buffer. */ - if (writer->ops->write_trace_buffer != NULL) - { - /* We ask for big blocks, in the hopes of efficiency, but - will take less if the target has packet size limitations - or some such. */ - gotten = target_get_raw_trace_data (buf, offset, - MAX_TRACE_UPLOAD); - if (gotten < 0) - error (_("Failure to get requested trace buffer data")); - /* No more data is forthcoming, we're done. */ - if (gotten == 0) - break; - - writer->ops->write_trace_buffer (writer, buf, gotten); - - offset += gotten; - } - else - { - uint16_t tp_num; - uint32_t tf_size; - /* Parse the trace buffers according to how data are stored - in trace buffer in GDBserver. */ - - gotten = target_get_raw_trace_data (buf, offset, 6); - - if (gotten == 0) - break; - - /* Read the first six bytes in, which is the tracepoint - number and trace frame size. */ - tp_num = (uint16_t) - extract_unsigned_integer (&buf[0], 2, byte_order); - - tf_size = (uint32_t) - extract_unsigned_integer (&buf[2], 4, byte_order); - - writer->ops->frame_ops->start (writer, tp_num); - gotten = 6; - - if (tf_size > 0) - { - unsigned int block; - - offset += 6; - - for (block = 0; block < tf_size; ) - { - gdb_byte block_type; - - /* We'll fetch one block each time, in order to - handle the extremely large 'M' block. We first - fetch one byte to get the type of the block. */ - gotten = target_get_raw_trace_data (buf, offset, 1); - if (gotten < 1) - error (_("Failure to get requested trace buffer data")); - - gotten = 1; - block += 1; - offset += 1; - - block_type = buf[0]; - switch (block_type) - { - case 'R': - gotten - = target_get_raw_trace_data (buf, offset, - trace_regblock_size); - if (gotten < trace_regblock_size) - error (_("Failure to get requested trace" - " buffer data")); - - TRACE_WRITE_R_BLOCK (writer, buf, - trace_regblock_size); - break; - case 'M': - { - unsigned short mlen; - ULONGEST addr; - LONGEST t; - int j; - - t = target_get_raw_trace_data (buf,offset, 10); - if (t < 10) - error (_("Failure to get requested trace" - " buffer data")); - - offset += 10; - block += 10; - - gotten = 0; - addr = (ULONGEST) - extract_unsigned_integer (buf, 8, - byte_order); - mlen = (unsigned short) - extract_unsigned_integer (&buf[8], 2, - byte_order); - - TRACE_WRITE_M_BLOCK_HEADER (writer, addr, - mlen); - - /* The memory contents in 'M' block may be - very large. Fetch the data from the target - and write them into file one by one. */ - for (j = 0; j < mlen; ) - { - unsigned int read_length; - - if (mlen - j > MAX_TRACE_UPLOAD) - read_length = MAX_TRACE_UPLOAD; - else - read_length = mlen - j; - - t = target_get_raw_trace_data (buf, - offset + j, - read_length); - if (t < read_length) - error (_("Failure to get requested" - " trace buffer data")); - - TRACE_WRITE_M_BLOCK_MEMORY (writer, buf, - read_length); - - j += read_length; - gotten += read_length; - } - - break; - } - case 'V': - { - int vnum; - LONGEST val; - - gotten - = target_get_raw_trace_data (buf, offset, - 12); - if (gotten < 12) - error (_("Failure to get requested" - " trace buffer data")); - - vnum = (int) extract_signed_integer (buf, - 4, - byte_order); - val - = extract_signed_integer (&buf[4], 8, - byte_order); - - TRACE_WRITE_V_BLOCK (writer, vnum, val); - } - break; - default: - error (_("Unknown block type '%c' (0x%x) in" - " trace frame"), - block_type, block_type); - } - - block += gotten; - offset += gotten; - } - } - else - offset += gotten; - - writer->ops->frame_ops->end (writer); - } - } - - writer->ops->end (writer); -} - -/* Return a trace writer for TFILE format. */ - -static struct trace_file_writer * -tfile_trace_file_writer_new (void) -{ - struct tfile_trace_file_writer *writer - = xmalloc (sizeof (struct tfile_trace_file_writer)); - - writer->base.ops = &tfile_write_ops; - writer->fp = NULL; - writer->pathname = NULL; - - return (struct trace_file_writer *) writer; -} - -static void -trace_save_command (char *args, int from_tty) -{ - int target_does_save = 0; - char **argv; - char *filename = NULL; - struct cleanup *back_to; - int generate_ctf = 0; - struct trace_file_writer *writer = NULL; - - if (args == NULL) - error_no_arg (_("file in which to save trace data")); - - argv = gdb_buildargv (args); - back_to = make_cleanup_freeargv (argv); - - for (; *argv; ++argv) - { - if (strcmp (*argv, "-r") == 0) - target_does_save = 1; - if (strcmp (*argv, "-ctf") == 0) - generate_ctf = 1; - else if (**argv == '-') - error (_("unknown option `%s'"), *argv); - else - filename = *argv; - } - - if (!filename) - error_no_arg (_("file in which to save trace data")); - - if (generate_ctf) - writer = ctf_trace_file_writer_new (); - else - writer = tfile_trace_file_writer_new (); - - make_cleanup (trace_file_writer_xfree, writer); - - trace_save (filename, writer, target_does_save); - - if (from_tty) - printf_filtered (_("Trace data saved to %s '%s'.\n"), - generate_ctf ? "directory" : "file", filename); - - do_cleanups (back_to); -} - -/* Save the trace data to file FILENAME of tfile format. */ - -void -trace_save_tfile (const char *filename, int target_does_save) -{ - struct trace_file_writer *writer; - struct cleanup *back_to; - - writer = tfile_trace_file_writer_new (); - back_to = make_cleanup (trace_file_writer_xfree, writer); - trace_save (filename, writer, target_does_save); - do_cleanups (back_to); -} - -/* Save the trace data to dir DIRNAME of ctf format. */ - -void -trace_save_ctf (const char *dirname, int target_does_save) -{ - struct trace_file_writer *writer; - struct cleanup *back_to; - - writer = ctf_trace_file_writer_new (); - back_to = make_cleanup (trace_file_writer_xfree, writer); - - trace_save (dirname, writer, target_does_save); - do_cleanups (back_to); -} - -/* Tell the target what to do with an ongoing tracing run if GDB - disconnects for some reason. */ - -static void -set_disconnected_tracing (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, - struct cmd_list_element *c) -{ - target_set_circular_trace_buffer (circular_trace_buffer); -} - -static void -set_trace_buffer_size (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, - struct cmd_list_element *c) -{ - int ret; - - ret = target_set_trace_notes (trace_user, NULL, NULL); - - if (!ret) - warning (_("Target does not support trace notes, user ignored")); -} - -static void -set_trace_notes (char *args, int from_tty, - struct cmd_list_element *c) -{ - int ret; - - ret = target_set_trace_notes (NULL, trace_notes, NULL); - - if (!ret) - warning (_("Target does not support trace notes, note ignored")); -} - -static void -set_trace_stop_notes (char *args, int from_tty, - struct cmd_list_element *c) -{ - int ret; - - ret = target_set_trace_notes (NULL, NULL, trace_stop_notes); - - if (!ret) - warning (_("Target does not support trace notes, stop note ignored")); -} - -/* Convert the memory pointed to by mem into hex, placing result in buf. - * Return a pointer to the last char put in buf (null) - * "stolen" from sparc-stub.c - */ - -static const char hexchars[] = "0123456789abcdef"; - -static char * -mem2hex (gdb_byte *mem, char *buf, int count) -{ - gdb_byte ch; - - while (count-- > 0) - { - ch = *mem++; - - *buf++ = hexchars[ch >> 4]; - *buf++ = hexchars[ch & 0xf]; - } - - *buf = 0; - - return buf; -} - -int -get_traceframe_number (void) -{ - return traceframe_number; -} - -int -get_tracepoint_number (void) -{ - return tracepoint_number; -} - -/* Make the traceframe NUM be the current trace frame. Does nothing - if NUM is already current. */ - -void -set_current_traceframe (int num) -{ - int newnum; - - if (traceframe_number == num) - { - /* Nothing to do. */ - return; - } - - newnum = target_trace_find (tfind_number, num, 0, 0, NULL); - - if (newnum != num) - warning (_("could not change traceframe")); - - set_traceframe_num (newnum); - - /* Changing the traceframe changes our view of registers and of the - frame chain. */ - registers_changed (); - - clear_traceframe_info (); -} - -/* Make the traceframe NUM be the current trace frame, and do nothing - more. */ - -void -set_traceframe_number (int num) -{ - traceframe_number = num; -} - -/* 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 = arg; - - set_current_traceframe (old->traceframe_number); -} - -static void -restore_current_traceframe_cleanup_dtor (void *arg) -{ - struct current_traceframe_cleanup *old = arg; - - xfree (old); + xfree (old); } struct cleanup * make_cleanup_restore_current_traceframe (void) { - struct current_traceframe_cleanup *old; + struct current_traceframe_cleanup *old = + XNEW (struct current_traceframe_cleanup); - old = xmalloc (sizeof (struct current_traceframe_cleanup)); old->traceframe_number = traceframe_number; return make_cleanup_dtor (do_restore_current_traceframe_cleanup, old, restore_current_traceframe_cleanup_dtor); } -struct cleanup * -make_cleanup_restore_traceframe_number (void) -{ - return make_cleanup_restore_integer (&traceframe_number); -} - /* Given a number and address, return an uploaded tracepoint with that number, creating if necessary. */ @@ -3938,8 +3147,8 @@ get_uploaded_tp (int num, ULONGEST addr, struct uploaded_tp **utpp) for (utp = *utpp; utp; utp = utp->next) if (utp->number == num && utp->addr == addr) return utp; - utp = (struct uploaded_tp *) xmalloc (sizeof (struct uploaded_tp)); - memset (utp, 0, sizeof (struct uploaded_tp)); + + utp = XCNEW (struct uploaded_tp); utp->number = num; utp->addr = addr; utp->actions = NULL; @@ -3947,10 +3156,11 @@ get_uploaded_tp (int num, ULONGEST addr, struct uploaded_tp **utpp) utp->cmd_strings = NULL; utp->next = *utpp; *utpp = utp; + return utp; } -static void +void free_uploaded_tps (struct uploaded_tp **utpp) { struct uploaded_tp *next_one; @@ -3974,15 +3184,16 @@ get_uploaded_tsv (int num, struct uploaded_tsv **utsvp) for (utsv = *utsvp; utsv; utsv = utsv->next) if (utsv->number == num) return utsv; - utsv = (struct uploaded_tsv *) xmalloc (sizeof (struct uploaded_tsv)); - memset (utsv, 0, sizeof (struct uploaded_tsv)); + + utsv = XCNEW (struct uploaded_tsv); utsv->number = num; utsv->next = *utsvp; *utsvp = utsv; + return utsv; } -static void +void free_uploaded_tsvs (struct uploaded_tsv **utsvp) { struct uploaded_tsv *next_one; @@ -4205,216 +3416,27 @@ merge_uploaded_trace_state_variables (struct uploaded_tsv **uploaded_tsvs) { tsv = create_tsv_from_upload (utsv); if (info_verbose) - printf_filtered (_("Created trace state variable " - "$%s for target's variable %d.\n"), - tsv->name, utsv->number); - } - /* Give precedence to numberings that come from the target. */ - if (tsv) - tsv->number = utsv->number; - } - - /* 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; - - ++highest; - for (ix = 0; VEC_iterate (tsv_s, tvariables, ix, tsv); ++ix) - if (tsv->number == 0) - tsv->number = highest++; - - free_uploaded_tsvs (uploaded_tsvs); -} - -/* target tfile command */ - -static struct target_ops tfile_ops; - -/* Fill in tfile_ops with its defined operations and properties. */ - -#define TRACE_HEADER_SIZE 8 - -static char *trace_filename; -static int trace_fd = -1; -static off_t trace_frames_offset; -static off_t cur_offset; -static int cur_data_size; -int trace_regblock_size; - -static void tfile_interp_line (char *line, - struct uploaded_tp **utpp, - struct uploaded_tsv **utsvp); - -/* Read SIZE bytes into READBUF from the trace frame, starting at - TRACE_FD's current position. Note that this call `read' - underneath, hence it advances the file's seek position. Throws an - error if the `read' syscall fails, or less than SIZE bytes are - read. */ - -static void -tfile_read (gdb_byte *readbuf, int size) -{ - int gotten; - - gotten = read (trace_fd, readbuf, size); - if (gotten < 0) - perror_with_name (trace_filename); - else if (gotten < size) - error (_("Premature end of file while reading trace file")); -} - -static void -tfile_open (char *filename, int from_tty) -{ - volatile struct gdb_exception ex; - char *temp; - struct cleanup *old_chain; - int flags; - int scratch_chan; - char header[TRACE_HEADER_SIZE]; - char linebuf[1000]; /* Should be max remote packet size or so. */ - gdb_byte byte; - int bytes, i; - struct trace_status *ts; - struct uploaded_tp *uploaded_tps = NULL; - struct uploaded_tsv *uploaded_tsvs = NULL; - - target_preopen (from_tty); - if (!filename) - error (_("No trace file specified.")); - - filename = tilde_expand (filename); - if (!IS_ABSOLUTE_PATH(filename)) - { - temp = concat (current_directory, "/", filename, (char *) NULL); - xfree (filename); - filename = temp; - } - - old_chain = make_cleanup (xfree, filename); - - flags = O_BINARY | O_LARGEFILE; - flags |= O_RDONLY; - scratch_chan = gdb_open_cloexec (filename, flags, 0); - if (scratch_chan < 0) - perror_with_name (filename); - - /* Looks semi-reasonable. Toss the old trace file and work on the new. */ - - discard_cleanups (old_chain); /* Don't free filename any more. */ - unpush_target (&tfile_ops); - - trace_filename = xstrdup (filename); - trace_fd = scratch_chan; - - bytes = 0; - /* Read the file header and test for validity. */ - tfile_read ((gdb_byte *) &header, TRACE_HEADER_SIZE); - - bytes += TRACE_HEADER_SIZE; - if (!(header[0] == 0x7f - && (strncmp (header + 1, "TRACE0\n", 7) == 0))) - error (_("File is not a valid trace file.")); - - push_target (&tfile_ops); - - trace_regblock_size = 0; - ts = current_trace_status (); - /* We know we're working with a file. Record its name. */ - ts->filename = trace_filename; - /* Set defaults in case there is no status line. */ - ts->running_known = 0; - ts->stop_reason = trace_stop_reason_unknown; - ts->traceframe_count = -1; - ts->buffer_free = 0; - ts->disconnected_tracing = 0; - ts->circular_buffer = 0; - - TRY_CATCH (ex, RETURN_MASK_ALL) - { - /* Read through a section of newline-terminated lines that - define things like tracepoints. */ - i = 0; - while (1) - { - tfile_read (&byte, 1); - - ++bytes; - if (byte == '\n') - { - /* Empty line marks end of the definition section. */ - if (i == 0) - break; - linebuf[i] = '\0'; - i = 0; - tfile_interp_line (linebuf, &uploaded_tps, &uploaded_tsvs); - } - else - linebuf[i++] = byte; - if (i >= 1000) - error (_("Excessively long lines in trace file")); + printf_filtered (_("Created trace state variable " + "$%s for target's variable %d.\n"), + tsv->name, utsv->number); } - - /* Record the starting offset of the binary trace data. */ - trace_frames_offset = bytes; - - /* If we don't have a blocksize, we can't interpret the - traceframes. */ - if (trace_regblock_size == 0) - error (_("No register block size recorded in trace file")); - } - if (ex.reason < 0) - { - /* Remove the partially set up target. */ - unpush_target (&tfile_ops); - throw_exception (ex); + /* Give precedence to numberings that come from the target. */ + if (tsv) + tsv->number = utsv->number; } - if (ts->traceframe_count <= 0) - warning (_("No traceframes present in this file.")); - - /* Add the file's tracepoints and variables into the current mix. */ - - /* Get trace state variables first, they may be checked when parsing - uploaded commands. */ - merge_uploaded_trace_state_variables (&uploaded_tsvs); - - merge_uploaded_tracepoints (&uploaded_tps); -} - -/* Interpret the given line from the definitions part of the trace - file. */ + /* 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; -static void -tfile_interp_line (char *line, struct uploaded_tp **utpp, - struct uploaded_tsv **utsvp) -{ - char *p = line; + ++highest; + for (ix = 0; VEC_iterate (tsv_s, tvariables, ix, tsv); ++ix) + if (tsv->number == 0) + tsv->number = highest++; - if (strncmp (p, "R ", strlen ("R ")) == 0) - { - p += strlen ("R "); - trace_regblock_size = strtol (p, &p, 16); - } - else if (strncmp (p, "status ", strlen ("status ")) == 0) - { - p += strlen ("status "); - parse_trace_status (p, current_trace_status ()); - } - else if (strncmp (p, "tp ", strlen ("tp ")) == 0) - { - p += strlen ("tp "); - parse_tracepoint_definition (p, utpp); - } - else if (strncmp (p, "tsv ", strlen ("tsv ")) == 0) - { - p += strlen ("tsv "); - parse_tsv_definition (p, utsvp); - } - else - warning (_("Ignoring trace file definition \"%s\""), line); + free_uploaded_tsvs (uploaded_tsvs); } /* Parse the part of trace status syntax that is shared between @@ -4470,7 +3492,7 @@ Status line: '%s'\n"), p, line); ts->stop_reason = tracepoint_passcount; ts->stopping_tracepoint = val; } - else if (strncmp (p, stop_reason_names[tstop_command], p1 - p) == 0) + else if (strncmp (p, stop_reason_names[trace_stop_command], p1 - p) == 0) { p2 = strchr (++p1, ':'); if (!p2 || p2 > p3) @@ -4480,7 +3502,7 @@ Status line: '%s'\n"), p, line); } else if (p2 != p1) { - ts->stop_desc = xmalloc (strlen (line)); + ts->stop_desc = (char *) xmalloc (strlen (line)); end = hex2bin (p1, (gdb_byte *) ts->stop_desc, (p2 - p1) / 2); ts->stop_desc[end] = '\0'; } @@ -4488,7 +3510,7 @@ Status line: '%s'\n"), p, line); ts->stop_desc = xstrdup (""); p = unpack_varlen_hex (++p2, &val); - ts->stop_reason = tstop_command; + ts->stop_reason = trace_stop_command; } else if (strncmp (p, stop_reason_names[trace_disconnected], p1 - p) == 0) { @@ -4500,7 +3522,7 @@ Status line: '%s'\n"), p, line); p2 = strchr (++p1, ':'); if (p2 != p1) { - ts->stop_desc = xmalloc ((p2 - p1) / 2 + 1); + ts->stop_desc = (char *) xmalloc ((p2 - p1) / 2 + 1); end = hex2bin (p1, (gdb_byte *) ts->stop_desc, (p2 - p1) / 2); ts->stop_desc[end] = '\0'; } @@ -4554,7 +3576,7 @@ Status line: '%s'\n"), p, line); else if (strncmp (p, "username", p1 - p) == 0) { ++p1; - ts->user_name = xmalloc (strlen (p) / 2); + ts->user_name = (char *) xmalloc (strlen (p) / 2); end = hex2bin (p1, (gdb_byte *) ts->user_name, (p3 - p1) / 2); ts->user_name[end] = '\0'; p = p3; @@ -4562,7 +3584,7 @@ Status line: '%s'\n"), p, line); else if (strncmp (p, "notes", p1 - p) == 0) { ++p1; - ts->notes = xmalloc (strlen (p) / 2); + ts->notes = (char *) xmalloc (strlen (p) / 2); end = hex2bin (p1, (gdb_byte *) ts->notes, (p3 - p1) / 2); ts->notes[end] = '\0'; p = p3; @@ -4689,16 +3711,16 @@ parse_tracepoint_definition (char *line, struct uploaded_tp **utpp) p = unpack_varlen_hex (p, &xlen); p++; /* skip a colon */ - buf = alloca (strlen (line)); + buf = (char *) alloca (strlen (line)); end = hex2bin (p, (gdb_byte *) buf, strlen (p) / 2); buf[end] = '\0'; - if (strncmp (srctype, "at:", strlen ("at:")) == 0) + if (startswith (srctype, "at:")) utp->at_string = xstrdup (buf); - else if (strncmp (srctype, "cond:", strlen ("cond:")) == 0) + else if (startswith (srctype, "cond:")) utp->cond_string = xstrdup (buf); - else if (strncmp (srctype, "cmd:", strlen ("cmd:")) == 0) + else if (startswith (srctype, "cmd:")) VEC_safe_push (char_ptr, utp->cmd_strings, xstrdup (buf)); } else if (piece == 'V') @@ -4726,7 +3748,7 @@ parse_tsv_definition (char *line, struct uploaded_tsv **utsvp) int end; struct uploaded_tsv *utsv = NULL; - buf = alloca (strlen (line)); + buf = (char *) alloca (strlen (line)); p = line; p = unpack_varlen_hex (p, &num); @@ -4744,595 +3766,11 @@ parse_tsv_definition (char *line, struct uploaded_tsv **utsvp) utsv->name = xstrdup (buf); } -/* Close the trace file and generally clean up. */ - -static void -tfile_close (void) -{ - int pid; - - if (trace_fd < 0) - return; - - close (trace_fd); - trace_fd = -1; - xfree (trace_filename); - trace_filename = NULL; - - trace_reset_local_state (); -} - -static void -tfile_files_info (struct target_ops *t) -{ - printf_filtered ("\t`%s'\n", trace_filename); -} - -/* The trace status for a file is that tracing can never be run. */ - -static int -tfile_get_trace_status (struct trace_status *ts) -{ - /* Other bits of trace status were collected as part of opening the - trace files, so nothing to do here. */ - - return -1; -} - -static void -tfile_get_tracepoint_status (struct breakpoint *tp, struct uploaded_tp *utp) -{ - /* Other bits of trace status were collected as part of opening the - trace files, so nothing to do here. */ -} - -/* Given the position of a traceframe in the file, figure out what - address the frame was collected at. This would normally be the - value of a collected PC register, but if not available, we - improvise. */ - -static CORE_ADDR -tfile_get_traceframe_address (off_t tframe_offset) -{ - CORE_ADDR addr = 0; - short tpnum; - struct tracepoint *tp; - off_t saved_offset = cur_offset; - - /* FIXME dig pc out of collected registers. */ - - /* Fall back to using tracepoint address. */ - lseek (trace_fd, tframe_offset, SEEK_SET); - tfile_read ((gdb_byte *) &tpnum, 2); - tpnum = (short) extract_signed_integer ((gdb_byte *) &tpnum, 2, - gdbarch_byte_order - (target_gdbarch ())); - - tp = get_tracepoint_by_number_on_target (tpnum); - /* FIXME this is a poor heuristic if multiple locations. */ - if (tp && tp->base.loc) - addr = tp->base.loc->address; - - /* Restore our seek position. */ - cur_offset = saved_offset; - lseek (trace_fd, cur_offset, SEEK_SET); - return addr; -} - -/* Given a type of search and some parameters, scan the collection of - traceframes in the file looking for a match. When found, return - both the traceframe and tracepoint number, otherwise -1 for - each. */ - -static int -tfile_trace_find (enum trace_find_type type, int num, - CORE_ADDR addr1, CORE_ADDR addr2, int *tpp) -{ - short tpnum; - int tfnum = 0, found = 0; - unsigned int data_size; - struct tracepoint *tp; - off_t offset, tframe_offset; - CORE_ADDR tfaddr; - - if (num == -1) - { - if (tpp) - *tpp = -1; - return -1; - } - - lseek (trace_fd, trace_frames_offset, SEEK_SET); - offset = trace_frames_offset; - while (1) - { - tframe_offset = offset; - tfile_read ((gdb_byte *) &tpnum, 2); - tpnum = (short) extract_signed_integer ((gdb_byte *) &tpnum, 2, - gdbarch_byte_order - (target_gdbarch ())); - offset += 2; - if (tpnum == 0) - break; - tfile_read ((gdb_byte *) &data_size, 4); - data_size = (unsigned int) extract_unsigned_integer - ((gdb_byte *) &data_size, 4, - gdbarch_byte_order (target_gdbarch ())); - offset += 4; - - if (type == tfind_number) - { - /* Looking for a specific trace frame. */ - if (tfnum == num) - found = 1; - } - else - { - /* Start from the _next_ trace frame. */ - if (tfnum > traceframe_number) - { - switch (type) - { - case tfind_pc: - tfaddr = tfile_get_traceframe_address (tframe_offset); - if (tfaddr == addr1) - found = 1; - break; - case tfind_tp: - tp = get_tracepoint (num); - if (tp && tpnum == tp->number_on_target) - found = 1; - break; - case tfind_range: - tfaddr = tfile_get_traceframe_address (tframe_offset); - if (addr1 <= tfaddr && tfaddr <= addr2) - found = 1; - break; - case tfind_outside: - tfaddr = tfile_get_traceframe_address (tframe_offset); - if (!(addr1 <= tfaddr && tfaddr <= addr2)) - found = 1; - break; - default: - internal_error (__FILE__, __LINE__, _("unknown tfind type")); - } - } - } - - if (found) - { - if (tpp) - *tpp = tpnum; - cur_offset = offset; - cur_data_size = data_size; - - return tfnum; - } - /* Skip past the traceframe's data. */ - lseek (trace_fd, data_size, SEEK_CUR); - offset += data_size; - /* Update our own count of traceframes. */ - ++tfnum; - } - /* Did not find what we were looking for. */ - if (tpp) - *tpp = -1; - return -1; -} - -/* Prototype of the callback passed to tframe_walk_blocks. */ -typedef int (*walk_blocks_callback_func) (char blocktype, void *data); - -/* Callback for traceframe_walk_blocks, used to find a given block - type in a traceframe. */ - -static int -match_blocktype (char blocktype, void *data) -{ - char *wantedp = data; - - if (*wantedp == blocktype) - return 1; - - return 0; -} - -/* Walk over all traceframe block starting at POS offset from - CUR_OFFSET, and call CALLBACK for each block found, passing in DATA - unmodified. If CALLBACK returns true, this returns the position in - the traceframe where the block is found, relative to the start of - the traceframe (cur_offset). Returns -1 if no callback call - returned true, indicating that all blocks have been walked. */ - -static int -traceframe_walk_blocks (walk_blocks_callback_func callback, - int pos, void *data) -{ - /* Iterate through a traceframe's blocks, looking for a block of the - requested type. */ - - lseek (trace_fd, cur_offset + pos, SEEK_SET); - while (pos < cur_data_size) - { - unsigned short mlen; - char block_type; - - tfile_read ((gdb_byte *) &block_type, 1); - - ++pos; - - if ((*callback) (block_type, data)) - return pos; - - switch (block_type) - { - case 'R': - lseek (trace_fd, cur_offset + pos + trace_regblock_size, SEEK_SET); - pos += trace_regblock_size; - break; - case 'M': - lseek (trace_fd, cur_offset + pos + 8, SEEK_SET); - tfile_read ((gdb_byte *) &mlen, 2); - mlen = (unsigned short) - extract_unsigned_integer ((gdb_byte *) &mlen, 2, - gdbarch_byte_order - (target_gdbarch ())); - lseek (trace_fd, mlen, SEEK_CUR); - pos += (8 + 2 + mlen); - break; - case 'V': - lseek (trace_fd, cur_offset + pos + 4 + 8, SEEK_SET); - pos += (4 + 8); - break; - default: - error (_("Unknown block type '%c' (0x%x) in trace frame"), - block_type, block_type); - break; - } - } - - return -1; -} - -/* Convenience wrapper around traceframe_walk_blocks. Looks for the - position offset of a block of type TYPE_WANTED in the current trace - frame, starting at POS. Returns -1 if no such block was found. */ - -static int -traceframe_find_block_type (char type_wanted, int pos) -{ - return traceframe_walk_blocks (match_blocktype, pos, &type_wanted); -} - -/* Look for a block of saved registers in the traceframe, and get the - requested register from it. */ - -static void -tfile_fetch_registers (struct target_ops *ops, - struct regcache *regcache, int regno) -{ - struct gdbarch *gdbarch = get_regcache_arch (regcache); - int offset, regn, regsize, pc_regno; - gdb_byte *regs; - - /* An uninitialized reg size says we're not going to be - successful at getting register blocks. */ - if (!trace_regblock_size) - return; - - regs = alloca (trace_regblock_size); - - if (traceframe_find_block_type ('R', 0) >= 0) - { - tfile_read (regs, trace_regblock_size); - - /* Assume the block is laid out in GDB register number order, - each register with the size that it has in GDB. */ - offset = 0; - for (regn = 0; regn < gdbarch_num_regs (gdbarch); regn++) - { - regsize = register_size (gdbarch, regn); - /* Make sure we stay within block bounds. */ - if (offset + regsize >= trace_regblock_size) - break; - if (regcache_register_status (regcache, regn) == REG_UNKNOWN) - { - if (regno == regn) - { - regcache_raw_supply (regcache, regno, regs + offset); - break; - } - else if (regno == -1) - { - regcache_raw_supply (regcache, regn, regs + offset); - } - } - offset += regsize; - } - return; - } - - /* We get here if no register data has been found. Mark registers - as unavailable. */ - for (regn = 0; regn < gdbarch_num_regs (gdbarch); regn++) - regcache_raw_supply (regcache, regn, NULL); - - /* We can often usefully guess that the PC is going to be the same - as the address of the tracepoint. */ - pc_regno = gdbarch_pc_regnum (gdbarch); - if (pc_regno >= 0 && (regno == -1 || regno == pc_regno)) - { - struct tracepoint *tp = get_tracepoint (tracepoint_number); - - if (tp && tp->base.loc) - { - /* But don't try to guess if tracepoint is multi-location... */ - if (tp->base.loc->next) - { - warning (_("Tracepoint %d has multiple " - "locations, cannot infer $pc"), - tp->base.number); - return; - } - /* ... or does while-stepping. */ - if (tp->step_count > 0) - { - warning (_("Tracepoint %d does while-stepping, " - "cannot infer $pc"), - tp->base.number); - return; - } - - store_unsigned_integer (regs, register_size (gdbarch, pc_regno), - gdbarch_byte_order (gdbarch), - tp->base.loc->address); - regcache_raw_supply (regcache, pc_regno, regs); - } - } -} - -static LONGEST -tfile_xfer_partial (struct target_ops *ops, enum target_object object, - const char *annex, gdb_byte *readbuf, - const gdb_byte *writebuf, ULONGEST offset, LONGEST len) -{ - /* We're only doing regular memory for now. */ - if (object != TARGET_OBJECT_MEMORY) - return -1; - - if (readbuf == NULL) - error (_("tfile_xfer_partial: trace file is read-only")); - - if (traceframe_number != -1) - { - int pos = 0; - - /* Iterate through the traceframe's blocks, looking for - memory. */ - while ((pos = traceframe_find_block_type ('M', pos)) >= 0) - { - ULONGEST maddr, amt; - unsigned short mlen; - enum bfd_endian byte_order = gdbarch_byte_order (target_gdbarch ()); - - tfile_read ((gdb_byte *) &maddr, 8); - maddr = extract_unsigned_integer ((gdb_byte *) &maddr, 8, - byte_order); - tfile_read ((gdb_byte *) &mlen, 2); - mlen = (unsigned short) - extract_unsigned_integer ((gdb_byte *) &mlen, 2, byte_order); - - /* If the block includes the first part of the desired - range, return as much it has; GDB will re-request the - remainder, which might be in a different block of this - trace frame. */ - if (maddr <= offset && offset < (maddr + mlen)) - { - amt = (maddr + mlen) - offset; - if (amt > len) - amt = len; - - if (maddr != offset) - lseek (trace_fd, offset - maddr, SEEK_CUR); - tfile_read (readbuf, amt); - return amt; - } - - /* Skip over this block. */ - pos += (8 + 2 + mlen); - } - } - - /* It's unduly pedantic to refuse to look at the executable for - read-only pieces; so do the equivalent of readonly regions aka - QTro packet. */ - /* FIXME account for relocation at some point. */ - if (exec_bfd) - { - asection *s; - bfd_size_type size; - bfd_vma vma; - - for (s = exec_bfd->sections; s; s = s->next) - { - if ((s->flags & SEC_LOAD) == 0 - || (s->flags & SEC_READONLY) == 0) - continue; - - vma = s->vma; - size = bfd_get_section_size (s); - if (vma <= offset && offset < (vma + size)) - { - ULONGEST amt; - - amt = (vma + size) - offset; - if (amt > len) - amt = len; - - amt = bfd_get_section_contents (exec_bfd, s, - readbuf, offset - vma, amt); - return amt; - } - } - } - - /* Indicate failure to find the requested memory block. */ - return -1; -} - -/* Iterate through the blocks of a trace frame, looking for a 'V' - block with a matching tsv number. */ - -static int -tfile_get_trace_state_variable_value (int tsvnum, LONGEST *val) -{ - int pos; - int found = 0; - - /* Iterate over blocks in current frame and find the last 'V' - block in which tsv number is TSVNUM. In one trace frame, there - may be multiple 'V' blocks created for a given trace variable, - and the last matched 'V' block contains the updated value. */ - pos = 0; - while ((pos = traceframe_find_block_type ('V', pos)) >= 0) - { - int vnum; - - tfile_read ((gdb_byte *) &vnum, 4); - vnum = (int) extract_signed_integer ((gdb_byte *) &vnum, 4, - gdbarch_byte_order - (target_gdbarch ())); - if (tsvnum == vnum) - { - tfile_read ((gdb_byte *) val, 8); - *val = extract_signed_integer ((gdb_byte *) val, 8, - gdbarch_byte_order - (target_gdbarch ())); - found = 1; - } - pos += (4 + 8); - } - - return found; -} - -static int -tfile_has_all_memory (struct target_ops *ops) -{ - return 1; -} - -static int -tfile_has_memory (struct target_ops *ops) -{ - return 1; -} - -static int -tfile_has_stack (struct target_ops *ops) -{ - return traceframe_number != -1; -} - -static int -tfile_has_registers (struct target_ops *ops) -{ - return traceframe_number != -1; -} - -/* Callback for traceframe_walk_blocks. Builds a traceframe_info - object for the tfile target's current traceframe. */ - -static int -build_traceframe_info (char blocktype, void *data) -{ - struct traceframe_info *info = data; - - switch (blocktype) - { - case 'M': - { - struct mem_range *r; - ULONGEST maddr; - unsigned short mlen; - - tfile_read ((gdb_byte *) &maddr, 8); - maddr = extract_unsigned_integer ((gdb_byte *) &maddr, 8, - gdbarch_byte_order - (target_gdbarch ())); - tfile_read ((gdb_byte *) &mlen, 2); - mlen = (unsigned short) - extract_unsigned_integer ((gdb_byte *) &mlen, - 2, gdbarch_byte_order - (target_gdbarch ())); - - r = VEC_safe_push (mem_range_s, info->memory, NULL); - - r->start = maddr; - r->length = mlen; - break; - } - case 'V': - { - int vnum; - - tfile_read ((gdb_byte *) &vnum, 4); - VEC_safe_push (int, info->tvars, vnum); - } - case 'R': - case 'S': - { - break; - } - default: - warning (_("Unhandled trace block type (%d) '%c ' " - "while building trace frame info."), - blocktype, blocktype); - break; - } - - return 0; -} - -static struct traceframe_info * -tfile_traceframe_info (void) -{ - struct traceframe_info *info = XCNEW (struct traceframe_info); - - traceframe_walk_blocks (build_traceframe_info, 0, info); - return info; -} - -static void -init_tfile_ops (void) -{ - tfile_ops.to_shortname = "tfile"; - tfile_ops.to_longname = "Local trace dump file"; - tfile_ops.to_doc - = "Use a trace file as a target. Specify the filename of the trace file."; - tfile_ops.to_open = tfile_open; - tfile_ops.to_close = tfile_close; - tfile_ops.to_fetch_registers = tfile_fetch_registers; - tfile_ops.to_xfer_partial = tfile_xfer_partial; - tfile_ops.to_files_info = tfile_files_info; - tfile_ops.to_get_trace_status = tfile_get_trace_status; - tfile_ops.to_get_tracepoint_status = tfile_get_tracepoint_status; - tfile_ops.to_trace_find = tfile_trace_find; - tfile_ops.to_get_trace_state_variable_value - = tfile_get_trace_state_variable_value; - tfile_ops.to_stratum = process_stratum; - tfile_ops.to_has_all_memory = tfile_has_all_memory; - tfile_ops.to_has_memory = tfile_has_memory; - tfile_ops.to_has_stack = tfile_has_stack; - tfile_ops.to_has_registers = tfile_has_registers; - tfile_ops.to_traceframe_info = tfile_traceframe_info; - tfile_ops.to_magic = OPS_MAGIC; -} - void free_current_marker (void *arg) { - struct static_tracepoint_marker **marker_p = arg; + struct static_tracepoint_marker **marker_p + = (struct static_tracepoint_marker **) arg; if (*marker_p != NULL) { @@ -5367,14 +3805,14 @@ parse_static_tracepoint_marker_definition (char *line, char **pp, if (endp == NULL) error (_("bad marker definition: %s"), line); - marker->str_id = xmalloc (endp - p + 1); + 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->extra = xmalloc (strlen (p) + 1); + marker->extra = (char *) xmalloc (strlen (p) + 1); end = hex2bin (p, (gdb_byte *) marker->extra, strlen (p) / 2); marker->extra[end] = '\0'; @@ -5399,7 +3837,6 @@ static void print_one_static_tracepoint_marker (int count, struct static_tracepoint_marker *marker) { - struct command_line *l; struct symbol *sym; char wrap_indent[80]; @@ -5420,13 +3857,13 @@ print_one_static_tracepoint_marker (int count, /* A counter field to help readability. This is not a stable identifier! */ - ui_out_field_int (uiout, "count", count); + uiout->field_int ("count", count); - ui_out_field_string (uiout, "marker-id", marker->str_id); + uiout->field_string ("marker-id", marker->str_id); - ui_out_field_fmt (uiout, "enabled", "%c", + uiout->field_fmt ("enabled", "%c", !VEC_empty (breakpoint_p, tracepoints) ? 'y' : 'n'); - ui_out_spaces (uiout, 2); + uiout->spaces (2); strcpy (wrap_indent, " "); @@ -5437,49 +3874,49 @@ print_one_static_tracepoint_marker (int count, strcpy (extra_field_indent, " "); - ui_out_field_core_addr (uiout, "addr", marker->gdbarch, marker->address); + uiout->field_core_addr ("addr", marker->gdbarch, marker->address); sal = find_pc_line (marker->address, 0); sym = find_pc_sect_function (marker->address, NULL); if (sym) { - ui_out_text (uiout, "in "); - ui_out_field_string (uiout, "func", + uiout->text ("in "); + uiout->field_string ("func", SYMBOL_PRINT_NAME (sym)); - ui_out_wrap_hint (uiout, wrap_indent); - ui_out_text (uiout, " at "); + uiout->wrap_hint (wrap_indent); + uiout->text (" at "); } else - ui_out_field_skip (uiout, "func"); + uiout->field_skip ("func"); if (sal.symtab != NULL) { - ui_out_field_string (uiout, "file", + uiout->field_string ("file", symtab_to_filename_for_display (sal.symtab)); - ui_out_text (uiout, ":"); + uiout->text (":"); - if (ui_out_is_mi_like_p (uiout)) + if (uiout->is_mi_like_p ()) { const char *fullname = symtab_to_fullname (sal.symtab); - ui_out_field_string (uiout, "fullname", fullname); + uiout->field_string ("fullname", fullname); } else - ui_out_field_skip (uiout, "fullname"); + uiout->field_skip ("fullname"); - ui_out_field_int (uiout, "line", sal.line); + uiout->field_int ("line", sal.line); } else { - ui_out_field_skip (uiout, "fullname"); - ui_out_field_skip (uiout, "line"); + uiout->field_skip ("fullname"); + uiout->field_skip ("line"); } - ui_out_text (uiout, "\n"); - ui_out_text (uiout, extra_field_indent); - ui_out_text (uiout, _("Data: \"")); - ui_out_field_string (uiout, "extra-data", marker->extra); - ui_out_text (uiout, "\"\n"); + uiout->text ("\n"); + uiout->text (extra_field_indent); + uiout->text (_("Data: \"")); + uiout->field_string ("extra-data", marker->extra); + uiout->text ("\"\n"); if (!VEC_empty (breakpoint_p, tracepoints)) { @@ -5490,23 +3927,23 @@ print_one_static_tracepoint_marker (int count, cleanup_chain = make_cleanup_ui_out_tuple_begin_end (uiout, "tracepoints-at"); - ui_out_text (uiout, extra_field_indent); - ui_out_text (uiout, _("Probed by static tracepoints: ")); + uiout->text (extra_field_indent); + uiout->text (_("Probed by static tracepoints: ")); for (ix = 0; VEC_iterate(breakpoint_p, tracepoints, ix, b); ix++) { if (ix > 0) - ui_out_text (uiout, ", "); - ui_out_text (uiout, "#"); - ui_out_field_int (uiout, "tracepoint-id", b->number); + uiout->text (", "); + uiout->text ("#"); + uiout->field_int ("tracepoint-id", b->number); } do_cleanups (cleanup_chain); - if (ui_out_is_mi_like_p (uiout)) - ui_out_field_int (uiout, "number-of-tracepoints", + if (uiout->is_mi_like_p ()) + uiout->field_int ("number-of-tracepoints", VEC_length(breakpoint_p, tracepoints)); else - ui_out_text (uiout, "\n"); + uiout->text ("\n"); } VEC_free (breakpoint_p, tracepoints); @@ -5532,18 +3969,18 @@ info_static_tracepoint_markers_command (char *arg, int from_tty) = make_cleanup_ui_out_table_begin_end (uiout, 5, -1, "StaticTracepointMarkersTable"); - ui_out_table_header (uiout, 7, ui_left, "counter", "Cnt"); + uiout->table_header (7, ui_left, "counter", "Cnt"); - ui_out_table_header (uiout, 40, ui_left, "marker-id", "ID"); + uiout->table_header (40, ui_left, "marker-id", "ID"); - ui_out_table_header (uiout, 3, ui_left, "enabled", "Enb"); + uiout->table_header (3, ui_left, "enabled", "Enb"); if (gdbarch_addr_bit (target_gdbarch ()) <= 32) - ui_out_table_header (uiout, 10, ui_left, "addr", "Address"); + uiout->table_header (10, ui_left, "addr", "Address"); else - ui_out_table_header (uiout, 18, ui_left, "addr", "Address"); - ui_out_table_header (uiout, 40, ui_noalign, "what", "What"); + uiout->table_header (18, ui_left, "addr", "Address"); + uiout->table_header (40, ui_noalign, "what", "What"); - ui_out_table_body (uiout); + uiout->table_body (); markers = target_static_tracepoint_markers_by_strid (NULL); make_cleanup (VEC_cleanup (static_tracepoint_marker_p), &markers); @@ -5625,12 +4062,14 @@ traceframe_info_start_memory (struct gdb_xml_parser *parser, const struct gdb_xml_element *element, void *user_data, VEC(gdb_xml_value_s) *attributes) { - struct traceframe_info *info = user_data; + 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 = xml_find_attribute (attributes, "start")->value; - length_p = xml_find_attribute (attributes, "length")->value; + start_p + = (ULONGEST *) xml_find_attribute (attributes, "start")->value; + length_p + = (ULONGEST *) xml_find_attribute (attributes, "length")->value; r->start = *start_p; r->length = *length_p; @@ -5644,8 +4083,9 @@ traceframe_info_start_tvar (struct gdb_xml_parser *parser, void *user_data, VEC(gdb_xml_value_s) *attributes) { - struct traceframe_info *info = user_data; - const char *id_attrib = xml_find_attribute (attributes, "id")->value; + struct traceframe_info *info = (struct traceframe_info *) user_data; + const char *id_attrib + = (const char *) xml_find_attribute (attributes, "id")->value; int id = gdb_xml_parse_ulongest (parser, id_attrib); VEC_safe_push (int, info->tvars, id); @@ -5656,7 +4096,7 @@ traceframe_info_start_tvar (struct gdb_xml_parser *parser, static void free_result (void *p) { - struct traceframe_info *result = p; + struct traceframe_info *result = (struct traceframe_info *) p; free_traceframe_info (result); } @@ -5763,8 +4203,8 @@ traceframe_available_memory (VEC(mem_range_s) **result, nr = VEC_safe_push (mem_range_s, *result, NULL); - nr->start = max (lo1, lo2); - nr->length = min (hi1, hi2) - nr->start; + nr->start = std::max (lo1, lo2); + nr->length = std::min (hi1, hi2) - nr->start; } normalize_mem_ranges (*result); @@ -5805,15 +4245,9 @@ _initialize_tracepoint (void) _("Tracing of program execution without stopping the program."), &cmdlist); - add_com ("tdump", class_trace, trace_dump_command, + add_com ("tdump", class_trace, tdump_command, _("Print everything collected at the current tracepoint.")); - add_com ("tsave", class_trace, trace_save_command, _("\ -Save the trace data to a file.\n\ -Use the '-ctf' option to save the data to CTF format.\n\ -Use the '-r' option to direct the target to save directly to the file,\n\ -using its own filesystem.")); - c = add_com ("tvariable", class_trace, trace_variable_command,_("\ Define a trace state variable.\n\ Argument is a $-prefixed name, optionally followed\n\ @@ -5836,58 +4270,58 @@ Status of trace state variables and their values.\n\ List target static tracepoints markers.\n\ ")); - add_prefix_cmd ("tfind", class_trace, trace_find_command, _("\ + add_prefix_cmd ("tfind", class_trace, tfind_command, _("\ Select a trace frame;\n\ No argument means forward by one frame; '-' means backward by one frame."), &tfindlist, "tfind ", 1, &cmdlist); - add_cmd ("outside", class_trace, trace_find_outside_command, _("\ + add_cmd ("outside", class_trace, tfind_outside_command, _("\ Select a trace frame whose PC is outside the given range (exclusive).\n\ Usage: tfind outside addr1, addr2"), &tfindlist); - add_cmd ("range", class_trace, trace_find_range_command, _("\ + add_cmd ("range", class_trace, tfind_range_command, _("\ Select a trace frame whose PC is in the given range (inclusive).\n\ Usage: tfind range addr1,addr2"), &tfindlist); - add_cmd ("line", class_trace, trace_find_line_command, _("\ + add_cmd ("line", class_trace, tfind_line_command, _("\ Select a trace frame by source line.\n\ Argument can be a line number (with optional source file),\n\ a function name, or '*' followed by an address.\n\ Default argument is 'the next source line that was traced'."), &tfindlist); - add_cmd ("tracepoint", class_trace, trace_find_tracepoint_command, _("\ + add_cmd ("tracepoint", class_trace, tfind_tracepoint_command, _("\ Select a trace frame by tracepoint number.\n\ Default is the tracepoint for the current trace frame."), &tfindlist); - add_cmd ("pc", class_trace, trace_find_pc_command, _("\ + add_cmd ("pc", class_trace, tfind_pc_command, _("\ Select a trace frame by PC.\n\ Default is the current PC, or the PC of the current trace frame."), &tfindlist); - add_cmd ("end", class_trace, trace_find_end_command, _("\ + add_cmd ("end", class_trace, tfind_end_command, _("\ De-select any trace frame and resume 'live' debugging."), &tfindlist); add_alias_cmd ("none", "end", class_trace, 0, &tfindlist); - add_cmd ("start", class_trace, trace_find_start_command, + add_cmd ("start", class_trace, tfind_start_command, _("Select the first trace frame in the trace buffer."), &tfindlist); - add_com ("tstatus", class_trace, trace_status_command, + add_com ("tstatus", class_trace, tstatus_command, _("Display the status of the current trace data collection.")); - add_com ("tstop", class_trace, trace_stop_command, _("\ + add_com ("tstop", class_trace, tstop_command, _("\ Stop trace data collection.\n\ Usage: tstop [ ... ]\n\ Any arguments supplied are recorded with the trace as a stop reason and\n\ reported by tstatus (if the target supports trace notes).")); - add_com ("tstart", class_trace, trace_start_command, _("\ + add_com ("tstart", class_trace, tstart_command, _("\ Start trace data collection.\n\ Usage: tstart [ ... ]\n\ Any arguments supplied are recorded with the trace as a note and\n\ @@ -5928,7 +4362,7 @@ Accepts a comma-separated list of (one or more) expressions.\n\ The result of each evaluation will be discarded.\n\ Note: this command can only be used in a tracepoint \"actions\" list.")); - add_com ("actions", class_trace, trace_actions_command, _("\ + add_com ("actions", class_trace, actions_command, _("\ Specify the actions to be taken at a tracepoint.\n\ Tracepoint actions may include collecting of specified data,\n\ single-stepping, or enabling/disabling other tracepoints,\n\ @@ -5996,8 +4430,4 @@ 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); - - init_tfile_ops (); - - add_target_with_completer (&tfile_ops, filename_completer); }