X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=gdb%2Ftracepoint.c;h=3484d7ad3b61aea01dbeccaac4f479910fc15920;hb=3c853d931322f71b01a217f05bb8302f32a263d2;hp=1e0feecf7c0c3835d33319fd2ff36ee7384143ed;hpb=35c9c7ba77c07c52aa0c81e62919bb3984b86c3a;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/tracepoint.c b/gdb/tracepoint.c index 1e0feecf7c..3484d7ad3b 100644 --- a/gdb/tracepoint.c +++ b/gdb/tracepoint.c @@ -46,7 +46,8 @@ #include "gdbthread.h" #include "stack.h" #include "gdbcore.h" - +#include "remote.h" +#include "source.h" #include "ax.h" #include "ax-gdb.h" @@ -382,10 +383,9 @@ trace_variable_command (char *args, int from_tty) void delete_trace_variable_command (char *args, int from_tty) { - int i, ix; + int ix; char **argv; struct cleanup *back_to; - struct trace_state_variable *tsv; if (args == NULL) { @@ -398,12 +398,12 @@ delete_trace_variable_command (char *args, int from_tty) argv = gdb_buildargv (args); back_to = make_cleanup_freeargv (argv); - for (i = 0; argv[i] != NULL; i++) + for (ix = 0; argv[ix] != NULL; ix++) { - if (*argv[i] == '$') - delete_trace_state_variable (argv[i] + 1); + if (*argv[ix] == '$') + delete_trace_state_variable (argv[ix] + 1); else - warning (_("Name \"%s\" not prefixed with '$', ignoring"), argv[i]); + warning (_("Name \"%s\" not prefixed with '$', ignoring"), argv[ix]); } do_cleanups (back_to); @@ -446,7 +446,7 @@ tvariables_info_1 (void) back_to2 = make_cleanup_ui_out_tuple_begin_end (uiout, "variable"); - name = concat ("$", tsv->name, NULL); + 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)); @@ -622,9 +622,10 @@ validate_actionline (char **line, struct breakpoint *t) if (*p == '$') /* look for special pseudo-symbols */ { - if ((0 == strncasecmp ("reg", p + 1, 3)) || - (0 == strncasecmp ("arg", p + 1, 3)) || - (0 == strncasecmp ("loc", p + 1, 3))) + if (0 == strncasecmp ("reg", p + 1, 3) + || 0 == strncasecmp ("arg", p + 1, 3) + || 0 == strncasecmp ("loc", p + 1, 3) + || 0 == strncasecmp ("_sdata", p + 1, 6)) { p = strchr (p, ','); continue; @@ -747,6 +748,9 @@ struct collection_list long next_aexpr_elt; struct agent_expr **aexpr_list; + /* True is the user requested a collection of "$_sdata", "static + tracepoint data". */ + int strace_data; } tracepoint_list, stepping_list; @@ -1086,6 +1090,14 @@ add_local_symbols (struct collection_list *collect, } } +static void +add_static_trace_data (struct collection_list *collection) +{ + 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) @@ -1100,6 +1112,7 @@ clear_collection_list (struct collection_list *list) } list->next_aexpr_elt = 0; memset (list->regs_mask, 0, sizeof (list->regs_mask)); + list->strace_data = 0; } /* reduce a collection list to string form (for gdb protocol) */ @@ -1114,9 +1127,19 @@ stringify_collection_list (struct collection_list *list, char *string) char *end; long i; - count = 1 + list->next_memrange + list->next_aexpr_elt + 1; + count = 1 + 1 + list->next_memrange + list->next_aexpr_elt + 1; str_list = (char *(*)[]) xmalloc (count * sizeof (char *)); + if (list->strace_data) + { + if (info_verbose) + printf_filtered ("\nCollecting static trace data\n"); + end = temp_buf; + *end++ = 'L'; + (*str_list)[ndx] = savestring (temp_buf, end - temp_buf); + ndx++; + } + for (i = sizeof (list->regs_mask) - 1; i > 0; i--) if (list->regs_mask[i] != 0) /* skip leading zeroes in regs_mask */ break; @@ -1226,7 +1249,6 @@ encode_actions_1 (struct command_line *action, { char *action_exp; struct expression *exp = NULL; - struct command_line *actions; int i; struct value *tempval; struct cmd_list_element *cmd; @@ -1277,6 +1299,11 @@ encode_actions_1 (struct command_line *action, 'L'); action_exp = strchr (action_exp, ','); /* more? */ } + else if (0 == strncasecmp ("$_sdata", action_exp, 7)) + { + add_static_trace_data (collect); + action_exp = strchr (action_exp, ','); /* more? */ + } else { unsigned long addr, len; @@ -1370,7 +1397,6 @@ encode_actions_1 (struct command_line *action, action_exp++; { - unsigned long addr, len; struct cleanup *old_chain = NULL; struct cleanup *old_chain1 = NULL; @@ -1401,8 +1427,8 @@ encode_actions_1 (struct command_line *action, here. */ gdb_assert (stepping_list); - encode_actions_1 (action->body_list[0], t, tloc, frame_reg, frame_offset, - stepping_list, NULL); + encode_actions_1 (action->body_list[0], t, tloc, frame_reg, + frame_offset, stepping_list, NULL); } else error (_("Invalid tracepoint command '%s'"), action->line); @@ -1477,7 +1503,7 @@ add_aexpr (struct collection_list *collect, struct agent_expr *aexpr) { collect->aexpr_list = xrealloc (collect->aexpr_list, - 2 * collect->aexpr_listsize * sizeof (struct agent_expr *)); + 2 * collect->aexpr_listsize * sizeof (struct agent_expr *)); collect->aexpr_listsize *= 2; } collect->aexpr_list[collect->next_aexpr_elt] = aexpr; @@ -1488,12 +1514,11 @@ add_aexpr (struct collection_list *collect, struct agent_expr *aexpr) void start_tracing (void) { - char buf[2048]; VEC(breakpoint_p) *tp_vec = NULL; int ix; struct breakpoint *t; struct trace_state_variable *tsv; - int any_enabled = 0; + int any_enabled = 0, num_to_download = 0; tp_vec = all_tracepoints (); @@ -1507,10 +1532,15 @@ start_tracing (void) for (ix = 0; VEC_iterate (breakpoint_p, tp_vec, ix, t); ix++) { if (t->enable_state == bp_enabled) - { - any_enabled = 1; - break; - } + any_enabled = 1; + + if ((t->type == bp_fast_tracepoint + ? may_insert_fast_tracepoints + : may_insert_tracepoints)) + ++num_to_download; + else + warning (_("May not insert %stracepoints, skipping tracepoint %d"), + (t->type == bp_fast_tracepoint ? "fast " : ""), t->number); } /* No point in tracing with only disabled tracepoints. */ @@ -1520,10 +1550,21 @@ start_tracing (void) error (_("No tracepoints enabled, not starting trace")); } + if (num_to_download <= 0) + { + VEC_free (breakpoint_p, tp_vec); + error (_("No tracepoints that may be downloaded, not starting trace")); + } + target_trace_init (); for (ix = 0; VEC_iterate (breakpoint_p, tp_vec, ix, t); ix++) { + if ((t->type == bp_fast_tracepoint + ? !may_insert_fast_tracepoints + : !may_insert_tracepoints)) + continue; + t->number_on_target = 0; target_download_tracepoint (t); t->number_on_target = t->number; @@ -1715,7 +1756,6 @@ trace_status_mi (int on_stop) { struct trace_status *ts = current_trace_status (); int status; - char *string_status; status = target_get_trace_status (ts); @@ -1850,7 +1890,6 @@ tfind_1 (enum trace_find_type type, int num, { int target_frameno = -1, target_tracept = -1; struct frame_id old_frame_id = null_frame_id; - char *reply; struct breakpoint *tp; /* Only try to get the current stack frame if we have a chance of @@ -2049,7 +2088,6 @@ static void trace_find_pc_command (char *args, int from_tty) { CORE_ADDR pc; - char tmp[40]; if (current_trace_status ()->running && !current_trace_status ()->from_file) error ("May not look at trace frames while trace is running."); @@ -2107,7 +2145,6 @@ trace_find_line_command (char *args, int from_tty) struct symtabs_and_lines sals; struct symtab_and_line sal; struct cleanup *old_chain; - char startpc_str[40], endpc_str[40]; if (current_trace_status ()->running && !current_trace_status ()->from_file) error ("May not look at trace frames while trace is running."); @@ -2171,7 +2208,6 @@ static void trace_find_range_command (char *args, int from_tty) { static CORE_ADDR start, stop; - char start_str[40], stop_str[40]; char *tmp; if (current_trace_status ()->running && !current_trace_status ()->from_file) @@ -2205,7 +2241,6 @@ static void trace_find_outside_command (char *args, int from_tty) { CORE_ADDR start, stop; - char start_str[40], stop_str[40]; char *tmp; if (current_trace_status ()->running && !current_trace_status ()->from_file) @@ -2632,6 +2667,7 @@ trace_save (const char *filename, int target_does_save) if (ts->stop_reason == tracepoint_error) { char *buf = (char *) alloca (strlen (ts->error_desc) * 2 + 1); + bin2hex ((gdb_byte *) ts->error_desc, buf, 0); fprintf (fp, ":%s", buf); } @@ -2698,7 +2734,7 @@ trace_save (const char *filename, int target_does_save) for (a = 0; VEC_iterate (char_ptr, utp->actions, a, act); ++a) fprintf (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->actions, a, act); ++a) + for (a = 0; VEC_iterate (char_ptr, utp->step_actions, a, act); ++a) fprintf (fp, "tp S%x:%s:%s\n", utp->number, phex_nz (utp->addr, sizeof (utp->addr)), act); if (utp->at_string) @@ -3103,13 +3139,17 @@ merge_uploaded_trace_state_variables (struct uploaded_tsv **uploaded_tsvs) { tsv = find_matching_tsv (utsv); if (tsv) - printf_filtered (_("Assuming trace state variable $%s is same as target's variable %d.\n"), - tsv->name, utsv->number); + { + if (info_verbose) + printf_filtered (_("Assuming trace state variable $%s is same as target's variable %d.\n"), + tsv->name, utsv->number); + } else { tsv = create_tsv_from_upload (utsv); - printf_filtered (_("Created trace state variable $%s for target's variable %d.\n"), - tsv->name, utsv->number); + 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) @@ -3171,7 +3211,7 @@ tfile_open (char *filename, int from_tty) filename = tilde_expand (filename); if (!IS_ABSOLUTE_PATH(filename)) { - temp = concat (current_directory, "/", filename, (char *)NULL); + temp = concat (current_directory, "/", filename, (char *) NULL); xfree (filename); filename = temp; } @@ -3316,8 +3356,6 @@ tfile_interp_line (char *line, /* Parse the part of trace status syntax that is shared between the remote protocol and the trace file reader. */ -extern char *unpack_varlen_hex (char *buff, ULONGEST *result); - void parse_trace_status (char *line, struct trace_status *ts) { @@ -3438,9 +3476,9 @@ parse_tracepoint_definition (char *line, struct uploaded_tp **utpp) char *p; char piece; ULONGEST num, addr, step, pass, orig_size, xlen, start; - int enabled, i, end; + int enabled, end; enum bptype type; - char *cond, *srctype, *src, *buf; + char *cond, *srctype, *buf; struct uploaded_tp *utp = NULL; p = line; @@ -3470,6 +3508,11 @@ parse_tracepoint_definition (char *line, struct uploaded_tp **utpp) p++; p = unpack_varlen_hex (p, &orig_size); } + else if (*p == 'S') + { + type = bp_static_tracepoint; + p++; + } else if (*p == 'X') { p++; @@ -3622,6 +3665,9 @@ tfile_get_traceframe_address (off_t tframe_offset) perror_with_name (trace_filename); else if (gotten < 2) error (_("Premature end of file while reading trace file")); + 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 */ @@ -3645,7 +3691,7 @@ tfile_trace_find (enum trace_find_type type, int num, { short tpnum; int tfnum = 0, found = 0, gotten; - int data_size; + unsigned int data_size; struct breakpoint *tp; off_t offset, tframe_offset; ULONGEST tfaddr; @@ -3660,6 +3706,9 @@ tfile_trace_find (enum trace_find_type type, int num, perror_with_name (trace_filename); else if (gotten < 2) error (_("Premature end of file while reading trace file")); + tpnum = (short) extract_signed_integer ((gdb_byte *) &tpnum, 2, + gdbarch_byte_order + (target_gdbarch)); offset += 2; if (tpnum == 0) break; @@ -3668,6 +3717,9 @@ tfile_trace_find (enum trace_find_type type, int num, perror_with_name (trace_filename); else if (gotten < 4) error (_("Premature end of file while reading trace file")); + data_size = (unsigned int) extract_unsigned_integer + ((gdb_byte *) &data_size, 4, + gdbarch_byte_order (target_gdbarch)); offset += 4; switch (type) { @@ -3727,7 +3779,7 @@ tfile_fetch_registers (struct target_ops *ops, { struct gdbarch *gdbarch = get_regcache_arch (regcache); char block_type; - int i, pos, offset, regn, regsize, gotten, pc_regno; + int pos, offset, regn, regsize, gotten, pc_regno; unsigned short mlen; char *regs; @@ -3789,6 +3841,10 @@ tfile_fetch_registers (struct target_ops *ops, perror_with_name (trace_filename); else if (gotten < 2) error (_("Premature end of file while reading trace file")); + 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; @@ -3881,12 +3937,18 @@ tfile_xfer_partial (struct target_ops *ops, enum target_object object, perror_with_name (trace_filename); else if (gotten < 8) error (_("Premature end of file while reading trace file")); - + maddr = extract_unsigned_integer ((gdb_byte *) &maddr, 8, + gdbarch_byte_order + (target_gdbarch)); gotten = read (trace_fd, &mlen, 2); if (gotten < 0) perror_with_name (trace_filename); else if (gotten < 2) error (_("Premature end of file while reading trace file")); + mlen = (unsigned short) + extract_unsigned_integer ((gdb_byte *) &mlen, 2, + gdbarch_byte_order + (target_gdbarch)); /* 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 @@ -3929,7 +3991,7 @@ tfile_xfer_partial (struct target_ops *ops, enum target_object object, { asection *s; bfd_size_type size; - bfd_vma lma; + bfd_vma vma; for (s = exec_bfd->sections; s; s = s->next) { @@ -3937,16 +3999,16 @@ tfile_xfer_partial (struct target_ops *ops, enum target_object object, (s->flags & SEC_READONLY) == 0) continue; - lma = s->lma; + vma = s->vma; size = bfd_get_section_size (s); - if (lma <= offset && offset < (lma + size)) + if (vma <= offset && offset < (vma + size)) { - amt = (lma + size) - offset; + amt = (vma + size) - offset; if (amt > len) amt = len; amt = bfd_get_section_contents (exec_bfd, s, - readbuf, offset - lma, amt); + readbuf, offset - vma, amt); return amt; } } @@ -3989,6 +4051,10 @@ tfile_get_trace_state_variable_value (int tsvnum, LONGEST *val) perror_with_name (trace_filename); else if (gotten < 2) error (_("Premature end of file while reading trace file")); + 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; @@ -3998,6 +4064,9 @@ tfile_get_trace_state_variable_value (int tsvnum, LONGEST *val) perror_with_name (trace_filename); else if (gotten < 4) error (_("Premature end of file while reading trace file")); + vnum = (int) extract_signed_integer ((gdb_byte *) &vnum, 4, + gdbarch_byte_order + (target_gdbarch)); if (tsvnum == vnum) { gotten = read (trace_fd, val, 8); @@ -4005,6 +4074,9 @@ tfile_get_trace_state_variable_value (int tsvnum, LONGEST *val) perror_with_name (trace_filename); else if (gotten < 8) error (_("Premature end of file while reading trace file")); + *val = extract_signed_integer ((gdb_byte *)val, 8, + gdbarch_byte_order + (target_gdbarch)); return 1; } lseek (trace_fd, 8, SEEK_CUR); @@ -4059,8 +4131,6 @@ init_tfile_ops (void) tfile_ops.to_get_trace_status = tfile_get_trace_status; tfile_ops.to_trace_find = tfile_trace_find; tfile_ops.to_get_trace_state_variable_value = tfile_get_trace_state_variable_value; - /* core_stratum might seem more logical, but GDB doesn't like having - more than one core_stratum vector. */ tfile_ops.to_stratum = process_stratum; tfile_ops.to_has_all_memory = tfile_has_all_memory; tfile_ops.to_has_memory = tfile_has_memory; @@ -4069,12 +4139,266 @@ init_tfile_ops (void) tfile_ops.to_magic = OPS_MAGIC; } +/* Given a line of text defining a static tracepoint marker, parse it + into a "static tracepoint marker" object. Throws an error is + parsing fails. If PP is non-null, it points to one past the end of + the parsed marker definition. */ + +void +parse_static_tracepoint_marker_definition (char *line, char **pp, + struct static_tracepoint_marker *marker) +{ + char *p, *endp; + ULONGEST addr; + int end; + + p = line; + p = unpack_varlen_hex (p, &addr); + p++; /* skip a colon */ + + marker->gdbarch = target_gdbarch; + marker->address = (CORE_ADDR) addr; + + endp = strchr (p, ':'); + if (endp == NULL) + error (_("bad marker definition: %s"), line); + + marker->str_id = 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); + end = hex2bin (p, (gdb_byte *) marker->extra, strlen (p) / 2); + marker->extra[end] = '\0'; + + if (pp) + *pp = p; +} + +/* Release a static tracepoint marker's contents. Note that the + object itself isn't released here. There objects are usually on + the stack. */ + +void +release_static_tracepoint_marker (struct static_tracepoint_marker *marker) +{ + xfree (marker->str_id); + marker->str_id = NULL; +} + +/* Print MARKER to gdb_stdout. */ + +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]; + char extra_field_indent[80]; + struct ui_stream *stb = ui_out_stream_new (uiout); + struct cleanup *old_chain = make_cleanup_ui_out_stream_delete (stb); + struct cleanup *bkpt_chain; + VEC(breakpoint_p) *tracepoints; + + struct symtab_and_line sal; + + init_sal (&sal); + + sal.pc = marker->address; + + tracepoints = static_tracepoints_here (marker->address); + + bkpt_chain = make_cleanup_ui_out_tuple_begin_end (uiout, "marker"); + + /* A counter field to help readability. This is not a stable + identifier! */ + ui_out_field_int (uiout, "count", count); + + ui_out_field_string (uiout, "marker-id", marker->str_id); + + ui_out_field_fmt (uiout, "enabled", "%c", + !VEC_empty (breakpoint_p, tracepoints) ? 'y' : 'n'); + ui_out_spaces (uiout, 2); + + strcpy (wrap_indent, " "); + + if (gdbarch_addr_bit (marker->gdbarch) <= 32) + strcat (wrap_indent, " "); + else + strcat (wrap_indent, " "); + + strcpy (extra_field_indent, " "); + + ui_out_field_core_addr (uiout, "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", + SYMBOL_PRINT_NAME (sym)); + ui_out_wrap_hint (uiout, wrap_indent); + ui_out_text (uiout, " at "); + } + else + ui_out_field_skip (uiout, "func"); + + if (sal.symtab != NULL) + { + ui_out_field_string (uiout, "file", sal.symtab->filename); + ui_out_text (uiout, ":"); + + if (ui_out_is_mi_like_p (uiout)) + { + char *fullname = symtab_to_fullname (sal.symtab); + + if (fullname) + ui_out_field_string (uiout, "fullname", fullname); + } + else + ui_out_field_skip (uiout, "fullname"); + + ui_out_field_int (uiout, "line", sal.line); + } + else + { + ui_out_field_skip (uiout, "fullname"); + ui_out_field_skip (uiout, "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"); + + if (!VEC_empty (breakpoint_p, tracepoints)) + { + struct cleanup *cleanup_chain; + int ix; + struct breakpoint *b; + + 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: ")); + 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); + } + + do_cleanups (cleanup_chain); + + if (ui_out_is_mi_like_p (uiout)) + ui_out_field_int (uiout, "number-of-tracepoints", + VEC_length(breakpoint_p, tracepoints)); + else + ui_out_text (uiout, "\n"); + } + VEC_free (breakpoint_p, tracepoints); + + do_cleanups (bkpt_chain); + do_cleanups (old_chain); +} + +static void +info_static_tracepoint_markers_command (char *arg, int from_tty) +{ + VEC(static_tracepoint_marker_p) *markers; + struct cleanup *old_chain; + struct static_tracepoint_marker *marker; + int i; + + old_chain + = make_cleanup_ui_out_table_begin_end (uiout, 5, -1, + "StaticTracepointMarkersTable"); + + ui_out_table_header (uiout, 7, ui_left, "counter", "Cnt"); + + ui_out_table_header (uiout, 40, ui_left, "marker-id", "ID"); + + ui_out_table_header (uiout, 3, ui_left, "enabled", "Enb"); + if (gdbarch_addr_bit (target_gdbarch) <= 32) + ui_out_table_header (uiout, 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"); + + ui_out_table_body (uiout); + + markers = target_static_tracepoint_markers_by_strid (NULL); + make_cleanup (VEC_cleanup (static_tracepoint_marker_p), &markers); + + for (i = 0; + VEC_iterate (static_tracepoint_marker_p, + markers, i, marker); + i++) + { + print_one_static_tracepoint_marker (i + 1, marker); + release_static_tracepoint_marker (marker); + } + + do_cleanups (old_chain); +} + +/* The $_sdata convenience variable is a bit special. We don't know + for sure type of the value until we actually have a chance to fetch + the data --- the size of the object depends on what has been + collected. We solve this by making $_sdata be an internalvar that + creates a new value on access. */ + +/* Return a new value with the correct type for the sdata object of + the current trace frame. Return a void value if there's no object + available. */ + +static struct value * +sdata_make_value (struct gdbarch *gdbarch, struct internalvar *var) +{ + LONGEST size; + gdb_byte *buf; + + /* We need to read the whole object before we know its size. */ + size = target_read_alloc (¤t_target, + TARGET_OBJECT_STATIC_TRACE_DATA, + NULL, &buf); + if (size >= 0) + { + struct value *v; + struct type *type; + + type = init_vector_type (builtin_type (gdbarch)->builtin_true_char, + size); + v = allocate_value (type); + memcpy (value_contents_raw (v), buf, size); + xfree (buf); + return v; + } + else + return allocate_value (builtin_type (gdbarch)->builtin_void); +} + /* module initialization */ void _initialize_tracepoint (void) { struct cmd_list_element *c; + /* Explicitly create without lookup, since that tries to create a + value with a void typed value, and when we get here, gdbarch + isn't initialized yet. At this point, we're quite sure there + isn't another convenience variable of the same name. */ + create_internalvar_type_lazy ("_sdata", sdata_make_value); + traceframe_number = -1; tracepoint_number = -1; @@ -4135,6 +4459,11 @@ If no arguments are supplied, delete all variables."), &deletelist); add_info ("tvariables", tvariables_info, _("\ Status of trace state variables and their values.\n\ +")); + + add_info ("static-tracepoint-markers", + info_static_tracepoint_markers_command, _("\ +List target static tracepoints markers.\n\ ")); add_prefix_cmd ("tfind", class_trace, trace_find_command, _("\ @@ -4154,7 +4483,7 @@ Usage: tfind range addr1,addr2"), add_cmd ("line", class_trace, trace_find_line_command, _("\ Select a trace frame by source line.\n\ -Argument can be a line number (with optional source file), \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); @@ -4217,6 +4546,7 @@ Also accepts the following special arguments:\n\ $regs -- all registers.\n\ $args -- all function arguments.\n\ $locals -- all variables local to the block/function scope.\n\ + $_sdata -- static tracepoint data (ignored for non-static tracepoints).\n\ Note: this command can only be used in a tracepoint \"actions\" list.")); add_com ("teval", class_trace, teval_pseudocommand, _("\ @@ -4227,8 +4557,8 @@ Note: this command can only be used in a tracepoint \"actions\" list.")); add_com ("actions", class_trace, 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\ +Tracepoint actions may include collecting of specified data,\n\ +single-stepping, or enabling/disabling other tracepoints,\n\ depending on target's capabilities.")); default_collect = xstrdup ("");