* [PATCH 0/5] New MI command -trace-frame-collected
@ 2013-06-07 13:07 Yao Qi
2013-06-07 13:07 ` [PATCH 4/5] " Yao Qi
` (5 more replies)
0 siblings, 6 replies; 36+ messages in thread
From: Yao Qi @ 2013-06-07 13:07 UTC (permalink / raw)
To: gdb-patches
Hi,
In a given traceframe, there are explicitly collected variables,
registers, trace state variables, memories, and computed expressions.
In MI, we don't have a command to dump these contents, and this patch
adds -trace-frame-collected to do so.
Patch 4/5 is the major part of this series, and patch 5/5 is the test
to -trace-frame-collected. GDB needs to know what trace state
variables are collected in a traceframe, so we extended the
qXfer:traceframe-info object to report the set of collected trace
state variables in the current traceframe. That is what patch 3/5 does.
Patch 1/5, and 2/5 code refactor.
The whole series are tested on x86_64-linux with native and gdbserver.
*** BLURB HERE ***
Yao Qi (5):
Remove global variable tracepoint_list and stepping_list.
Move code to get_traceframe_location.
Add id of TSV into traceframe_info.
New MI command -trace-frame-collected
New test: gdb.trace/mi-trace-frame-collected.exp
gdb/NEWS | 9 +
gdb/breakpoint.c | 2 -
gdb/common/filestuff.c | 2 -
gdb/common/gdb_vecs.h | 2 +
gdb/ctf.c | 12 +
gdb/doc/gdb.texinfo | 122 ++++++++-
gdb/dwarf2loc.c | 2 -
gdb/features/traceframe-info.dtd | 5 +-
gdb/gdbserver/tracepoint.c | 7 +
gdb/mi/mi-cmds.c | 2 +
gdb/mi/mi-cmds.h | 1 +
gdb/mi/mi-main.c | 296 +++++++++++++++++++-
gdb/remote.c | 2 +-
.../gdb.trace/mi-trace-frame-collected.exp | 157 ++++++++++
gdb/tracepoint.c | 308 +++++++++++++-------
gdb/tracepoint.h | 53 ++++-
16 files changed, 860 insertions(+), 122 deletions(-)
create mode 100644 gdb/testsuite/gdb.trace/mi-trace-frame-collected.exp
--
1.7.7.6
^ permalink raw reply [flat|nested] 36+ messages in thread* [PATCH 4/5] New MI command -trace-frame-collected 2013-06-07 13:07 [PATCH 0/5] New MI command -trace-frame-collected Yao Qi @ 2013-06-07 13:07 ` Yao Qi 2013-06-07 13:07 ` [PATCH 1/5] Remove global variable tracepoint_list and stepping_list Yao Qi ` (4 subsequent siblings) 5 siblings, 0 replies; 36+ messages in thread From: Yao Qi @ 2013-06-07 13:07 UTC (permalink / raw) To: gdb-patches Hi, This patch adds the new MI command -trace-frame-collected, which can dump explicitly collected variables, computed expressions, tvars, memory and registers. See details in the doc about MI command options. Two new fields wholly_collected and computed are added in 'struct collection_list' to record the wholly collected objects and computed expressions during parsing actions. gdb/doc: 2013-06-07 Pedro Alves <pedro@codesourcery.com> * gdb.texinfo (GDB/MI Tracepoint Commands): Document -trace-frame-collected. gdb: 2013-06-07 Pedro Alves <pedro@codesourcery.com> Yao Qi <yao@codesourcery.com> * mi/mi-cmds.c (mi_cmds): Register -trace-frame-collected. * mi/mi-cmds.h (mi_cmd_trace_frame_collected): Declare. * mi/mi-main.c (print_variable_or_computed): New function. (mi_cmd_trace_frame_collected): New function. * tracepoint.c (struct traceframe_info): Move to tracepoint.h (struct collection_list): Likewise. (do_collect_symbol): Include locals and arguments in the wholly collected variables list. (clear_collection_list): Clear wholly collected variables list and computed variables list. (append_exp): New function. (encode_actions_1): Include variables in the wholly collected variables list. Include memory ranges and full-fledged expressions in the computed expressions list. (encode_actions_rsp): Move some code to ... (encode_actions): ... here. Return the cleanup chain. (get_traceframe_location, get_traceframe_info): Remove static. * tracepoint.h (struct memrange): Moved from tracepoint.c. (struct collection_list): Moved from tracepoint.c. Add two new fields 'wholly_collected' and 'computed'. (find_trace_state_variable_by_number): Declare. (encode_actions, encode_actions_rsp): Declare. (get_traceframe_info, get_traceframe_location): Declare. * NEWS: Mention new MI command -trace-frame-collected --- gdb/NEWS | 4 + gdb/doc/gdb.texinfo | 110 +++++++++++++++++++ gdb/mi/mi-cmds.c | 2 + gdb/mi/mi-cmds.h | 1 + gdb/mi/mi-main.c | 294 +++++++++++++++++++++++++++++++++++++++++++++++++++ gdb/tracepoint.c | 117 +++++++++++++-------- gdb/tracepoint.h | 46 ++++++++ 7 files changed, 531 insertions(+), 43 deletions(-) diff --git a/gdb/NEWS b/gdb/NEWS index b10d6d4..4ee2fe4 100644 --- a/gdb/NEWS +++ b/gdb/NEWS @@ -80,6 +80,10 @@ show range-stepping "--skip-unavailable" option. When used, only available registers are displayed. + ** The new command -trace-frame-collected dumps explicitly collected + variables, computed expressions, tvars, memory and registers in a + traceframe. + * New system-wide configuration scripts A GDB installation now provides scripts suitable for use as system-wide configuration scripts for the following systems: diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo index fefac12..7ba6273 100644 --- a/gdb/doc/gdb.texinfo +++ b/gdb/doc/gdb.texinfo @@ -33162,6 +33162,116 @@ with the @samp{$} character. The corresponding @value{GDBN} command is @samp{tvariable}. +@subheading The @code{-trace-frame-collected} Command +@findex -trace-frame-collected + +@subsubheading Synopsis + +@smallexample + -trace-frame-collected + [--var-print-values @var{var_pval}] + [--comp-print-values @var{comp_pval}] + [--registers-format @var{regformat}] + [--memory-contents] +@end smallexample + +This command returns the set of explicitly wholly collected objects, +register names, trace state variable names, memory ranges and computed +expressions that have been collected at a particular trace frame. The +optional parameters to the command affect the output format in +different ways. See the output description table below for more +details. + +The reported names can be used in the normal manner to create +varobjs and inspect the objects themselves. The items returned by +this command are categorized so that it is clear which is a variable, +which is a register, which is a trace state variable, which is a +memory range and which is a computed expression. + +For instance, if the actions were @code{myVar, myArray[myIndex] +myObj.field, myPtr->field, myCount + 2, *(int*)0xaf02bef0@@40}, the +set of named objects explicitly wholly collected would be +@code{myVar}, and the set of computed expressions would be +@code{myArray[myIndex], myObj.field, myPtr->field, myCount + 2, +*(int*)0xaf02bef0@@40}. + +An example output would be: + +@smallexample +(gdb) +-trace-frame-collected +^done, + explicit-variables=[@{name="i",value="1"@}], + computed-expressions=[@{name="a.b",value="0"@}, + @{name="array[5]",value="0"@}, + @{name="$tvar1 + 1",value="43970027"@}], + registers=[@{number="0",value="0x7fe2c6e79ec8"@}, + @{number="1",value="0x0"@}, + @{number="2",value="0x4"@}, + ... + @{number="125",value="0x0"@}], + tvars=[@{name="$tvar1",current="43970026"@}], + memory=[@{address="0x0000000000602264",length="4"@}, + @{address="0x0000000000615bc0",length="4"@}] +(gdb) +@end smallexample + +Where: + +@table @code +@item explicit-variables +The set of objects that have been explicitly wholly collected at the +current trace frame. For each object, its name and value are printed. +The @code{--var-print-values} option affects how or whether the value +field is output. If @var{var_pval} is 0, then print only the names; +if it is 1, print also their values; and if it is 2, print the name, +type and value for simple data types, and the name and type for +arrays, structures and unions. + +@item computed-expressions +The set of computed expressions that have been collected at the +current trace frame. The @code{--comp-print-values} option affects +this set, as the @code{--var-print-values} option affects the +@code{explicit-variables} set. See above. + +@item registers +The registers that have been collected at the current trace frame. +For each register collected, the name and current value are returned. +The value is formatted according to the @code{--registers-format} +option. See the @command{-data-list-register-values} command for a +list of the allowed formats. The default is @samp{x}. + +@item tvars +The trace state variables that have been collected at the current +trace frame. For each trace state variable collected, the name and +current value are returned. + +@item memory +The set of memory ranges that have been collected at the current trace +frame. Its content is a list of tuples. Each tuple represents a +collected memory range and has the following fields: + +@table @code +@item address +The start address of the memory range, as hexadecimal literal. + +@item length +The length of the memory range, as decimal literal. + +@item contents +The contents of the memory block, in hex. This field is only present +if the @code{--memory-contents} options is specified. + +@end table + +@end table + +@subsubheading @value{GDBN} Command + +There is no corresponding @value{GDBN} command. + +@subsubheading Example + @subheading -trace-list-variables @findex -trace-list-variables diff --git a/gdb/mi/mi-cmds.c b/gdb/mi/mi-cmds.c index eb67abe..0768b2a 100644 --- a/gdb/mi/mi-cmds.c +++ b/gdb/mi/mi-cmds.c @@ -148,6 +148,8 @@ static struct mi_cmd mi_cmds[] = DEF_MI_CMD_MI ("trace-define-variable", mi_cmd_trace_define_variable), DEF_MI_CMD_MI_1 ("trace-find", mi_cmd_trace_find, &mi_suppress_notification.traceframe), + DEF_MI_CMD_MI ("trace-frame-collected", + mi_cmd_trace_frame_collected), DEF_MI_CMD_MI ("trace-list-variables", mi_cmd_trace_list_variables), DEF_MI_CMD_MI ("trace-save", mi_cmd_trace_save), DEF_MI_CMD_MI ("trace-start", mi_cmd_trace_start), diff --git a/gdb/mi/mi-cmds.h b/gdb/mi/mi-cmds.h index 8839319..a472582 100644 --- a/gdb/mi/mi-cmds.h +++ b/gdb/mi/mi-cmds.h @@ -94,6 +94,7 @@ extern mi_cmd_argv_ftype mi_cmd_thread_list_ids; extern mi_cmd_argv_ftype mi_cmd_thread_select; extern mi_cmd_argv_ftype mi_cmd_trace_define_variable; extern mi_cmd_argv_ftype mi_cmd_trace_find; +extern mi_cmd_argv_ftype mi_cmd_trace_frame_collected; extern mi_cmd_argv_ftype mi_cmd_trace_list_variables; extern mi_cmd_argv_ftype mi_cmd_trace_save; extern mi_cmd_argv_ftype mi_cmd_trace_start; diff --git a/gdb/mi/mi-main.c b/gdb/mi/mi-main.c index a63ff8b..9f9e6e6 100644 --- a/gdb/mi/mi-main.c +++ b/gdb/mi/mi-main.c @@ -2585,3 +2585,297 @@ mi_cmd_ada_task_info (char *command, char **argv, int argc) print_ada_task_info (current_uiout, argv[0], current_inferior ()); } + +/* Print EXPRESSION according to VALUES. */ + +static void +print_variable_or_computed (char *expression, enum print_values values) +{ + struct expression *expr; + struct cleanup *old_chain; + struct value *val; + struct ui_file *stb; + struct value_print_options opts; + struct type *type; + struct ui_out *uiout = current_uiout; + + stb = mem_fileopen (); + old_chain = make_cleanup_ui_file_delete (stb); + + expr = parse_expression (expression); + + make_cleanup (free_current_contents, &expr); + + if (values == PRINT_SIMPLE_VALUES) + val = evaluate_type (expr); + else + val = evaluate_expression (expr); + + if (values != PRINT_NO_VALUES) + make_cleanup_ui_out_tuple_begin_end (uiout, NULL); + ui_out_field_string (uiout, "name", expression); + + switch (values) + { + case PRINT_SIMPLE_VALUES: + type = check_typedef (value_type (val)); + type_print (value_type (val), "", stb, -1); + ui_out_field_stream (uiout, "type", stb); + if (TYPE_CODE (type) != TYPE_CODE_ARRAY + && TYPE_CODE (type) != TYPE_CODE_STRUCT + && TYPE_CODE (type) != TYPE_CODE_UNION) + { + struct value_print_options opts; + + get_raw_print_options (&opts); + opts.deref_ref = 1; + common_val_print (val, stb, 0, &opts, current_language); + ui_out_field_stream (uiout, "value", stb); + } + break; + case PRINT_ALL_VALUES: + { + struct value_print_options opts; + + get_raw_print_options (&opts); + opts.deref_ref = 1; + common_val_print (val, stb, 0, &opts, current_language); + ui_out_field_stream (uiout, "value", stb); + } + break; + } + + do_cleanups (old_chain); +} + +/* Implement the "-trace-frame-collected" command. */ + +void +mi_cmd_trace_frame_collected (char *command, char **argv, int argc) +{ + struct cleanup *old_chain; + struct bp_location *tloc; + int stepping_frame; + struct collection_list tracepoint_list, stepping_list; + struct collection_list *clist; + struct traceframe_info *tinfo; + int oind = 0; + int var_print_values = PRINT_ALL_VALUES; + int comp_print_values = PRINT_ALL_VALUES; + int registers_format = 'x'; + int memory_contents = 0; + struct ui_out *uiout = current_uiout; + enum opt + { + VAR_PRINT_VALUES, + COMP_PRINT_VALUES, + REGISTERS_FORMAT, + MEMORY_CONTENTS, + }; + static const struct mi_opt opts[] = + { + {"-var-print-values", VAR_PRINT_VALUES, 1}, + {"-comp-print-values", COMP_PRINT_VALUES, 1}, + {"-registers-format", REGISTERS_FORMAT, 1}, + {"-memory-contents", MEMORY_CONTENTS, 0}, + { 0, 0, 0 } + }; + + while (1) + { + char *oarg; + int opt = mi_getopt ("-trace-frame-collected", argc, argv, opts, + &oind, &oarg); + if (opt < 0) + break; + switch ((enum opt) opt) + { + case VAR_PRINT_VALUES: + var_print_values = mi_parse_print_values (oarg); + break; + case COMP_PRINT_VALUES: + comp_print_values = mi_parse_print_values (oarg); + break; + case REGISTERS_FORMAT: + registers_format = oarg[0]; + case MEMORY_CONTENTS: + memory_contents = 1; + break; + } + } + + if (oind != argc) + error (_("Usage: -trace-frame-collected " + "[--var-print-values PRINT_VALUES] " + "[--comp-print-values PRINT_VALUES] " + "[--registers-format FORMAT]" + "[--memory-contents]")); + + /* This throws an error is not inspecting a trace frame. */ + tloc = get_traceframe_location (&stepping_frame); + + /* This command only makes sense for the current frame, not the + selected frame. */ + old_chain = make_cleanup_restore_current_thread (); + select_frame (get_current_frame ()); + + encode_actions (tloc, &tracepoint_list, &stepping_list); + + tinfo = get_traceframe_info (); + + if (stepping_frame) + clist = &stepping_list; + else + clist = &tracepoint_list; + + /* Explicitly wholly collected variables. */ + { + struct cleanup *list_cleanup; + char *p; + int i; + + list_cleanup = make_cleanup_ui_out_list_begin_end (uiout, + "explicit-variables"); + for (i = 0; VEC_iterate (char_ptr, clist->wholly_collected, i, p); i++) + print_variable_or_computed (p, var_print_values); + do_cleanups (list_cleanup); + } + + /* Computed expressions. */ + { + struct cleanup *list_cleanup; + char *p; + int i; + + list_cleanup + = make_cleanup_ui_out_list_begin_end (uiout, + "computed-expressions"); + for (i = 0; VEC_iterate (char_ptr, clist->computed, i, p); i++) + print_variable_or_computed (p, comp_print_values); + do_cleanups (list_cleanup); + } + + /* Registers. Given pseudo-registers, and that some architectures + (like MIPS) actually hide the raw registers, we don't go through + the trace frame info, but instead consult the register cache for + register availability. */ + { + struct cleanup *list_cleanup; + struct frame_info *frame; + struct gdbarch *gdbarch; + int regnum; + int numregs; + + list_cleanup = make_cleanup_ui_out_list_begin_end (uiout, "registers"); + + frame = get_selected_frame (NULL); + gdbarch = get_frame_arch (frame); + numregs = gdbarch_num_regs (gdbarch) + gdbarch_num_pseudo_regs (gdbarch); + + for (regnum = 0; regnum < numregs; regnum++) + { + if (gdbarch_register_name (gdbarch, regnum) == NULL + || *(gdbarch_register_name (gdbarch, regnum)) == '\0') + continue; + + output_register (frame, regnum, registers_format, 1); + } + + do_cleanups (list_cleanup); + } + + /* Trace state variables. */ + { + struct cleanup *list_cleanup; + int tvar; + char *tsvname; + int i; + + list_cleanup = make_cleanup_ui_out_list_begin_end (uiout, "tvars"); + + tsvname = NULL; + make_cleanup (free_current_contents, &tsvname); + + for (i = 0; VEC_iterate (int, tinfo->tvars, i, tvar); i++) + { + struct cleanup *cleanup_child; + struct trace_state_variable *tsv; + + tsv = find_trace_state_variable_by_number (tvar); + + cleanup_child = make_cleanup_ui_out_tuple_begin_end (uiout, NULL); + + if (tsv != NULL) + { + tsvname = xrealloc (tsvname, strlen (tsv->name) + 2); + tsvname[0] = '$'; + strcpy (tsvname + 1, tsv->name); + ui_out_field_string (uiout, "name", tsvname); + + tsv->value_known = target_get_trace_state_variable_value (tsv->number, + &tsv->value); + ui_out_field_int (uiout, "current", tsv->value); + } + else + { + ui_out_field_skip (uiout, "name"); + ui_out_field_skip (uiout, "current"); + } + + do_cleanups (cleanup_child); + } + + do_cleanups (list_cleanup); + } + + /* Memory. */ + { + struct cleanup *list_cleanup; + VEC(mem_range_s) *available_memory = NULL; + struct mem_range *r; + int i; + + traceframe_available_memory (&available_memory, 0, ULONGEST_MAX); + make_cleanup (VEC_cleanup(mem_range_s), &available_memory); + + list_cleanup = make_cleanup_ui_out_list_begin_end (uiout, "memory"); + + for (i = 0; VEC_iterate (mem_range_s, available_memory, i, r); i++) + { + struct cleanup *cleanup_child; + gdb_byte *data; + struct gdbarch *gdbarch = target_gdbarch (); + + cleanup_child = make_cleanup_ui_out_tuple_begin_end (uiout, NULL); + + ui_out_field_core_addr (uiout, "address", gdbarch, r->start); + ui_out_field_int (uiout, "length", r->length); + + data = xmalloc (r->length); + make_cleanup (xfree, data); + + if (memory_contents) + { + if (target_read_memory (r->start, data, r->length) == 0) + { + int m; + char *data_str, *p; + + data_str = xmalloc (r->length * 2 + 1); + make_cleanup (xfree, data_str); + + for (m = 0, p = data_str; m < r->length; ++m, p += 2) + sprintf (p, "%02x", data[m]); + ui_out_field_string (uiout, "contents", data_str); + } + else + ui_out_field_skip (uiout, "contents"); + } + do_cleanups (cleanup_child); + } + + do_cleanups (list_cleanup); + } + + do_cleanups (old_chain); +} diff --git a/gdb/tracepoint.c b/gdb/tracepoint.c index d3f0d48..89418af 100644 --- a/gdb/tracepoint.c +++ b/gdb/tracepoint.c @@ -340,6 +340,22 @@ find_trace_state_variable (const char *name) return NULL; } +/* Return the tsv if its number is NUMBER. Return NULL if not + found. */ + +struct trace_state_variable * +find_trace_state_variable_by_number (int number) +{ + struct trace_state_variable *tsv; + int ix; + + for (ix = 0; VEC_iterate (tsv_s, tvariables, ix, tsv); ++ix) + if (tsv->number == number) + return tsv; + + return NULL; +} + static void delete_trace_state_variable (const char *name) { @@ -853,29 +869,6 @@ enum { memrange_absolute = -1 }; -struct memrange -{ - int type; /* memrange_absolute for absolute memory range, - else basereg number. */ - bfd_signed_vma start; - bfd_signed_vma end; -}; - -struct collection_list - { - unsigned char regs_mask[32]; /* room for up to 256 regs */ - long listsize; - long next_memrange; - struct memrange *list; - long aexpr_listsize; /* size of array pointed to by expr_list elt */ - long next_aexpr_elt; - struct agent_expr **aexpr_list; - - /* True is the user requested a collection of "$_sdata", "static - tracepoint data". */ - int strace_data; - }; - /* MEMRANGE functions: */ static int memrange_cmp (const void *, const void *); @@ -1166,6 +1159,9 @@ do_collect_symbol (const char *print_name, collect_symbol (p->collect, 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)); } /* Add all locals (or args) symbols to collection list. */ @@ -1242,6 +1238,9 @@ clear_collection_list (struct collection_list *list) xfree (list->aexpr_list); xfree (list->list); + + VEC_free (char_ptr, list->wholly_collected); + VEC_free (char_ptr, list->computed); } /* Wrapper to function clear_collection_list. */ @@ -1392,6 +1391,21 @@ stringify_collection_list (struct collection_list *list) return *str_list; } +/* Add the printed expression EXP to *LIST. */ + +static void +append_exp (struct expression *exp, VEC(char_ptr) **list) +{ + 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); + ui_file_delete (tmp_stream); +} static void encode_actions_1 (struct command_line *action, @@ -1537,16 +1551,25 @@ encode_actions_1 (struct command_line *action, check_typedef (exp->elts[1].type); add_memrange (collect, memrange_absolute, addr, TYPE_LENGTH (exp->elts[1].type)); + append_exp (exp, &collect->computed); break; case OP_VAR_VALUE: - collect_symbol (collect, - exp->elts[2].symbol, - tloc->gdbarch, - frame_reg, - frame_offset, - tloc->address, - trace_string); + { + 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); + } break; default: /* Full-fledged expression. */ @@ -1582,6 +1605,8 @@ encode_actions_1 (struct command_line *action, } } } + + append_exp (exp, &collect->computed); break; } /* switch */ do_cleanups (old_chain); @@ -1635,7 +1660,11 @@ encode_actions_1 (struct command_line *action, } /* for */ } -static void +/* 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. */ + +struct cleanup * encode_actions (struct bp_location *tloc, struct collection_list *tracepoint_list, struct collection_list *stepping_list) @@ -1643,7 +1672,15 @@ encode_actions (struct bp_location *tloc, int frame_reg; LONGEST frame_offset; struct command_line *actions; - struct cleanup *old_chain; + struct cleanup *old_chain, *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); old_chain = make_cleanup (null_cleanup, NULL); @@ -1659,6 +1696,8 @@ encode_actions (struct bp_location *tloc, memrange_sortmerge (tracepoint_list); memrange_sortmerge (stepping_list); + + return return_chain; } /* Render all actions into gdb protocol. */ @@ -1670,15 +1709,7 @@ encode_actions_rsp (struct bp_location *tloc, struct cleanup *back_to; struct collection_list tracepoint_list, stepping_list; - back_to = 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); - - encode_actions (tloc, &tracepoint_list, &stepping_list); + back_to = encode_actions (tloc, &tracepoint_list, &stepping_list); *tdp_actions = stringify_collection_list (&tracepoint_list); *stepping_actions = stringify_collection_list (&stepping_list); @@ -2947,7 +2978,7 @@ trace_dump_actions (struct command_line *action, traceframe. Set *STEPPING_FRAME_P to 1 if the current traceframe is the stepping traceframe. */ -static struct bp_location * +struct bp_location * get_traceframe_location (int *stepping_frame_p) { struct tracepoint *t; @@ -5682,7 +5713,7 @@ parse_traceframe_info (const char *tframe_info) This is where we avoid re-fetching the object from the target if we already have it cached. */ -static struct traceframe_info * +struct traceframe_info * get_traceframe_info (void) { if (traceframe_info == NULL) diff --git a/gdb/tracepoint.h b/gdb/tracepoint.h index 37abbdd..5481246 100644 --- a/gdb/tracepoint.h +++ b/gdb/tracepoint.h @@ -323,6 +323,38 @@ struct trace_file_writer const struct trace_file_write_ops *ops; }; +struct memrange +{ + /* memrange_absolute for absolute memory range, else basereg + number. */ + int type; + bfd_signed_vma start; + bfd_signed_vma end; +}; + +struct collection_list +{ + /* room for up to 256 regs */ + unsigned char regs_mask[32]; + long listsize; + long next_memrange; + struct memrange *list; + + /* size of array pointed to by expr_list elt. */ + long aexpr_listsize; + long next_aexpr_elt; + struct agent_expr **aexpr_list; + + /* True is the user requested a collection of "$_sdata", "static + tracepoint data". */ + int strace_data; + + /* A set of names of wholly collected objects. */ + VEC(char_ptr) *wholly_collected; + /* A set of computed expressions. */ + VEC(char_ptr) *computed; +}; + extern void parse_static_tracepoint_marker_definition (char *line, char **pp, struct static_tracepoint_marker *marker); @@ -367,6 +399,9 @@ extern void validate_actionline (const char *, struct breakpoint *); extern void validate_trace_state_variable_name (const char *name); extern struct trace_state_variable *find_trace_state_variable (const char *name); +extern struct trace_state_variable * + find_trace_state_variable_by_number (int number); + extern struct trace_state_variable *create_trace_state_variable (const char *name); extern int encode_source_string (int num, ULONGEST addr, @@ -416,4 +451,15 @@ extern struct traceframe_info *parse_traceframe_info (const char *tframe_info); extern int traceframe_available_memory (VEC(mem_range_s) **result, CORE_ADDR memaddr, ULONGEST len); +extern struct cleanup *encode_actions (struct bp_location *tloc, + struct collection_list *tracepoint_list, + struct collection_list *stepping_list); + +extern void encode_actions_rsp (struct bp_location *tloc, + char ***tdp_actions, char ***stepping_actions); + +extern struct traceframe_info *get_traceframe_info (void); + +extern struct bp_location *get_traceframe_location (int *stepping_frame_p); + #endif /* TRACEPOINT_H */ -- 1.7.7.6 ^ permalink raw reply [flat|nested] 36+ messages in thread
* [PATCH 1/5] Remove global variable tracepoint_list and stepping_list. 2013-06-07 13:07 [PATCH 0/5] New MI command -trace-frame-collected Yao Qi 2013-06-07 13:07 ` [PATCH 4/5] " Yao Qi @ 2013-06-07 13:07 ` Yao Qi 2013-06-07 20:50 ` Pedro Alves 2013-06-07 13:07 ` [PATCH 3/5] Add id of TSV into traceframe_info Yao Qi ` (3 subsequent siblings) 5 siblings, 1 reply; 36+ messages in thread From: Yao Qi @ 2013-06-07 13:07 UTC (permalink / raw) To: gdb-patches This patch is a refactor patch. Simply, it removes two global variables tracepoint_list and stepping_list. gdb: 2013-06-07 Pedro Alves <pedro@codesourcery.com> Yao Qi <yao@codesourcery.com> * tracepoint.c (tracepoint_list, stepping_list): Remove. (do_clear_collection_list, init_collection_list): New. (encode_actions): Change the type of the second and third parameter from 'char ***' to 'struct collection_list *'. (encode_actions): Rename to encode_actions_rsp, and rewrite on top of the new encode_actions implementation. (encode_actions): New function. (_initialize_tracepoint): Delete references to 'tracepoint_list' and 'stepping_list'. * tracepoint.h (encode_actions): Remove declaration. (encode_actions_rsp): Add declaration. * remote.c (remote_download_tracepoint): Caller update. --- gdb/remote.c | 2 +- gdb/tracepoint.c | 112 ++++++++++++++++++++++++++++++----------------------- gdb/tracepoint.h | 4 +- 3 files changed, 66 insertions(+), 52 deletions(-) diff --git a/gdb/remote.c b/gdb/remote.c index 080d048..d06b1ed 100644 --- a/gdb/remote.c +++ b/gdb/remote.c @@ -10524,7 +10524,7 @@ remote_download_tracepoint (struct bp_location *loc) struct breakpoint *b = loc->owner; struct tracepoint *t = (struct tracepoint *) b; - encode_actions (loc, &tdp_actions, &stepping_actions); + encode_actions_rsp (loc, &tdp_actions, &stepping_actions); old_chain = make_cleanup (free_actions_list_cleanup_wrapper, tdp_actions); (void) make_cleanup (free_actions_list_cleanup_wrapper, diff --git a/gdb/tracepoint.c b/gdb/tracepoint.c index 5bad3e8..03f9230 100644 --- a/gdb/tracepoint.c +++ b/gdb/tracepoint.c @@ -873,8 +873,7 @@ struct collection_list /* True is the user requested a collection of "$_sdata", "static tracepoint data". */ int strace_data; - } -tracepoint_list, stepping_list; + }; /* MEMRANGE functions: */ @@ -1239,6 +1238,35 @@ 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; + + xfree (list->aexpr_list); + xfree (list->list); +} + +/* Wrapper to function clear_collection_list. */ + +static void +do_clear_collection_list (void *list) +{ + struct collection_list *l = list; + + clear_collection_list (l); +} + +/* Initialize collection_list CLIST. */ + +static void +init_collection_list (struct collection_list *clist) +{ + 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 *)); } /* Reduce a collection list to string form (for gdb protocol). */ @@ -1606,37 +1634,50 @@ encode_actions_1 (struct command_line *action, } /* for */ } -/* Render all actions into gdb protocol. */ - -void -encode_actions (struct bp_location *tloc, char ***tdp_actions, - char ***stepping_actions) +static 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; - - back_to = make_cleanup (null_cleanup, NULL); + struct command_line *actions; + struct cleanup *old_chain; - clear_collection_list (&tracepoint_list); - clear_collection_list (&stepping_list); + old_chain = make_cleanup (null_cleanup, NULL); - *tdp_actions = NULL; - *stepping_actions = NULL; + actions = all_tracepoint_actions_and_cleanup (tloc->owner); gdbarch_virtual_frame_pointer (tloc->gdbarch, tloc->address, &frame_reg, &frame_offset); - actions = all_tracepoint_actions_and_cleanup (tloc->owner); - encode_actions_1 (actions, tloc, frame_reg, frame_offset, - &tracepoint_list, &stepping_list); + tracepoint_list, stepping_list); + + do_cleanups (old_chain); + + memrange_sortmerge (tracepoint_list); + memrange_sortmerge (stepping_list); +} + +/* Render all actions into gdb protocol. */ + +void +encode_actions_rsp (struct bp_location *tloc, + char ***tdp_actions, char ***stepping_actions) +{ + struct cleanup *back_to; + struct collection_list tracepoint_list, stepping_list; + + back_to = make_cleanup (null_cleanup, NULL); - memrange_sortmerge (&tracepoint_list); - memrange_sortmerge (&stepping_list); + 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); + + encode_actions (tloc, &tracepoint_list, &stepping_list); *tdp_actions = stringify_collection_list (&tracepoint_list); *stepping_actions = stringify_collection_list (&stepping_list); @@ -5673,33 +5714,6 @@ _initialize_tracepoint (void) traceframe_number = -1; tracepoint_number = -1; - if (tracepoint_list.list == NULL) - { - tracepoint_list.listsize = 128; - tracepoint_list.list = xmalloc - (tracepoint_list.listsize * sizeof (struct memrange)); - } - if (tracepoint_list.aexpr_list == NULL) - { - tracepoint_list.aexpr_listsize = 128; - tracepoint_list.aexpr_list = xmalloc - (tracepoint_list.aexpr_listsize * sizeof (struct agent_expr *)); - } - - if (stepping_list.list == NULL) - { - stepping_list.listsize = 128; - stepping_list.list = xmalloc - (stepping_list.listsize * sizeof (struct memrange)); - } - - if (stepping_list.aexpr_list == NULL) - { - stepping_list.aexpr_listsize = 128; - stepping_list.aexpr_list = xmalloc - (stepping_list.aexpr_listsize * sizeof (struct agent_expr *)); - } - add_info ("scope", scope_info, _("List the variables local to a scope")); diff --git a/gdb/tracepoint.h b/gdb/tracepoint.h index 3b09ca8..5ecf1fb 100644 --- a/gdb/tracepoint.h +++ b/gdb/tracepoint.h @@ -357,8 +357,8 @@ void free_actions (struct breakpoint *); extern const char *decode_agent_options (const char *exp, int *trace_string); -extern void encode_actions (struct bp_location *tloc, - char ***tdp_actions, char ***stepping_actions); +extern void encode_actions_rsp (struct bp_location *tloc, + char ***tdp_actions, char ***stepping_actions); extern void validate_actionline (const char *, struct breakpoint *); extern void validate_trace_state_variable_name (const char *name); -- 1.7.7.6 ^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PATCH 1/5] Remove global variable tracepoint_list and stepping_list. 2013-06-07 13:07 ` [PATCH 1/5] Remove global variable tracepoint_list and stepping_list Yao Qi @ 2013-06-07 20:50 ` Pedro Alves 0 siblings, 0 replies; 36+ messages in thread From: Pedro Alves @ 2013-06-07 20:50 UTC (permalink / raw) To: Yao Qi; +Cc: gdb-patches On 06/07/2013 02:08 PM, Yao Qi wrote: > This patch is a refactor patch. Simply, it removes two global > variables tracepoint_list and stepping_list. > > gdb: > > 2013-06-07 Pedro Alves <pedro@codesourcery.com> > Yao Qi <yao@codesourcery.com> > > * tracepoint.c (tracepoint_list, stepping_list): Remove. > (do_clear_collection_list, init_collection_list): New. > (encode_actions): Change the type of the second and third > parameter from 'char ***' to 'struct collection_list *'. > (encode_actions): Rename to encode_actions_rsp, and rewrite on top > of the new encode_actions implementation. > (encode_actions): New function. Also, "Make static.". > (_initialize_tracepoint): Delete references to 'tracepoint_list' > and 'stepping_list'. > * tracepoint.h (encode_actions): Remove declaration. > (encode_actions_rsp): Add declaration. > * remote.c (remote_download_tracepoint): Caller update. > > /* MEMRANGE functions: */ > > @@ -1239,6 +1238,35 @@ 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; > + > + xfree (list->aexpr_list); > + xfree (list->list); > +} This change is not mentioned in the ChangeLog. > + > +/* Wrapper to function clear_collection_list. */ "Wrapper for". "to" would be used to introduce a rationale for the wrapping, like e.g., "wrapper to allow frobing ...". I suggest mentioning cleanups, like e.g.,: /* A cleanup wrapper for clear_collection_list. */ > /* Reduce a collection list to string form (for gdb protocol). */ > @@ -1606,37 +1634,50 @@ encode_actions_1 (struct command_line *action, > } /* for */ > } > > -/* Render all actions into gdb protocol. */ > - > -void > -encode_actions (struct bp_location *tloc, char ***tdp_actions, > - char ***stepping_actions) > +static void > +encode_actions (struct bp_location *tloc, > + struct collection_list *tracepoint_list, > + struct collection_list *stepping_list) Missing docu. Ah, found it in patch 4. (would have been best merged here). > { > - 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; > - > - back_to = make_cleanup (null_cleanup, NULL); > + struct command_line *actions; > + struct cleanup *old_chain; > > - clear_collection_list (&tracepoint_list); > - clear_collection_list (&stepping_list); > + old_chain = make_cleanup (null_cleanup, NULL); > > - *tdp_actions = NULL; > - *stepping_actions = NULL; > + actions = all_tracepoint_actions_and_cleanup (tloc->owner); > > gdbarch_virtual_frame_pointer (tloc->gdbarch, > tloc->address, &frame_reg, &frame_offset); > > - actions = all_tracepoint_actions_and_cleanup (tloc->owner); > - > encode_actions_1 (actions, tloc, frame_reg, frame_offset, > - &tracepoint_list, &stepping_list); > + tracepoint_list, stepping_list); > + > + do_cleanups (old_chain); > + > + memrange_sortmerge (tracepoint_list); > + memrange_sortmerge (stepping_list); > +} > + > +/* Render all actions into gdb protocol. */ > + > +void > +encode_actions_rsp (struct bp_location *tloc, > + char ***tdp_actions, char ***stepping_actions) > +{ > + struct cleanup *back_to; > + struct collection_list tracepoint_list, stepping_list; > + > + back_to = make_cleanup (null_cleanup, NULL); > > - memrange_sortmerge (&tracepoint_list); > - memrange_sortmerge (&stepping_list); > + 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); Thanks for splitting all this up into pieces. Much appreciated. However, there's a weird back and forth dance going on between this patch and patch 4, making the reader dizzy. :-) Patch 4 moves these back to encode_actions... There's only one caller of encode_actions in this patch, so it'd be better to leaving encode_actions as a single function in this patch, and leave the split for one of the follow ups (possible patch 4), explaining that the split allows reusing the encode bits without generating the RSP, necessary for the MI command's implementation. > + > + encode_actions (tloc, &tracepoint_list, &stepping_list); -- Pedro Alves ^ permalink raw reply [flat|nested] 36+ messages in thread
* [PATCH 3/5] Add id of TSV into traceframe_info. 2013-06-07 13:07 [PATCH 0/5] New MI command -trace-frame-collected Yao Qi 2013-06-07 13:07 ` [PATCH 4/5] " Yao Qi 2013-06-07 13:07 ` [PATCH 1/5] Remove global variable tracepoint_list and stepping_list Yao Qi @ 2013-06-07 13:07 ` Yao Qi 2013-06-07 14:39 ` Eli Zaretskii 2013-06-07 13:07 ` [PATCH 2/5] Move code to get_traceframe_location Yao Qi ` (2 subsequent siblings) 5 siblings, 1 reply; 36+ messages in thread From: Yao Qi @ 2013-06-07 13:07 UTC (permalink / raw) To: gdb-patches Hi, This patch extends the qXfer:traceframe-info object to report the set of collected trace state variables in the current traceframe. Since VEC(int) is used in tracepoint.h, to avoid duplicated definition error, this patch also moves DEF_VEC_I(int) to gdb_vecs.h, and include it in other files instead of defining it by their own. When GDB reads from trace file (tfile or ctf), the traceframe_ifo object should be updated for trace state variables as well. gdb: 2013-06-07 Pedro Alves <pedro@codesourcery.com> Yao Qi <yao@codesourcery.com> * ctf.c (ctf_traceframe_info): Push trace state variables present in the trace data into the traceframe info object. * breakpoint.c (DEF_VEC_I): Remove. * common/filestuff.c (DEF_VEC_I): Likewise. * dwarf2loc.c (DEF_VEC_I): Likewise. * mi/mi-main.c (DEF_VEC_I): Likewise. * common/gdb_vecs.h (DEF_VEC_I): Define vector for int. * features/traceframe-info.dtd: Add tvar element and its attributes. * tracepoint.c (free_traceframe_info): Free vector 'tvars'. (build_traceframe_info): Push trace state variables present in the trace data into the traceframe info object. (traceframe_info_start_tvar): New function. (tvar_attributes): New. (traceframe_info_children): Add "tvar" element. * tracepoint.h (struct traceframe_info) <tvars>: New field. * NEWS: Mention the change in GDB and GDBserver. gdb/doc: 2013-06-07 Pedro Alves <pedro@codesourcery.com> * gdb.texinfo (Traceframe Info Format): Document tvar element and its attributes. gdb/gdbserver: 2013-06-06 Pedro Alves <pedro@codesourcery.com> * tracepoint.c (build_traceframe_info_xml): Output trace state variables present in the trace buffer. --- gdb/NEWS | 5 +++++ gdb/breakpoint.c | 2 -- gdb/common/filestuff.c | 2 -- gdb/common/gdb_vecs.h | 2 ++ gdb/ctf.c | 12 ++++++++++++ gdb/doc/gdb.texinfo | 12 +++++++++++- gdb/dwarf2loc.c | 2 -- gdb/features/traceframe-info.dtd | 5 ++++- gdb/gdbserver/tracepoint.c | 7 +++++++ gdb/mi/mi-main.c | 2 -- gdb/tracepoint.c | 30 ++++++++++++++++++++++++++++++ gdb/tracepoint.h | 3 +++ 12 files changed, 74 insertions(+), 10 deletions(-) diff --git a/gdb/NEWS b/gdb/NEWS index 00eeeb6..b10d6d4 100644 --- a/gdb/NEWS +++ b/gdb/NEWS @@ -91,6 +91,8 @@ show range-stepping the number of control packets from/to GDB. See "New remote packets" below. +* GDB now understands the element 'tvar' in the XML traceframe info. + * New remote packets vCont;r @@ -112,6 +114,9 @@ qXfer:libraries-svr4:read's annex ** GDBserver now supports target-assisted range stepping. Currently enabled on x86/x86_64 GNU/Linux targets. + ** GDBserver now adds element 'tvar' in the XML in the reply to + 'qXfer:traceframe-info:read'. + *** Changes in GDB 7.6 * Target record has been renamed to record-full. diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c index d4ccc81..6054ef4 100644 --- a/gdb/breakpoint.c +++ b/gdb/breakpoint.c @@ -5788,8 +5788,6 @@ bptype_string (enum bptype type) return bptypes[(int) type].description; } -DEF_VEC_I(int); - /* For MI, output a field named 'thread-groups' with a list as the value. For CLI, prefix the list with the string 'inf'. */ diff --git a/gdb/common/filestuff.c b/gdb/common/filestuff.c index daf96d9..7d1a69a 100644 --- a/gdb/common/filestuff.c +++ b/gdb/common/filestuff.c @@ -157,8 +157,6 @@ fdwalk (int (*func) (void *, int), void *arg) don't use a hashtab because libiberty isn't linked into gdbserver; and anyway we don't expect there to be many open fds. */ -DEF_VEC_I (int); - static VEC (int) *open_fds; /* An fdwalk callback function used by notice_open_fds. It puts the diff --git a/gdb/common/gdb_vecs.h b/gdb/common/gdb_vecs.h index 1b05b0c..7df3001 100644 --- a/gdb/common/gdb_vecs.h +++ b/gdb/common/gdb_vecs.h @@ -29,6 +29,8 @@ DEF_VEC_P (char_ptr); DEF_VEC_P (const_char_ptr); +DEF_VEC_I (int); + extern void free_char_ptr_vec (VEC (char_ptr) *char_ptr_vec); extern struct cleanup * diff --git a/gdb/ctf.c b/gdb/ctf.c index 278f950..1f6402d 100644 --- a/gdb/ctf.c +++ b/gdb/ctf.c @@ -1778,6 +1778,18 @@ ctf_traceframe_info (void) def = bt_ctf_get_field (event, scope, "length"); r->length = (uint16_t) bt_ctf_get_uint64 (def); } + else if (strcmp (name, "tsv") == 0) + { + int32_t vnum; + const struct bt_definition *scope + = bt_ctf_get_top_level_scope (event, + BT_EVENT_FIELDS); + const struct bt_definition *def; + + def = bt_ctf_get_field (event, scope, "num"); + vnum = (int32_t) bt_ctf_get_uint64 (def); + VEC_safe_push (int, info->tvars, vnum); + } else { warning (_("Unhandled trace block type (%s) " diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo index 82b1030..fefac12 100644 --- a/gdb/doc/gdb.texinfo +++ b/gdb/doc/gdb.texinfo @@ -41790,17 +41790,27 @@ A region of collected memory starting at @var{addr} and extending for <memory start="@var{addr}" length="@var{length}"/> @end smallexample +@item +A block indicating trace state variable numbered @var{number} has been +collected: + +@smallexample +<tvar id="@var{number}"/> +@end smallexample + @end itemize The formal DTD for the traceframe info format is given below: @smallexample -<!ELEMENT traceframe-info (memory)* > +<!ELEMENT traceframe-info (memory | tvar)* > <!ATTLIST traceframe-info version CDATA #FIXED "1.0"> <!ELEMENT memory EMPTY> <!ATTLIST memory start CDATA #REQUIRED length CDATA #REQUIRED> +<!ELEMENT tvar> +<!ATTLIST tvar id CDATA #REQUIRED> @end smallexample @node Branch Trace Format diff --git a/gdb/dwarf2loc.c b/gdb/dwarf2loc.c index 9e44096..aac2a1a 100644 --- a/gdb/dwarf2loc.c +++ b/gdb/dwarf2loc.c @@ -42,8 +42,6 @@ #include "gdb_string.h" #include "gdb_assert.h" -DEF_VEC_I(int); - extern int dwarf2_always_disassemble; static void dwarf_expr_frame_base_1 (struct symbol *framefunc, CORE_ADDR pc, diff --git a/gdb/features/traceframe-info.dtd b/gdb/features/traceframe-info.dtd index 0da2bec..b811122 100644 --- a/gdb/features/traceframe-info.dtd +++ b/gdb/features/traceframe-info.dtd @@ -5,9 +5,12 @@ notice and this notice are preserved. --> <!-- traceframe-info: Root element with versioning --> -<!ELEMENT traceframe-info (memory)* > +<!ELEMENT traceframe-info (memory | tvar)* > <!ATTLIST traceframe-info version CDATA #FIXED "1.0"> <!ELEMENT memory EMPTY> <!ATTLIST memory start CDATA #REQUIRED length CDATA #REQUIRED> + +<!ELEMENT tvar EMPTY> +<!ATTLIST tvar id CDATA #REQUIRED> diff --git a/gdb/gdbserver/tracepoint.c b/gdb/gdbserver/tracepoint.c index 1ff6114..5acc51a 100644 --- a/gdb/gdbserver/tracepoint.c +++ b/gdb/gdbserver/tracepoint.c @@ -5390,6 +5390,13 @@ build_traceframe_info_xml (char blocktype, unsigned char *dataptr, void *data) break; } case 'V': + { + int vnum; + + memcpy (&vnum, dataptr, sizeof (vnum)); + buffer_xml_printf (buffer, "<tvar id=\"%d\"/>\n", vnum); + break; + } case 'R': case 'S': { diff --git a/gdb/mi/mi-main.c b/gdb/mi/mi-main.c index 4fccfb3..a63ff8b 100644 --- a/gdb/mi/mi-main.c +++ b/gdb/mi/mi-main.c @@ -513,8 +513,6 @@ mi_cmd_thread_info (char *command, char **argv, int argc) print_thread_info (current_uiout, argv[0], -1); } -DEF_VEC_I(int); - struct collect_cores_data { int pid; diff --git a/gdb/tracepoint.c b/gdb/tracepoint.c index ab0d0bf..d3f0d48 100644 --- a/gdb/tracepoint.c +++ b/gdb/tracepoint.c @@ -235,6 +235,7 @@ free_traceframe_info (struct traceframe_info *info) if (info != NULL) { VEC_free (mem_range_s, info->memory); + VEC_free (int, info->tvars); xfree (info); } @@ -5233,6 +5234,12 @@ build_traceframe_info (char blocktype, void *data) break; } case 'V': + { + int vnum; + + tfile_read ((gdb_byte *) &vnum, 4); + VEC_safe_push (int, info->tvars, vnum); + } case 'R': case 'S': { @@ -5590,6 +5597,21 @@ traceframe_info_start_memory (struct gdb_xml_parser *parser, r->length = *length_p; } +/* Handle the start of a <tvar> element. */ + +static void +traceframe_info_start_tvar (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; + const char *id_attrib = xml_find_attribute (attributes, "id")->value; + int id = gdb_xml_parse_ulongest (parser, id_attrib); + + VEC_safe_push (int, info->tvars, id); +} + /* Discard the constructed trace frame info (if an error occurs). */ static void @@ -5608,10 +5630,18 @@ static const struct gdb_xml_attribute memory_attributes[] = { { NULL, GDB_XML_AF_NONE, NULL, NULL } }; +static const struct gdb_xml_attribute tvar_attributes[] = { + { "id", GDB_XML_AF_NONE, NULL, NULL }, + { NULL, GDB_XML_AF_NONE, NULL, NULL } +}; + static const struct gdb_xml_element traceframe_info_children[] = { { "memory", memory_attributes, NULL, GDB_XML_EF_REPEATABLE | GDB_XML_EF_OPTIONAL, traceframe_info_start_memory, NULL }, + { "tvar", tvar_attributes, NULL, + GDB_XML_EF_REPEATABLE | GDB_XML_EF_OPTIONAL, + traceframe_info_start_tvar, NULL }, { NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL } }; diff --git a/gdb/tracepoint.h b/gdb/tracepoint.h index 5ecf1fb..37abbdd 100644 --- a/gdb/tracepoint.h +++ b/gdb/tracepoint.h @@ -30,6 +30,9 @@ struct traceframe_info { /* Collected memory. */ VEC(mem_range_s) *memory; + + /* Collected trace state variables. */ + VEC(int) *tvars; }; /* A trace state variable is a value managed by a target being -- 1.7.7.6 ^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PATCH 3/5] Add id of TSV into traceframe_info. 2013-06-07 13:07 ` [PATCH 3/5] Add id of TSV into traceframe_info Yao Qi @ 2013-06-07 14:39 ` Eli Zaretskii 2013-06-08 11:06 ` Yao Qi 0 siblings, 1 reply; 36+ messages in thread From: Eli Zaretskii @ 2013-06-07 14:39 UTC (permalink / raw) To: Yao Qi; +Cc: gdb-patches > From: Yao Qi <yao@codesourcery.com> > Date: Fri, 7 Jun 2013 21:08:11 +0800 > > --- a/gdb/NEWS > +++ b/gdb/NEWS > @@ -91,6 +91,8 @@ show range-stepping > the number of control packets from/to GDB. See "New remote packets" > below. > > +* GDB now understands the element 'tvar' in the XML traceframe info. > + Shouldn't we tell what that element means or does? > + ** GDBserver now adds element 'tvar' in the XML in the reply to > + 'qXfer:traceframe-info:read'. And here. > --- a/gdb/doc/gdb.texinfo > +++ b/gdb/doc/gdb.texinfo > @@ -41790,17 +41790,27 @@ A region of collected memory starting at @var{addr} and extending for > <memory start="@var{addr}" length="@var{length}"/> > @end smallexample > > +@item > +A block indicating trace state variable numbered @var{number} has been > +collected: > + > +@smallexample > +<tvar id="@var{number}"/> > +@end smallexample > + > @end itemize > > The formal DTD for the traceframe info format is given below: > > @smallexample > -<!ELEMENT traceframe-info (memory)* > > +<!ELEMENT traceframe-info (memory | tvar)* > > <!ATTLIST traceframe-info version CDATA #FIXED "1.0"> > > <!ELEMENT memory EMPTY> > <!ATTLIST memory start CDATA #REQUIRED > length CDATA #REQUIRED> > +<!ELEMENT tvar> > +<!ATTLIST tvar id CDATA #REQUIRED> > @end smallexample This part is OK. Thanks. ^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PATCH 3/5] Add id of TSV into traceframe_info. 2013-06-07 14:39 ` Eli Zaretskii @ 2013-06-08 11:06 ` Yao Qi 0 siblings, 0 replies; 36+ messages in thread From: Yao Qi @ 2013-06-08 11:06 UTC (permalink / raw) To: Eli Zaretskii; +Cc: gdb-patches On 06/07/2013 10:39 PM, Eli Zaretskii wrote: >> +* GDB now understands the element 'tvar' in the XML traceframe info. >> >+ > Shouldn't we tell what that element means or does? > >> >+ ** GDBserver now adds element 'tvar' in the XML in the reply to >> >+ 'qXfer:traceframe-info:read'. > And here. > This element has the id of trace state variables collected in the trace frame. How about this, * GDB now understands the element 'tvar' in the XML traceframe info. It has the id of the collected trace state variables. and ** GDBserver now adds element 'tvar' in the XML in the reply to 'qXfer:traceframe-info:read'. It has the id of the collected trace state variables. -- Yao (é½å°§) ^ permalink raw reply [flat|nested] 36+ messages in thread
* [PATCH 2/5] Move code to get_traceframe_location. 2013-06-07 13:07 [PATCH 0/5] New MI command -trace-frame-collected Yao Qi ` (2 preceding siblings ...) 2013-06-07 13:07 ` [PATCH 3/5] Add id of TSV into traceframe_info Yao Qi @ 2013-06-07 13:07 ` Yao Qi 2013-06-07 21:09 ` Pedro Alves 2013-06-07 13:07 ` [PATCH 5/5] New test: gdb.trace/mi-trace-frame-collected.exp Yao Qi 2013-06-13 1:29 ` [PATCH 0/6 V2] New MI command -trace-frame-collected Yao Qi 5 siblings, 1 reply; 36+ messages in thread From: Yao Qi @ 2013-06-07 13:07 UTC (permalink / raw) To: gdb-patches This patch is a refactor patch. It moves some code into a new function get_traceframe_location, which will be shared in the next patch in this series. gdb: 2013-06-06 Pedro Alves <pedro@codesourcery.com> Yao Qi <yao@codesourcery.com> * tracepoint.c (trace_dump_command): Move code to ... (get_traceframe_location): ... here. New. --- gdb/tracepoint.c | 79 ++++++++++++++++++++++++++++++++---------------------- 1 files changed, 47 insertions(+), 32 deletions(-) diff --git a/gdb/tracepoint.c b/gdb/tracepoint.c index 03f9230..ab0d0bf 100644 --- a/gdb/tracepoint.c +++ b/gdb/tracepoint.c @@ -2942,6 +2942,48 @@ trace_dump_actions (struct command_line *action, } } +/* Return bp_location of the tracepoint associated with the current + traceframe. Set *STEPPING_FRAME_P to 1 if the current traceframe + is the stepping traceframe. */ + +static struct bp_location * +get_traceframe_location (int *stepping_frame_p) +{ + struct tracepoint *t; + struct bp_location *tloc; + struct regcache *regcache; + + if (tracepoint_number == -1) + error (_("No current trace frame.")); + + t = get_tracepoint (tracepoint_number); + + if (t == NULL) + error (_("No known tracepoint matches 'current' tracepoint #%d."), + tracepoint_number); + + /* The current frame is a trap frame if the frame PC is equal to the + tracepoint PC. If not, then the current frame was collected + during single-stepping. */ + regcache = get_current_regcache (); + + /* If the traceframe's address matches any of the tracepoint's + locations, assume it is a direct hit rather than a while-stepping + frame. (FIXME this is not reliable, should record each frame's + type.) */ + for (tloc = t->base.loc; tloc; tloc = tloc->next) + if (tloc->address == regcache_read_pc (regcache)) + { + *stepping_frame_p = 0; + return tloc; + } + + /* If this is a stepping frame, we don't know which location + triggered. The first is as good (or bad) a guess as any... */ + *stepping_frame_p = 1; + return t->base.loc; +} + /* Return all the actions, including default collect, of a tracepoint T. It constructs cleanups into the chain, and leaves the caller to handle them (call do_cleanups). */ @@ -2982,46 +3024,19 @@ all_tracepoint_actions_and_cleanup (struct breakpoint *t) static void trace_dump_command (char *args, int from_tty) { - struct regcache *regcache; - struct tracepoint *t; int stepping_frame = 0; struct bp_location *loc; - char *default_collect_line = NULL; - struct command_line *actions, *default_collect_action = NULL; struct cleanup *old_chain; + struct command_line *actions; - if (tracepoint_number == -1) - { - warning (_("No current trace frame.")); - return; - } - - old_chain = make_cleanup (null_cleanup, NULL); - t = get_tracepoint (tracepoint_number); - - if (t == NULL) - error (_("No known tracepoint matches 'current' tracepoint #%d."), - tracepoint_number); + /* This throws an error is not inspecting a trace frame. */ + loc = get_traceframe_location (&stepping_frame); printf_filtered ("Data collected at tracepoint %d, trace frame %d:\n", tracepoint_number, traceframe_number); - /* The current frame is a trap frame if the frame PC is equal - to the tracepoint PC. If not, then the current frame was - collected during single-stepping. */ - - regcache = get_current_regcache (); - - /* If the traceframe's address matches any of the tracepoint's - locations, assume it is a direct hit rather than a while-stepping - frame. (FIXME this is not reliable, should record each frame's - type.) */ - stepping_frame = 1; - for (loc = t->base.loc; loc; loc = loc->next) - if (loc->address == regcache_read_pc (regcache)) - stepping_frame = 0; - - actions = all_tracepoint_actions_and_cleanup (&t->base); + old_chain = make_cleanup (null_cleanup, NULL); + actions = all_tracepoint_actions_and_cleanup (loc->owner); trace_dump_actions (actions, 0, stepping_frame, from_tty); -- 1.7.7.6 ^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PATCH 2/5] Move code to get_traceframe_location. 2013-06-07 13:07 ` [PATCH 2/5] Move code to get_traceframe_location Yao Qi @ 2013-06-07 21:09 ` Pedro Alves 0 siblings, 0 replies; 36+ messages in thread From: Pedro Alves @ 2013-06-07 21:09 UTC (permalink / raw) To: Yao Qi; +Cc: gdb-patches On 06/07/2013 02:08 PM, Yao Qi wrote: > This patch is a refactor patch. Mainly, but not only. > +static struct bp_location * > +get_traceframe_location (int *stepping_frame_p) > +{ > + if (tracepoint_number == -1) > + error (_("No current trace frame.")); > +} > + > @@ -2982,46 +3024,19 @@ all_tracepoint_actions_and_cleanup (struct breakpoint *t) > static void > trace_dump_command (char *args, int from_tty) > { > - if (tracepoint_number == -1) > - { > - warning (_("No current trace frame.")); > - return; > - } There's a behavior change here. Can you split that out to a separate, preparatory patch, please? -- Pedro Alves ^ permalink raw reply [flat|nested] 36+ messages in thread
* [PATCH 5/5] New test: gdb.trace/mi-trace-frame-collected.exp 2013-06-07 13:07 [PATCH 0/5] New MI command -trace-frame-collected Yao Qi ` (3 preceding siblings ...) 2013-06-07 13:07 ` [PATCH 2/5] Move code to get_traceframe_location Yao Qi @ 2013-06-07 13:07 ` Yao Qi 2013-06-13 1:29 ` [PATCH 0/6 V2] New MI command -trace-frame-collected Yao Qi 5 siblings, 0 replies; 36+ messages in thread From: Yao Qi @ 2013-06-07 13:07 UTC (permalink / raw) To: gdb-patches gdb/testsuite 2013-06-07 Yao Qi <yao@codesourcery.com> * gdb.trace/mi-trace-frame-collected.exp: New. --- .../gdb.trace/mi-trace-frame-collected.exp | 154 ++++++++++++++++++++ 1 files changed, 154 insertions(+), 0 deletions(-) create mode 100644 gdb/testsuite/gdb.trace/mi-trace-frame-collected.exp diff --git a/gdb/testsuite/gdb.trace/mi-trace-frame-collected.exp b/gdb/testsuite/gdb.trace/mi-trace-frame-collected.exp new file mode 100644 index 0000000..d79eaa7 --- /dev/null +++ b/gdb/testsuite/gdb.trace/mi-trace-frame-collected.exp @@ -0,0 +1,154 @@ +# Copyright 2013 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +load_lib trace-support.exp + +standard_testfile actions.c + +if { [prepare_for_testing ${testfile}.exp ${testfile} ${srcfile} {debug}] } { + return -1 +} + +if ![runto_main] { + fail "Can't run to main to check for trace support" + return -1 +} + +if ![gdb_target_supports_trace] { + unsupported "Current target does not support trace" + return -1 +} + +gdb_exit + +load_lib mi-support.exp +set MIFLAGS "-i=mi" + +if [mi_gdb_start] { + return +} +mi_run_to_main + +mi_gdb_test "-break-insert end" \ + "\\^done,bkpt=\{number=\"${decimal}\",type=\"breakpoint\".*\"\}" \ + "insert tracepoint on end" +mi_gdb_test "-break-insert -a gdb_recursion_test" \ + "\\^done,bkpt=\{number=\"${decimal}\",type=\"tracepoint\".*\"\}" \ + "insert tracepoint on gdb_recursion_test" + +mi_gdb_test "-trace-define-variable \$tsv 1" {.*\^done} \ + "-trace-define-variable" + +# Define an action. +set pcreg "" +if [is_amd64_regs_target] { + set pcreg "rip" +} elseif [is_x86_like_target] { + set pcreg "eip" +} else { + # Other ports support tracepoing should set the name of pc + # register. + fail "set the number and the name of pc register" + return -1 +} + +mi_gdb_test "-break-commands 3 \"collect gdb_char_test\" \"collect gdb_union1_test\" \"collect gdb_struct1_test.l\" \"collect gdb_arr_test\[0\]\" \"collect $${pcreg}\" \"teval \$tsv += 1\" \"collect \$tsv\" \"end\" " \ + {\^done} "set action" + +mi_gdb_test "-break-insert -a gdb_c_test" \ + "\\^done,bkpt=\{number=\"${decimal}\",type=\"tracepoint\".*\"\}" \ + "insert tracepoint on gdb_c_test" +# Collect a global variable to make sure no registers are collected +# expect PC. +mi_gdb_test "-break-commands 4 \"collect gdb_char_test\" \"end\" " \ + {\^done} "set action on tracepoint 4" + +mi_gdb_test "-trace-start" {.*\^done} "trace start" +mi_send_resuming_command "exec-continue" "continuing to end" +mi_expect_stop \ + "breakpoint-hit" "end" ".*" ".*" ".*" {"" "disp=\"keep\""} \ + "stop at end" +mi_gdb_test "-trace-stop" {.*\^done,stop-reason=.*} "trace stop" + +# Save trace frames to tfile. +set tracefile [standard_output_file ${testfile}] +mi_gdb_test "-trace-save ${tracefile}.tf" ".*\\^done" \ + "save tfile trace file" +# Save trace frames to ctf. +mi_gdb_test "-trace-save -ctf ${tracefile}.ctf" ".*\\^done" \ + "save ctf trace file" + +# Test MI command '-trace-frame-collected' from different data source. + +proc test_trace_frame_collected { data_source } { + global decimal hex + global mi_gdb_prompt + + with_test_prefix "$data_source" { + mi_gdb_test "-trace-find frame-number 0" \ + ".*\\^done,found=\"1\",tracepoint=\"${decimal}\",traceframe=\"0\",frame=\{.*" \ + "-trace-find frame-number 0" + + # Test MI command '-trace-frame-collected' dumps only + # collected registers. + mi_gdb_test "-trace-frame-collected" \ + "\\^done,explicit-variables=\\\[\{name=\"gdb_char_test\",value=\".*\"\}\\\],computed-expressions=\\\[\\\],registers=\\\[\{number=\"$decimal\",value=\"$hex\"\}\\\],tvars=\\\[\\\],memory=\\\[\{address=\"$hex\",length=\"1\"\}\\\]"\ + "-trace-frame-collected (register)" + + mi_gdb_test "-trace-find frame-number 1" \ + ".*\\^done,found=\"1\",tracepoint=\"${decimal}\",traceframe=\"1\",frame=\{.*" \ + "-trace-find frame-number 1" + + # Test MI command '-trace-frame-collected' + mi_gdb_test "-trace-frame-collected" \ + "\\^done,explicit-variables=\\\[\{name=\"gdb_char_test\",value=\".*\"\},\{name=\"gdb_union1_test\",value=\".*\"\}\\\],computed-expressions=\\\[\{name=\"gdb_struct1_test\.l\",.*\},\{name=\"gdb_arr_test\\\[0\\\]\",.*\}\\\],registers=\\\[.*\\\],tvars=\\\[\{name=\"\\\$tsv\",current=\"2\"\}\\\],memory=\\\[\{address=\"$hex\",length=\"1\"\},.*\\\]"\ + "-trace-frame-collected" + mi_gdb_test "-trace-frame-collected --var-print-values 2 --comp-print-values --simple-values --registers-format x --memory-contents" \ + "\\^done,explicit-variables=\\\[\{name=\"gdb_char_test\",type=\"char\",value=\".*\"\},\{name=\"gdb_union1_test\",type=\"union GDB_UNION_TEST\"\}\\\],computed-expressions=\\\[.*\\\],registers=\\\[.*\\\],tvars=\\\[\{name=\"\\\$tsv\",current=\"2\"\}\\\],memory=\\\[\{address=\"$hex\",length=\"1\",contents=\".*\"\},.*\\\]" \ + "-trace-frame-collected --var-print-values 2 --comp-print-values --simple-values --registers-format x --memory-contents" + + mi_gdb_test "-trace-find none" ".*\\^done,found=\"0\".*" \ + "-trace-find none" + } +} + +test_trace_frame_collected "live" + +# Change target to ctf if GDB supports it. +set msg "-target-select ctf" +send_gdb "-target-select ctf ${tracefile}.ctf\n" +gdb_expect { + -re ".*\\^connected.*${mi_gdb_prompt}$" { + # GDB supports ctf, do the test. + test_trace_frame_collected "ctf" + } + -re ".*\\^error,msg=\"Undefined target command.*${mi_gdb_prompt}$" { + # GDB doesn't support ctf, skip the test. + unsupported "gdb does not support ctf target" + } + -re ".*$mi_gdb_prompt$" { + fail "$msg" + } + timeout { + fail "$msg (timeout)" + } +} + +# Change target to tfile. +mi_gdb_test "-target-select tfile ${tracefile}.tf" ".*\\^connected.*" \ + "-target-select tfile" +test_trace_frame_collected "tfile" + +mi_gdb_exit -- 1.7.7.6 ^ permalink raw reply [flat|nested] 36+ messages in thread
* [PATCH 0/6 V2] New MI command -trace-frame-collected 2013-06-07 13:07 [PATCH 0/5] New MI command -trace-frame-collected Yao Qi ` (4 preceding siblings ...) 2013-06-07 13:07 ` [PATCH 5/5] New test: gdb.trace/mi-trace-frame-collected.exp Yao Qi @ 2013-06-13 1:29 ` Yao Qi 2013-06-13 1:29 ` [PATCH 5/6] " Yao Qi ` (6 more replies) 5 siblings, 7 replies; 36+ messages in thread From: Yao Qi @ 2013-06-13 1:29 UTC (permalink / raw) To: gdb-patches Hi, In a given traceframe, there are explicitly collected variables, registers, trace state variables, memories, and computed expressions. In MI, we don't have a command to dump these contents, and this patch adds -trace-frame-collected to do so. Patch 5/6 is the major part of this series, and patch 6/6 is the test to -trace-frame-collected. GDB needs to know what trace state variables are collected in a traceframe, so we extended the qXfer:traceframe-info object to report the set of collected trace state variables in the current traceframe. That is what patch 4/5 does. Patch 1/6, 2/6 and 3/6 is code refactor. The whole series are tested on x86_64-linux with native and gdbserver. This is the V2 of this series. In V2, there are several changes: - Mention some changes in ChangeLog entry and correct comments. - Split the changes on encode_actions in a different way, which is more readable. - Move the change from warning to error to a separate patch. - Explain what 'tvar' element does in NEWS. The V1 can be found <http://sourceware.org/ml/gdb-patches/2013-06/msg00148.html> *** BLURB HERE *** Yao Qi (6): Remove global variable tracepoint_list and stepping_list. Emit error in tdump command when traceframe is not selected. Move code to get_traceframe_location. Add id of TSV into traceframe_info. New MI command -trace-frame-collected New test: gdb.trace/mi-trace-frame-collected.exp gdb/NEWS | 11 + gdb/breakpoint.c | 2 - gdb/common/filestuff.c | 2 - gdb/common/gdb_vecs.h | 2 + gdb/ctf.c | 12 + gdb/doc/gdb.texinfo | 122 ++++++++- gdb/dwarf2loc.c | 2 - gdb/features/traceframe-info.dtd | 5 +- gdb/gdbserver/tracepoint.c | 7 + gdb/mi/mi-cmds.c | 2 + gdb/mi/mi-cmds.h | 1 + gdb/mi/mi-main.c | 299 +++++++++++++++++++- gdb/remote.c | 2 +- .../gdb.trace/mi-trace-frame-collected.exp | 154 ++++++++++ gdb/tracepoint.c | 304 +++++++++++++------- gdb/tracepoint.h | 50 +++- 16 files changed, 858 insertions(+), 119 deletions(-) create mode 100644 gdb/testsuite/gdb.trace/mi-trace-frame-collected.exp -- 1.7.7.6 ^ permalink raw reply [flat|nested] 36+ messages in thread
* [PATCH 5/6] New MI command -trace-frame-collected 2013-06-13 1:29 ` [PATCH 0/6 V2] New MI command -trace-frame-collected Yao Qi @ 2013-06-13 1:29 ` Yao Qi 2013-06-13 14:27 ` Eli Zaretskii 2013-06-13 1:29 ` [PATCH 4/6] Add id of TSV into traceframe_info Yao Qi ` (5 subsequent siblings) 6 siblings, 1 reply; 36+ messages in thread From: Yao Qi @ 2013-06-13 1:29 UTC (permalink / raw) To: gdb-patches This patch adds the new MI command -trace-frame-collected, which can dump explicitly collected variables, computed expressions, tvars, memory and registers. See details in the doc about MI command options. Two new fields wholly_collected and computed are added in 'struct collection_list' to record the wholly collected objects and computed expressions during parsing actions. gdb/doc: 2013-06-13 Pedro Alves <pedro@codesourcery.com> * gdb.texinfo (GDB/MI Tracepoint Commands): Document -trace-frame-collected. gdb: 2013-06-13 Pedro Alves <pedro@codesourcery.com> Yao Qi <yao@codesourcery.com> * mi/mi-cmds.c (mi_cmds): Register -trace-frame-collected. * mi/mi-cmds.h (mi_cmd_trace_frame_collected): Declare. * mi/mi-main.c (print_variable_or_computed): New function. (mi_cmd_trace_frame_collected): New function. * tracepoint.c (find_trace_state_variable_by_number): New. (struct traceframe_info): Move to tracepoint.h (struct collection_list): Likewise. (do_collect_symbol): Include locals and arguments in the wholly collected variables list. (clear_collection_list): Clear wholly collected variables list and computed variables list. (append_exp): New function. (encode_actions_1): Include variables in the wholly collected variables list. Include memory ranges and full-fledged expressions in the computed expressions list. (encode_actions): Move some code to ... Return the cleanup chain. (encode_actions_rsp): ... here. (get_traceframe_location, get_traceframe_info): Remove static. * tracepoint.h (struct memrange): Moved from tracepoint.c. (struct collection_list): Moved from tracepoint.c. Add two new fields 'wholly_collected' and 'computed'. (find_trace_state_variable_by_number): Declare. (encode_actions): Adjust declaration. (encode_actions_rsp): Declare. (get_traceframe_info, get_traceframe_location): Declare. * NEWS: Mention new MI command -trace-frame-collected --- gdb/NEWS | 4 + gdb/doc/gdb.texinfo | 110 +++++++++++++++++++ gdb/mi/mi-cmds.c | 2 + gdb/mi/mi-cmds.h | 1 + gdb/mi/mi-main.c | 297 +++++++++++++++++++++++++++++++++++++++++++++++++++ gdb/remote.c | 2 +- gdb/tracepoint.c | 144 ++++++++++++++++--------- gdb/tracepoint.h | 47 ++++++++- 8 files changed, 553 insertions(+), 54 deletions(-) diff --git a/gdb/NEWS b/gdb/NEWS index 2c66db7..d480f45 100644 --- a/gdb/NEWS +++ b/gdb/NEWS @@ -80,6 +80,10 @@ show range-stepping "--skip-unavailable" option. When used, only the available registers are displayed. + ** The new command -trace-frame-collected dumps explicitly collected + variables, computed expressions, tvars, memory and registers in a + traceframe. + * New system-wide configuration scripts A GDB installation now provides scripts suitable for use as system-wide configuration scripts for the following systems: diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo index 3992704..1a5fe28 100644 --- a/gdb/doc/gdb.texinfo +++ b/gdb/doc/gdb.texinfo @@ -33161,6 +33161,116 @@ with the @samp{$} character. The corresponding @value{GDBN} command is @samp{tvariable}. +@subheading The @code{-trace-frame-collected} Command +@findex -trace-frame-collected + +@subsubheading Synopsis + +@smallexample + -trace-frame-collected + [--var-print-values @var{var_pval}] + [--comp-print-values @var{comp_pval}] + [--registers-format @var{regformat}] + [--memory-contents] +@end smallexample + +This command returns the set of explicitly wholly collected objects, +register names, trace state variable names, memory ranges and computed +expressions that have been collected at a particular trace frame. The +optional parameters to the command affect the output format in +different ways. See the output description table below for more +details. + +The reported names can be used in the normal manner to create +varobjs and inspect the objects themselves. The items returned by +this command are categorized so that it is clear which is a variable, +which is a register, which is a trace state variable, which is a +memory range and which is a computed expression. + +For instance, if the actions were @code{myVar, myArray[myIndex] +myObj.field, myPtr->field, myCount + 2, *(int*)0xaf02bef0@@40}, the +set of named objects explicitly wholly collected would be +@code{myVar}, and the set of computed expressions would be +@code{myArray[myIndex], myObj.field, myPtr->field, myCount + 2, +*(int*)0xaf02bef0@@40}. + +An example output would be: + +@smallexample +(gdb) +-trace-frame-collected +^done, + explicit-variables=[@{name="i",value="1"@}], + computed-expressions=[@{name="a.b",value="0"@}, + @{name="array[5]",value="0"@}, + @{name="$tvar1 + 1",value="43970027"@}], + registers=[@{number="0",value="0x7fe2c6e79ec8"@}, + @{number="1",value="0x0"@}, + @{number="2",value="0x4"@}, + ... + @{number="125",value="0x0"@}], + tvars=[@{name="$tvar1",current="43970026"@}], + memory=[@{address="0x0000000000602264",length="4"@}, + @{address="0x0000000000615bc0",length="4"@}] +(gdb) +@end smallexample + +Where: + +@table @code +@item explicit-variables +The set of objects that have been explicitly wholly collected at the +current trace frame. For each object, its name and value are printed. +The @code{--var-print-values} option affects how or whether the value +field is output. If @var{var_pval} is 0, then print only the names; +if it is 1, print also their values; and if it is 2, print the name, +type and value for simple data types, and the name and type for +arrays, structures and unions. + +@item computed-expressions +The set of computed expressions that have been collected at the +current trace frame. The @code{--comp-print-values} option affects +this set, as the @code{--var-print-values} option affects the +@code{explicit-variables} set. See above. + +@item registers +The registers that have been collected at the current trace frame. +For each register collected, the name and current value are returned. +The value is formatted according to the @code{--registers-format} +option. See the @command{-data-list-register-values} command for a +list of the allowed formats. The default is @samp{x}. + +@item tvars +The trace state variables that have been collected at the current +trace frame. For each trace state variable collected, the name and +current value are returned. + +@item memory +The set of memory ranges that have been collected at the current trace +frame. Its content is a list of tuples. Each tuple represents a +collected memory range and has the following fields: + +@table @code +@item address +The start address of the memory range, as hexadecimal literal. + +@item length +The length of the memory range, as decimal literal. + +@item contents +The contents of the memory block, in hex. This field is only present +if the @code{--memory-contents} options is specified. + +@end table + +@end table + +@subsubheading @value{GDBN} Command + +There is no corresponding @value{GDBN} command. + +@subsubheading Example + @subheading -trace-list-variables @findex -trace-list-variables diff --git a/gdb/mi/mi-cmds.c b/gdb/mi/mi-cmds.c index eb67abe..0768b2a 100644 --- a/gdb/mi/mi-cmds.c +++ b/gdb/mi/mi-cmds.c @@ -148,6 +148,8 @@ static struct mi_cmd mi_cmds[] = DEF_MI_CMD_MI ("trace-define-variable", mi_cmd_trace_define_variable), DEF_MI_CMD_MI_1 ("trace-find", mi_cmd_trace_find, &mi_suppress_notification.traceframe), + DEF_MI_CMD_MI ("trace-frame-collected", + mi_cmd_trace_frame_collected), DEF_MI_CMD_MI ("trace-list-variables", mi_cmd_trace_list_variables), DEF_MI_CMD_MI ("trace-save", mi_cmd_trace_save), DEF_MI_CMD_MI ("trace-start", mi_cmd_trace_start), diff --git a/gdb/mi/mi-cmds.h b/gdb/mi/mi-cmds.h index 8839319..a472582 100644 --- a/gdb/mi/mi-cmds.h +++ b/gdb/mi/mi-cmds.h @@ -94,6 +94,7 @@ extern mi_cmd_argv_ftype mi_cmd_thread_list_ids; extern mi_cmd_argv_ftype mi_cmd_thread_select; extern mi_cmd_argv_ftype mi_cmd_trace_define_variable; extern mi_cmd_argv_ftype mi_cmd_trace_find; +extern mi_cmd_argv_ftype mi_cmd_trace_frame_collected; extern mi_cmd_argv_ftype mi_cmd_trace_list_variables; extern mi_cmd_argv_ftype mi_cmd_trace_save; extern mi_cmd_argv_ftype mi_cmd_trace_start; diff --git a/gdb/mi/mi-main.c b/gdb/mi/mi-main.c index 430d530..0b8740da 100644 --- a/gdb/mi/mi-main.c +++ b/gdb/mi/mi-main.c @@ -2585,3 +2585,300 @@ mi_cmd_ada_task_info (char *command, char **argv, int argc) print_ada_task_info (current_uiout, argv[0], current_inferior ()); } + +/* Print EXPRESSION according to VALUES. */ + +static void +print_variable_or_computed (char *expression, enum print_values values) +{ + struct expression *expr; + struct cleanup *old_chain; + struct value *val; + struct ui_file *stb; + struct value_print_options opts; + struct type *type; + struct ui_out *uiout = current_uiout; + + stb = mem_fileopen (); + old_chain = make_cleanup_ui_file_delete (stb); + + expr = parse_expression (expression); + + make_cleanup (free_current_contents, &expr); + + if (values == PRINT_SIMPLE_VALUES) + val = evaluate_type (expr); + else + val = evaluate_expression (expr); + + if (values != PRINT_NO_VALUES) + make_cleanup_ui_out_tuple_begin_end (uiout, NULL); + ui_out_field_string (uiout, "name", expression); + + switch (values) + { + case PRINT_SIMPLE_VALUES: + type = check_typedef (value_type (val)); + type_print (value_type (val), "", stb, -1); + ui_out_field_stream (uiout, "type", stb); + if (TYPE_CODE (type) != TYPE_CODE_ARRAY + && TYPE_CODE (type) != TYPE_CODE_STRUCT + && TYPE_CODE (type) != TYPE_CODE_UNION) + { + struct value_print_options opts; + + get_raw_print_options (&opts); + opts.deref_ref = 1; + common_val_print (val, stb, 0, &opts, current_language); + ui_out_field_stream (uiout, "value", stb); + } + break; + case PRINT_ALL_VALUES: + { + struct value_print_options opts; + + get_raw_print_options (&opts); + opts.deref_ref = 1; + common_val_print (val, stb, 0, &opts, current_language); + ui_out_field_stream (uiout, "value", stb); + } + break; + } + + do_cleanups (old_chain); +} + +/* Implement the "-trace-frame-collected" command. */ + +void +mi_cmd_trace_frame_collected (char *command, char **argv, int argc) +{ + struct cleanup *old_chain; + struct bp_location *tloc; + int stepping_frame; + struct collection_list *clist; + struct traceframe_info *tinfo; + int oind = 0; + int var_print_values = PRINT_ALL_VALUES; + int comp_print_values = PRINT_ALL_VALUES; + int registers_format = 'x'; + int memory_contents = 0; + struct ui_out *uiout = current_uiout; + enum opt + { + VAR_PRINT_VALUES, + COMP_PRINT_VALUES, + REGISTERS_FORMAT, + MEMORY_CONTENTS, + }; + static const struct mi_opt opts[] = + { + {"-var-print-values", VAR_PRINT_VALUES, 1}, + {"-comp-print-values", COMP_PRINT_VALUES, 1}, + {"-registers-format", REGISTERS_FORMAT, 1}, + {"-memory-contents", MEMORY_CONTENTS, 0}, + { 0, 0, 0 } + }; + + while (1) + { + char *oarg; + int opt = mi_getopt ("-trace-frame-collected", argc, argv, opts, + &oind, &oarg); + if (opt < 0) + break; + switch ((enum opt) opt) + { + case VAR_PRINT_VALUES: + var_print_values = mi_parse_print_values (oarg); + break; + case COMP_PRINT_VALUES: + comp_print_values = mi_parse_print_values (oarg); + break; + case REGISTERS_FORMAT: + registers_format = oarg[0]; + case MEMORY_CONTENTS: + memory_contents = 1; + break; + } + } + + if (oind != argc) + error (_("Usage: -trace-frame-collected " + "[--var-print-values PRINT_VALUES] " + "[--comp-print-values PRINT_VALUES] " + "[--registers-format FORMAT]" + "[--memory-contents]")); + + /* This throws an error is not inspecting a trace frame. */ + tloc = get_traceframe_location (&stepping_frame); + + /* This command only makes sense for the current frame, not the + selected frame. */ + old_chain = make_cleanup_restore_current_thread (); + select_frame (get_current_frame ()); + + { + struct collection_list tracepoint_list, stepping_list; + + encode_actions (tloc, &tracepoint_list, &stepping_list); + + if (stepping_frame) + clist = &stepping_list; + else + clist = &tracepoint_list; + } + + tinfo = get_traceframe_info (); + + /* Explicitly wholly collected variables. */ + { + struct cleanup *list_cleanup; + char *p; + int i; + + list_cleanup = make_cleanup_ui_out_list_begin_end (uiout, + "explicit-variables"); + for (i = 0; VEC_iterate (char_ptr, clist->wholly_collected, i, p); i++) + print_variable_or_computed (p, var_print_values); + do_cleanups (list_cleanup); + } + + /* Computed expressions. */ + { + struct cleanup *list_cleanup; + char *p; + int i; + + list_cleanup + = make_cleanup_ui_out_list_begin_end (uiout, + "computed-expressions"); + for (i = 0; VEC_iterate (char_ptr, clist->computed, i, p); i++) + print_variable_or_computed (p, comp_print_values); + do_cleanups (list_cleanup); + } + + /* Registers. Given pseudo-registers, and that some architectures + (like MIPS) actually hide the raw registers, we don't go through + the trace frame info, but instead consult the register cache for + register availability. */ + { + struct cleanup *list_cleanup; + struct frame_info *frame; + struct gdbarch *gdbarch; + int regnum; + int numregs; + + list_cleanup = make_cleanup_ui_out_list_begin_end (uiout, "registers"); + + frame = get_selected_frame (NULL); + gdbarch = get_frame_arch (frame); + numregs = gdbarch_num_regs (gdbarch) + gdbarch_num_pseudo_regs (gdbarch); + + for (regnum = 0; regnum < numregs; regnum++) + { + if (gdbarch_register_name (gdbarch, regnum) == NULL + || *(gdbarch_register_name (gdbarch, regnum)) == '\0') + continue; + + output_register (frame, regnum, registers_format, 1); + } + + do_cleanups (list_cleanup); + } + + /* Trace state variables. */ + { + struct cleanup *list_cleanup; + int tvar; + char *tsvname; + int i; + + list_cleanup = make_cleanup_ui_out_list_begin_end (uiout, "tvars"); + + tsvname = NULL; + make_cleanup (free_current_contents, &tsvname); + + for (i = 0; VEC_iterate (int, tinfo->tvars, i, tvar); i++) + { + struct cleanup *cleanup_child; + struct trace_state_variable *tsv; + + tsv = find_trace_state_variable_by_number (tvar); + + cleanup_child = make_cleanup_ui_out_tuple_begin_end (uiout, NULL); + + if (tsv != NULL) + { + tsvname = xrealloc (tsvname, strlen (tsv->name) + 2); + tsvname[0] = '$'; + strcpy (tsvname + 1, tsv->name); + ui_out_field_string (uiout, "name", tsvname); + + tsv->value_known = target_get_trace_state_variable_value (tsv->number, + &tsv->value); + ui_out_field_int (uiout, "current", tsv->value); + } + else + { + ui_out_field_skip (uiout, "name"); + ui_out_field_skip (uiout, "current"); + } + + do_cleanups (cleanup_child); + } + + do_cleanups (list_cleanup); + } + + /* Memory. */ + { + struct cleanup *list_cleanup; + VEC(mem_range_s) *available_memory = NULL; + struct mem_range *r; + int i; + + traceframe_available_memory (&available_memory, 0, ULONGEST_MAX); + make_cleanup (VEC_cleanup(mem_range_s), &available_memory); + + list_cleanup = make_cleanup_ui_out_list_begin_end (uiout, "memory"); + + for (i = 0; VEC_iterate (mem_range_s, available_memory, i, r); i++) + { + struct cleanup *cleanup_child; + gdb_byte *data; + struct gdbarch *gdbarch = target_gdbarch (); + + cleanup_child = make_cleanup_ui_out_tuple_begin_end (uiout, NULL); + + ui_out_field_core_addr (uiout, "address", gdbarch, r->start); + ui_out_field_int (uiout, "length", r->length); + + data = xmalloc (r->length); + make_cleanup (xfree, data); + + if (memory_contents) + { + if (target_read_memory (r->start, data, r->length) == 0) + { + int m; + char *data_str, *p; + + data_str = xmalloc (r->length * 2 + 1); + make_cleanup (xfree, data_str); + + for (m = 0, p = data_str; m < r->length; ++m, p += 2) + sprintf (p, "%02x", data[m]); + ui_out_field_string (uiout, "contents", data_str); + } + else + ui_out_field_skip (uiout, "contents"); + } + do_cleanups (cleanup_child); + } + + do_cleanups (list_cleanup); + } + + do_cleanups (old_chain); +} diff --git a/gdb/remote.c b/gdb/remote.c index 080d048..d06b1ed 100644 --- a/gdb/remote.c +++ b/gdb/remote.c @@ -10524,7 +10524,7 @@ remote_download_tracepoint (struct bp_location *loc) struct breakpoint *b = loc->owner; struct tracepoint *t = (struct tracepoint *) b; - encode_actions (loc, &tdp_actions, &stepping_actions); + encode_actions_rsp (loc, &tdp_actions, &stepping_actions); old_chain = make_cleanup (free_actions_list_cleanup_wrapper, tdp_actions); (void) make_cleanup (free_actions_list_cleanup_wrapper, diff --git a/gdb/tracepoint.c b/gdb/tracepoint.c index d7d0e88..4f10c93 100644 --- a/gdb/tracepoint.c +++ b/gdb/tracepoint.c @@ -340,6 +340,22 @@ find_trace_state_variable (const char *name) return NULL; } +/* Return the tsv if its number is NUMBER. Return NULL if not + found. */ + +struct trace_state_variable * +find_trace_state_variable_by_number (int number) +{ + struct trace_state_variable *tsv; + int ix; + + for (ix = 0; VEC_iterate (tsv_s, tvariables, ix, tsv); ++ix) + if (tsv->number == number) + return tsv; + + return NULL; +} + static void delete_trace_state_variable (const char *name) { @@ -853,29 +869,6 @@ enum { memrange_absolute = -1 }; -struct memrange -{ - int type; /* memrange_absolute for absolute memory range, - else basereg number. */ - bfd_signed_vma start; - bfd_signed_vma end; -}; - -struct collection_list - { - unsigned char regs_mask[32]; /* room for up to 256 regs */ - long listsize; - long next_memrange; - struct memrange *list; - long aexpr_listsize; /* size of array pointed to by expr_list elt */ - long next_aexpr_elt; - struct agent_expr **aexpr_list; - - /* True is the user requested a collection of "$_sdata", "static - tracepoint data". */ - int strace_data; - }; - /* MEMRANGE functions: */ static int memrange_cmp (const void *, const void *); @@ -1166,6 +1159,9 @@ do_collect_symbol (const char *print_name, collect_symbol (p->collect, 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)); } /* Add all locals (or args) symbols to collection list. */ @@ -1242,6 +1238,9 @@ clear_collection_list (struct collection_list *list) 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. */ @@ -1392,6 +1391,21 @@ stringify_collection_list (struct collection_list *list) return *str_list; } +/* Add the printed expression EXP to *LIST. */ + +static void +append_exp (struct expression *exp, VEC(char_ptr) **list) +{ + 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); + ui_file_delete (tmp_stream); +} static void encode_actions_1 (struct command_line *action, @@ -1537,16 +1551,25 @@ encode_actions_1 (struct command_line *action, check_typedef (exp->elts[1].type); add_memrange (collect, memrange_absolute, addr, TYPE_LENGTH (exp->elts[1].type)); + append_exp (exp, &collect->computed); break; case OP_VAR_VALUE: - collect_symbol (collect, - exp->elts[2].symbol, - tloc->gdbarch, - frame_reg, - frame_offset, - tloc->address, - trace_string); + { + 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); + } break; default: /* Full-fledged expression. */ @@ -1582,6 +1605,8 @@ encode_actions_1 (struct command_line *action, } } } + + append_exp (exp, &collect->computed); break; } /* switch */ do_cleanups (old_chain); @@ -1635,46 +1660,63 @@ encode_actions_1 (struct command_line *action, } /* for */ } -/* Render all actions into gdb protocol. */ +/* 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. */ -void -encode_actions (struct bp_location *tloc, char ***tdp_actions, - char ***stepping_actions) +struct cleanup * +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; - struct collection_list tracepoint_list, stepping_list; - - back_to = make_cleanup (null_cleanup, NULL); + struct cleanup *back_to, *return_chain; - init_collection_list (&tracepoint_list); - init_collection_list (&stepping_list); + 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); - - *tdp_actions = NULL; - *stepping_actions = NULL; + 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); actions = all_tracepoint_actions_and_cleanup (tloc->owner); encode_actions_1 (actions, tloc, frame_reg, frame_offset, - &tracepoint_list, &stepping_list); + tracepoint_list, stepping_list); - memrange_sortmerge (&tracepoint_list); - memrange_sortmerge (&stepping_list); + memrange_sortmerge (tracepoint_list); + memrange_sortmerge (stepping_list); + + do_cleanups (back_to); + return return_chain; +} + +/* Render all actions into gdb protocol. */ + +void +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 (tloc, &tracepoint_list, &stepping_list); *tdp_actions = stringify_collection_list (&tracepoint_list); *stepping_actions = stringify_collection_list (&stepping_list); - do_cleanups (back_to); + do_cleanups (cleanup); } static void @@ -2938,7 +2980,7 @@ trace_dump_actions (struct command_line *action, traceframe. Set *STEPPING_FRAME_P to 1 if the current traceframe is the stepping traceframe. */ -static struct bp_location * +struct bp_location * get_traceframe_location (int *stepping_frame_p) { struct tracepoint *t; @@ -5673,7 +5715,7 @@ parse_traceframe_info (const char *tframe_info) This is where we avoid re-fetching the object from the target if we already have it cached. */ -static struct traceframe_info * +struct traceframe_info * get_traceframe_info (void) { if (traceframe_info == NULL) diff --git a/gdb/tracepoint.h b/gdb/tracepoint.h index 350ab5e..e79ba3a 100644 --- a/gdb/tracepoint.h +++ b/gdb/tracepoint.h @@ -323,6 +323,38 @@ struct trace_file_writer const struct trace_file_write_ops *ops; }; +struct memrange +{ + /* memrange_absolute for absolute memory range, else basereg + number. */ + int type; + bfd_signed_vma start; + bfd_signed_vma end; +}; + +struct collection_list +{ + /* room for up to 256 regs */ + unsigned char regs_mask[32]; + long listsize; + long next_memrange; + struct memrange *list; + + /* size of array pointed to by expr_list elt. */ + long aexpr_listsize; + long next_aexpr_elt; + struct agent_expr **aexpr_list; + + /* True is the user requested a collection of "$_sdata", "static + tracepoint data". */ + int strace_data; + + /* A set of names of wholly collected objects. */ + VEC(char_ptr) *wholly_collected; + /* A set of computed expressions. */ + VEC(char_ptr) *computed; +}; + extern void parse_static_tracepoint_marker_definition (char *line, char **pp, struct static_tracepoint_marker *marker); @@ -360,13 +392,20 @@ void free_actions (struct breakpoint *); extern const char *decode_agent_options (const char *exp, int *trace_string); -extern void encode_actions (struct bp_location *tloc, - char ***tdp_actions, char ***stepping_actions); +extern struct cleanup *encode_actions (struct bp_location *tloc, + struct collection_list *tracepoint_list, + struct collection_list *stepping_list); + +extern void encode_actions_rsp (struct bp_location *tloc, + char ***tdp_actions, char ***stepping_actions); extern void validate_actionline (const char *, struct breakpoint *); extern void validate_trace_state_variable_name (const char *name); extern struct trace_state_variable *find_trace_state_variable (const char *name); +extern struct trace_state_variable * + find_trace_state_variable_by_number (int number); + extern struct trace_state_variable *create_trace_state_variable (const char *name); extern int encode_source_string (int num, ULONGEST addr, @@ -416,4 +455,8 @@ extern struct traceframe_info *parse_traceframe_info (const char *tframe_info); extern int traceframe_available_memory (VEC(mem_range_s) **result, CORE_ADDR memaddr, ULONGEST len); +extern struct traceframe_info *get_traceframe_info (void); + +extern struct bp_location *get_traceframe_location (int *stepping_frame_p); + #endif /* TRACEPOINT_H */ -- 1.7.7.6 ^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PATCH 5/6] New MI command -trace-frame-collected 2013-06-13 1:29 ` [PATCH 5/6] " Yao Qi @ 2013-06-13 14:27 ` Eli Zaretskii 2013-06-14 9:52 ` Yao Qi 0 siblings, 1 reply; 36+ messages in thread From: Eli Zaretskii @ 2013-06-13 14:27 UTC (permalink / raw) To: Yao Qi; +Cc: gdb-patches > From: Yao Qi <yao@codesourcery.com> > Date: Thu, 13 Jun 2013 09:28:33 +0800 > > This patch adds the new MI command -trace-frame-collected, which can > dump explicitly collected variables, computed expressions, tvars, > memory and registers. See details in the doc about MI command > options. Thanks. > diff --git a/gdb/NEWS b/gdb/NEWS > index 2c66db7..d480f45 100644 > --- a/gdb/NEWS > +++ b/gdb/NEWS > @@ -80,6 +80,10 @@ show range-stepping > "--skip-unavailable" option. When used, only the available registers > are displayed. > > + ** The new command -trace-frame-collected dumps explicitly collected > + variables, computed expressions, tvars, memory and registers in a > + traceframe. > + This is OK. > +This command returns the set of explicitly wholly collected objects, What is meant by "explicitly wholly collected objects"? That phrase got me confused, especially the "wholly" part. > +For instance, if the actions were @code{myVar, myArray[myIndex] > +myObj.field, myPtr->field, myCount + 2, *(int*)0xaf02bef0@@40}, the It is better to put the code part in @smallexample. > +@item computed-expressions > +The set of computed expressions that have been collected at the > +current trace frame. The @code{--comp-print-values} option affects > +this set, as the @code{--var-print-values} option affects the ^^ "like", not "as". And you don't need the comma before that. OK with the above changes, and assuming we resolve the "wholly" issue. ^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PATCH 5/6] New MI command -trace-frame-collected 2013-06-13 14:27 ` Eli Zaretskii @ 2013-06-14 9:52 ` Yao Qi 2013-06-14 12:34 ` Eli Zaretskii 0 siblings, 1 reply; 36+ messages in thread From: Yao Qi @ 2013-06-14 9:52 UTC (permalink / raw) To: Eli Zaretskii; +Cc: gdb-patches On 06/13/2013 09:09 PM, Eli Zaretskii wrote: > What is meant by "explicitly wholly collected objects"? That phrase > got me confused, especially the "wholly" part. > In tracepoint actions, variables can be collected, in whole or part. As the doc explained below, if myVar, myArray[myIndex], and myObj.field are collected, only myVar is collected as a whole or wholly collected and the rest are not. If myObj is collected in actions, it is wholly collected too. myArray is partially collected, since only element on index myIndex is collected, and we call it computed expressions here. -- Yao (é½å°§) ^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PATCH 5/6] New MI command -trace-frame-collected 2013-06-14 9:52 ` Yao Qi @ 2013-06-14 12:34 ` Eli Zaretskii 2013-06-17 10:21 ` Yao Qi 0 siblings, 1 reply; 36+ messages in thread From: Eli Zaretskii @ 2013-06-14 12:34 UTC (permalink / raw) To: Yao Qi; +Cc: gdb-patches > Date: Fri, 14 Jun 2013 17:37:09 +0800 > From: Yao Qi <yao@codesourcery.com> > CC: <gdb-patches@sourceware.org> > > On 06/13/2013 09:09 PM, Eli Zaretskii wrote: > > What is meant by "explicitly wholly collected objects"? That phrase > > got me confused, especially the "wholly" part. > > > > In tracepoint actions, variables can be collected, in whole or part. As > the doc explained below, if myVar, myArray[myIndex], and myObj.field are > collected, only myVar is collected as a whole or wholly collected and > the rest are not. If myObj is collected in actions, it is wholly > collected too. myArray is partially collected, since only element on > index myIndex is collected, and we call it computed expressions here. This is not described anywhere in the manual. In fact, the word "wholly" never appears in the manual and "whole" never appears in any context related to tracepoints. In the node "Tracepoint Actions", we don't make any distinction between collecting "in whole" and "in part". So if this distinction is important, please add to "Tracepoint Actions" the explanation similar to what you wrote above, and then make a cross-reference to that from the description of -trace-frame-collected. Thanks. ^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PATCH 5/6] New MI command -trace-frame-collected 2013-06-14 12:34 ` Eli Zaretskii @ 2013-06-17 10:21 ` Yao Qi 2013-06-17 15:48 ` Eli Zaretskii 0 siblings, 1 reply; 36+ messages in thread From: Yao Qi @ 2013-06-17 10:21 UTC (permalink / raw) To: Eli Zaretskii; +Cc: gdb-patches On 06/14/2013 06:41 PM, Eli Zaretskii wrote: > This is not described anywhere in the manual. In fact, the word > "wholly" never appears in the manual and "whole" never appears in any > context related to tracepoints. In the node "Tracepoint Actions", we > don't make any distinction between collecting "in whole" and "in > part". > > So if this distinction is important, please add to "Tracepoint > Actions" the explanation similar to what you wrote above, and then > make a cross-reference to that from the description of > -trace-frame-collected. This distinction is important to the commands displaying contents in a given traceframe, such as -trace-frame-collected, but this distinction is not important to trace actions. When users define actions, they just think of what they want to collect. It doesn't that matter that objects are collected wholly or partially. When users examine the collected data in traceframe, it is important or useful to show them which objects are wholly collected and which are not. So I'd like to explain the term "wholly" by the example we already have in the context of command -trace-frame-collected. What do you think? -- Yao (é½å°§) gdb/doc: 2013-06-17 Pedro Alves <pedro@codesourcery.com> Yao Qi <yao@codesourcery.com> * gdb.texinfo (GDB/MI Tracepoint Commands): Document -trace-frame-collected. gdb: 2013-06-17 Pedro Alves <pedro@codesourcery.com> Yao Qi <yao@codesourcery.com> * mi/mi-cmds.c (mi_cmds): Register -trace-frame-collected. * mi/mi-cmds.h (mi_cmd_trace_frame_collected): Declare. * mi/mi-main.c (print_variable_or_computed): New function. (mi_cmd_trace_frame_collected): New function. * tracepoint.c (find_trace_state_variable_by_number): New. (struct traceframe_info): Move to tracepoint.h (struct collection_list): Likewise. (do_collect_symbol): Include locals and arguments in the wholly collected variables list. (clear_collection_list): Clear wholly collected variables list and computed variables list. (append_exp): New function. (encode_actions_1): Include variables in the wholly collected variables list. Include memory ranges and full-fledged expressions in the computed expressions list. (encode_actions): Move some code to ... Return the cleanup chain. (encode_actions_rsp): ... here. New function. (get_traceframe_location, get_traceframe_info): Remove static. * tracepoint.h (struct memrange): Moved from tracepoint.c. (struct collection_list): Moved from tracepoint.c. Add two new fields 'wholly_collected' and 'computed'. (find_trace_state_variable_by_number): Declare. (encode_actions): Adjust declaration. (encode_actions_rsp): Declare. (get_traceframe_info, get_traceframe_location): Declare. * NEWS: Mention new MI command -trace-frame-collected. --- gdb/NEWS | 4 + gdb/doc/gdb.texinfo | 113 +++++++++++++++++++ gdb/mi/mi-cmds.c | 2 + gdb/mi/mi-cmds.h | 1 + gdb/mi/mi-main.c | 297 +++++++++++++++++++++++++++++++++++++++++++++++++++ gdb/remote.c | 2 +- gdb/tracepoint.c | 144 ++++++++++++++++--------- gdb/tracepoint.h | 47 ++++++++- 8 files changed, 556 insertions(+), 54 deletions(-) diff --git a/gdb/NEWS b/gdb/NEWS index 2c66db7..d480f45 100644 --- a/gdb/NEWS +++ b/gdb/NEWS @@ -80,6 +80,10 @@ show range-stepping "--skip-unavailable" option. When used, only the available registers are displayed. + ** The new command -trace-frame-collected dumps explicitly wholly collected + variables, computed expressions, tvars, memory and registers in a + traceframe. + * New system-wide configuration scripts A GDB installation now provides scripts suitable for use as system-wide configuration scripts for the following systems: diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo index 3992704..a2629c0 100644 --- a/gdb/doc/gdb.texinfo +++ b/gdb/doc/gdb.texinfo @@ -33161,6 +33161,119 @@ with the @samp{$} character. The corresponding @value{GDBN} command is @samp{tvariable}. +@subheading The @code{-trace-frame-collected} Command +@findex -trace-frame-collected + +@subsubheading Synopsis + +@smallexample + -trace-frame-collected + [--var-print-values @var{var_pval}] + [--comp-print-values @var{comp_pval}] + [--registers-format @var{regformat}] + [--memory-contents] +@end smallexample + +This command returns the set of explicitly wholly collected (explained +below with an example) objects, register names, trace state variable +names, memory ranges and computed expressions that have been collected +at a particular trace frame. The optional parameters to the command +affect the output format in different ways. See the output description +table below for more details. + +The reported names can be used in the normal manner to create +varobjs and inspect the objects themselves. The items returned by +this command are categorized so that it is clear which is a variable, +which is a register, which is a trace state variable, which is a +memory range and which is a computed expression. + +For instance, if the actions were +@smallexample +collect myVar, myArray[myIndex] myObj.field, myPtr->field, myCount + 2 +collect *(int*)0xaf02bef0@@40 +@end smallexample +the set of named objects explicitly wholly collected would be +@code{myVar}, because it is collected in whole. Object @code{myArray} +is partially collected, because only element on index @code{myIndex} +is collected. The rest of objects are computed expressions. + +An example output would be: + +@smallexample +(gdb) +-trace-frame-collected +^done, + explicit-variables=[@{name="i",value="1"@}], + computed-expressions=[@{name="a.b",value="0"@}, + @{name="array[5]",value="0"@}, + @{name="$tvar1 + 1",value="43970027"@}], + registers=[@{number="0",value="0x7fe2c6e79ec8"@}, + @{number="1",value="0x0"@}, + @{number="2",value="0x4"@}, + ... + @{number="125",value="0x0"@}], + tvars=[@{name="$tvar1",current="43970026"@}], + memory=[@{address="0x0000000000602264",length="4"@}, + @{address="0x0000000000615bc0",length="4"@}] +(gdb) +@end smallexample + +Where: + +@table @code +@item explicit-variables +The set of objects that have been explicitly wholly collected at the +current trace frame. For each object, its name and value are printed. +The @code{--var-print-values} option affects how or whether the value +field is output. If @var{var_pval} is 0, then print only the names; +if it is 1, print also their values; and if it is 2, print the name, +type and value for simple data types, and the name and type for +arrays, structures and unions. + +@item computed-expressions +The set of computed expressions that have been collected at the +current trace frame. The @code{--comp-print-values} option affects +this set like the @code{--var-print-values} option affects the +@code{explicit-variables} set. See above. + +@item registers +The registers that have been collected at the current trace frame. +For each register collected, the name and current value are returned. +The value is formatted according to the @code{--registers-format} +option. See the @command{-data-list-register-values} command for a +list of the allowed formats. The default is @samp{x}. + +@item tvars +The trace state variables that have been collected at the current +trace frame. For each trace state variable collected, the name and +current value are returned. + +@item memory +The set of memory ranges that have been collected at the current trace +frame. Its content is a list of tuples. Each tuple represents a +collected memory range and has the following fields: + +@table @code +@item address +The start address of the memory range, as hexadecimal literal. + +@item length +The length of the memory range, as decimal literal. + +@item contents +The contents of the memory block, in hex. This field is only present +if the @code{--memory-contents} options is specified. + +@end table + +@end table + +@subsubheading @value{GDBN} Command + +There is no corresponding @value{GDBN} command. + +@subsubheading Example + @subheading -trace-list-variables @findex -trace-list-variables diff --git a/gdb/mi/mi-cmds.c b/gdb/mi/mi-cmds.c index eb67abe..0768b2a 100644 --- a/gdb/mi/mi-cmds.c +++ b/gdb/mi/mi-cmds.c @@ -148,6 +148,8 @@ static struct mi_cmd mi_cmds[] = DEF_MI_CMD_MI ("trace-define-variable", mi_cmd_trace_define_variable), DEF_MI_CMD_MI_1 ("trace-find", mi_cmd_trace_find, &mi_suppress_notification.traceframe), + DEF_MI_CMD_MI ("trace-frame-collected", + mi_cmd_trace_frame_collected), DEF_MI_CMD_MI ("trace-list-variables", mi_cmd_trace_list_variables), DEF_MI_CMD_MI ("trace-save", mi_cmd_trace_save), DEF_MI_CMD_MI ("trace-start", mi_cmd_trace_start), diff --git a/gdb/mi/mi-cmds.h b/gdb/mi/mi-cmds.h index 8839319..a472582 100644 --- a/gdb/mi/mi-cmds.h +++ b/gdb/mi/mi-cmds.h @@ -94,6 +94,7 @@ extern mi_cmd_argv_ftype mi_cmd_thread_list_ids; extern mi_cmd_argv_ftype mi_cmd_thread_select; extern mi_cmd_argv_ftype mi_cmd_trace_define_variable; extern mi_cmd_argv_ftype mi_cmd_trace_find; +extern mi_cmd_argv_ftype mi_cmd_trace_frame_collected; extern mi_cmd_argv_ftype mi_cmd_trace_list_variables; extern mi_cmd_argv_ftype mi_cmd_trace_save; extern mi_cmd_argv_ftype mi_cmd_trace_start; diff --git a/gdb/mi/mi-main.c b/gdb/mi/mi-main.c index 430d530..0b8740da 100644 --- a/gdb/mi/mi-main.c +++ b/gdb/mi/mi-main.c @@ -2585,3 +2585,300 @@ mi_cmd_ada_task_info (char *command, char **argv, int argc) print_ada_task_info (current_uiout, argv[0], current_inferior ()); } + +/* Print EXPRESSION according to VALUES. */ + +static void +print_variable_or_computed (char *expression, enum print_values values) +{ + struct expression *expr; + struct cleanup *old_chain; + struct value *val; + struct ui_file *stb; + struct value_print_options opts; + struct type *type; + struct ui_out *uiout = current_uiout; + + stb = mem_fileopen (); + old_chain = make_cleanup_ui_file_delete (stb); + + expr = parse_expression (expression); + + make_cleanup (free_current_contents, &expr); + + if (values == PRINT_SIMPLE_VALUES) + val = evaluate_type (expr); + else + val = evaluate_expression (expr); + + if (values != PRINT_NO_VALUES) + make_cleanup_ui_out_tuple_begin_end (uiout, NULL); + ui_out_field_string (uiout, "name", expression); + + switch (values) + { + case PRINT_SIMPLE_VALUES: + type = check_typedef (value_type (val)); + type_print (value_type (val), "", stb, -1); + ui_out_field_stream (uiout, "type", stb); + if (TYPE_CODE (type) != TYPE_CODE_ARRAY + && TYPE_CODE (type) != TYPE_CODE_STRUCT + && TYPE_CODE (type) != TYPE_CODE_UNION) + { + struct value_print_options opts; + + get_raw_print_options (&opts); + opts.deref_ref = 1; + common_val_print (val, stb, 0, &opts, current_language); + ui_out_field_stream (uiout, "value", stb); + } + break; + case PRINT_ALL_VALUES: + { + struct value_print_options opts; + + get_raw_print_options (&opts); + opts.deref_ref = 1; + common_val_print (val, stb, 0, &opts, current_language); + ui_out_field_stream (uiout, "value", stb); + } + break; + } + + do_cleanups (old_chain); +} + +/* Implement the "-trace-frame-collected" command. */ + +void +mi_cmd_trace_frame_collected (char *command, char **argv, int argc) +{ + struct cleanup *old_chain; + struct bp_location *tloc; + int stepping_frame; + struct collection_list *clist; + struct traceframe_info *tinfo; + int oind = 0; + int var_print_values = PRINT_ALL_VALUES; + int comp_print_values = PRINT_ALL_VALUES; + int registers_format = 'x'; + int memory_contents = 0; + struct ui_out *uiout = current_uiout; + enum opt + { + VAR_PRINT_VALUES, + COMP_PRINT_VALUES, + REGISTERS_FORMAT, + MEMORY_CONTENTS, + }; + static const struct mi_opt opts[] = + { + {"-var-print-values", VAR_PRINT_VALUES, 1}, + {"-comp-print-values", COMP_PRINT_VALUES, 1}, + {"-registers-format", REGISTERS_FORMAT, 1}, + {"-memory-contents", MEMORY_CONTENTS, 0}, + { 0, 0, 0 } + }; + + while (1) + { + char *oarg; + int opt = mi_getopt ("-trace-frame-collected", argc, argv, opts, + &oind, &oarg); + if (opt < 0) + break; + switch ((enum opt) opt) + { + case VAR_PRINT_VALUES: + var_print_values = mi_parse_print_values (oarg); + break; + case COMP_PRINT_VALUES: + comp_print_values = mi_parse_print_values (oarg); + break; + case REGISTERS_FORMAT: + registers_format = oarg[0]; + case MEMORY_CONTENTS: + memory_contents = 1; + break; + } + } + + if (oind != argc) + error (_("Usage: -trace-frame-collected " + "[--var-print-values PRINT_VALUES] " + "[--comp-print-values PRINT_VALUES] " + "[--registers-format FORMAT]" + "[--memory-contents]")); + + /* This throws an error is not inspecting a trace frame. */ + tloc = get_traceframe_location (&stepping_frame); + + /* This command only makes sense for the current frame, not the + selected frame. */ + old_chain = make_cleanup_restore_current_thread (); + select_frame (get_current_frame ()); + + { + struct collection_list tracepoint_list, stepping_list; + + encode_actions (tloc, &tracepoint_list, &stepping_list); + + if (stepping_frame) + clist = &stepping_list; + else + clist = &tracepoint_list; + } + + tinfo = get_traceframe_info (); + + /* Explicitly wholly collected variables. */ + { + struct cleanup *list_cleanup; + char *p; + int i; + + list_cleanup = make_cleanup_ui_out_list_begin_end (uiout, + "explicit-variables"); + for (i = 0; VEC_iterate (char_ptr, clist->wholly_collected, i, p); i++) + print_variable_or_computed (p, var_print_values); + do_cleanups (list_cleanup); + } + + /* Computed expressions. */ + { + struct cleanup *list_cleanup; + char *p; + int i; + + list_cleanup + = make_cleanup_ui_out_list_begin_end (uiout, + "computed-expressions"); + for (i = 0; VEC_iterate (char_ptr, clist->computed, i, p); i++) + print_variable_or_computed (p, comp_print_values); + do_cleanups (list_cleanup); + } + + /* Registers. Given pseudo-registers, and that some architectures + (like MIPS) actually hide the raw registers, we don't go through + the trace frame info, but instead consult the register cache for + register availability. */ + { + struct cleanup *list_cleanup; + struct frame_info *frame; + struct gdbarch *gdbarch; + int regnum; + int numregs; + + list_cleanup = make_cleanup_ui_out_list_begin_end (uiout, "registers"); + + frame = get_selected_frame (NULL); + gdbarch = get_frame_arch (frame); + numregs = gdbarch_num_regs (gdbarch) + gdbarch_num_pseudo_regs (gdbarch); + + for (regnum = 0; regnum < numregs; regnum++) + { + if (gdbarch_register_name (gdbarch, regnum) == NULL + || *(gdbarch_register_name (gdbarch, regnum)) == '\0') + continue; + + output_register (frame, regnum, registers_format, 1); + } + + do_cleanups (list_cleanup); + } + + /* Trace state variables. */ + { + struct cleanup *list_cleanup; + int tvar; + char *tsvname; + int i; + + list_cleanup = make_cleanup_ui_out_list_begin_end (uiout, "tvars"); + + tsvname = NULL; + make_cleanup (free_current_contents, &tsvname); + + for (i = 0; VEC_iterate (int, tinfo->tvars, i, tvar); i++) + { + struct cleanup *cleanup_child; + struct trace_state_variable *tsv; + + tsv = find_trace_state_variable_by_number (tvar); + + cleanup_child = make_cleanup_ui_out_tuple_begin_end (uiout, NULL); + + if (tsv != NULL) + { + tsvname = xrealloc (tsvname, strlen (tsv->name) + 2); + tsvname[0] = '$'; + strcpy (tsvname + 1, tsv->name); + ui_out_field_string (uiout, "name", tsvname); + + tsv->value_known = target_get_trace_state_variable_value (tsv->number, + &tsv->value); + ui_out_field_int (uiout, "current", tsv->value); + } + else + { + ui_out_field_skip (uiout, "name"); + ui_out_field_skip (uiout, "current"); + } + + do_cleanups (cleanup_child); + } + + do_cleanups (list_cleanup); + } + + /* Memory. */ + { + struct cleanup *list_cleanup; + VEC(mem_range_s) *available_memory = NULL; + struct mem_range *r; + int i; + + traceframe_available_memory (&available_memory, 0, ULONGEST_MAX); + make_cleanup (VEC_cleanup(mem_range_s), &available_memory); + + list_cleanup = make_cleanup_ui_out_list_begin_end (uiout, "memory"); + + for (i = 0; VEC_iterate (mem_range_s, available_memory, i, r); i++) + { + struct cleanup *cleanup_child; + gdb_byte *data; + struct gdbarch *gdbarch = target_gdbarch (); + + cleanup_child = make_cleanup_ui_out_tuple_begin_end (uiout, NULL); + + ui_out_field_core_addr (uiout, "address", gdbarch, r->start); + ui_out_field_int (uiout, "length", r->length); + + data = xmalloc (r->length); + make_cleanup (xfree, data); + + if (memory_contents) + { + if (target_read_memory (r->start, data, r->length) == 0) + { + int m; + char *data_str, *p; + + data_str = xmalloc (r->length * 2 + 1); + make_cleanup (xfree, data_str); + + for (m = 0, p = data_str; m < r->length; ++m, p += 2) + sprintf (p, "%02x", data[m]); + ui_out_field_string (uiout, "contents", data_str); + } + else + ui_out_field_skip (uiout, "contents"); + } + do_cleanups (cleanup_child); + } + + do_cleanups (list_cleanup); + } + + do_cleanups (old_chain); +} diff --git a/gdb/remote.c b/gdb/remote.c index 080d048..d06b1ed 100644 --- a/gdb/remote.c +++ b/gdb/remote.c @@ -10524,7 +10524,7 @@ remote_download_tracepoint (struct bp_location *loc) struct breakpoint *b = loc->owner; struct tracepoint *t = (struct tracepoint *) b; - encode_actions (loc, &tdp_actions, &stepping_actions); + encode_actions_rsp (loc, &tdp_actions, &stepping_actions); old_chain = make_cleanup (free_actions_list_cleanup_wrapper, tdp_actions); (void) make_cleanup (free_actions_list_cleanup_wrapper, diff --git a/gdb/tracepoint.c b/gdb/tracepoint.c index d7d0e88..4f10c93 100644 --- a/gdb/tracepoint.c +++ b/gdb/tracepoint.c @@ -340,6 +340,22 @@ find_trace_state_variable (const char *name) return NULL; } +/* Return the tsv if its number is NUMBER. Return NULL if not + found. */ + +struct trace_state_variable * +find_trace_state_variable_by_number (int number) +{ + struct trace_state_variable *tsv; + int ix; + + for (ix = 0; VEC_iterate (tsv_s, tvariables, ix, tsv); ++ix) + if (tsv->number == number) + return tsv; + + return NULL; +} + static void delete_trace_state_variable (const char *name) { @@ -853,29 +869,6 @@ enum { memrange_absolute = -1 }; -struct memrange -{ - int type; /* memrange_absolute for absolute memory range, - else basereg number. */ - bfd_signed_vma start; - bfd_signed_vma end; -}; - -struct collection_list - { - unsigned char regs_mask[32]; /* room for up to 256 regs */ - long listsize; - long next_memrange; - struct memrange *list; - long aexpr_listsize; /* size of array pointed to by expr_list elt */ - long next_aexpr_elt; - struct agent_expr **aexpr_list; - - /* True is the user requested a collection of "$_sdata", "static - tracepoint data". */ - int strace_data; - }; - /* MEMRANGE functions: */ static int memrange_cmp (const void *, const void *); @@ -1166,6 +1159,9 @@ do_collect_symbol (const char *print_name, collect_symbol (p->collect, 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)); } /* Add all locals (or args) symbols to collection list. */ @@ -1242,6 +1238,9 @@ clear_collection_list (struct collection_list *list) 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. */ @@ -1392,6 +1391,21 @@ stringify_collection_list (struct collection_list *list) return *str_list; } +/* Add the printed expression EXP to *LIST. */ + +static void +append_exp (struct expression *exp, VEC(char_ptr) **list) +{ + 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); + ui_file_delete (tmp_stream); +} static void encode_actions_1 (struct command_line *action, @@ -1537,16 +1551,25 @@ encode_actions_1 (struct command_line *action, check_typedef (exp->elts[1].type); add_memrange (collect, memrange_absolute, addr, TYPE_LENGTH (exp->elts[1].type)); + append_exp (exp, &collect->computed); break; case OP_VAR_VALUE: - collect_symbol (collect, - exp->elts[2].symbol, - tloc->gdbarch, - frame_reg, - frame_offset, - tloc->address, - trace_string); + { + 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); + } break; default: /* Full-fledged expression. */ @@ -1582,6 +1605,8 @@ encode_actions_1 (struct command_line *action, } } } + + append_exp (exp, &collect->computed); break; } /* switch */ do_cleanups (old_chain); @@ -1635,46 +1660,63 @@ encode_actions_1 (struct command_line *action, } /* for */ } -/* Render all actions into gdb protocol. */ +/* 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. */ -void -encode_actions (struct bp_location *tloc, char ***tdp_actions, - char ***stepping_actions) +struct cleanup * +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; - struct collection_list tracepoint_list, stepping_list; - - back_to = make_cleanup (null_cleanup, NULL); + struct cleanup *back_to, *return_chain; - init_collection_list (&tracepoint_list); - init_collection_list (&stepping_list); + 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); - - *tdp_actions = NULL; - *stepping_actions = NULL; + 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); actions = all_tracepoint_actions_and_cleanup (tloc->owner); encode_actions_1 (actions, tloc, frame_reg, frame_offset, - &tracepoint_list, &stepping_list); + tracepoint_list, stepping_list); - memrange_sortmerge (&tracepoint_list); - memrange_sortmerge (&stepping_list); + memrange_sortmerge (tracepoint_list); + memrange_sortmerge (stepping_list); + + do_cleanups (back_to); + return return_chain; +} + +/* Render all actions into gdb protocol. */ + +void +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 (tloc, &tracepoint_list, &stepping_list); *tdp_actions = stringify_collection_list (&tracepoint_list); *stepping_actions = stringify_collection_list (&stepping_list); - do_cleanups (back_to); + do_cleanups (cleanup); } static void @@ -2938,7 +2980,7 @@ trace_dump_actions (struct command_line *action, traceframe. Set *STEPPING_FRAME_P to 1 if the current traceframe is the stepping traceframe. */ -static struct bp_location * +struct bp_location * get_traceframe_location (int *stepping_frame_p) { struct tracepoint *t; @@ -5673,7 +5715,7 @@ parse_traceframe_info (const char *tframe_info) This is where we avoid re-fetching the object from the target if we already have it cached. */ -static struct traceframe_info * +struct traceframe_info * get_traceframe_info (void) { if (traceframe_info == NULL) diff --git a/gdb/tracepoint.h b/gdb/tracepoint.h index 350ab5e..e79ba3a 100644 --- a/gdb/tracepoint.h +++ b/gdb/tracepoint.h @@ -323,6 +323,38 @@ struct trace_file_writer const struct trace_file_write_ops *ops; }; +struct memrange +{ + /* memrange_absolute for absolute memory range, else basereg + number. */ + int type; + bfd_signed_vma start; + bfd_signed_vma end; +}; + +struct collection_list +{ + /* room for up to 256 regs */ + unsigned char regs_mask[32]; + long listsize; + long next_memrange; + struct memrange *list; + + /* size of array pointed to by expr_list elt. */ + long aexpr_listsize; + long next_aexpr_elt; + struct agent_expr **aexpr_list; + + /* True is the user requested a collection of "$_sdata", "static + tracepoint data". */ + int strace_data; + + /* A set of names of wholly collected objects. */ + VEC(char_ptr) *wholly_collected; + /* A set of computed expressions. */ + VEC(char_ptr) *computed; +}; + extern void parse_static_tracepoint_marker_definition (char *line, char **pp, struct static_tracepoint_marker *marker); @@ -360,13 +392,20 @@ void free_actions (struct breakpoint *); extern const char *decode_agent_options (const char *exp, int *trace_string); -extern void encode_actions (struct bp_location *tloc, - char ***tdp_actions, char ***stepping_actions); +extern struct cleanup *encode_actions (struct bp_location *tloc, + struct collection_list *tracepoint_list, + struct collection_list *stepping_list); + +extern void encode_actions_rsp (struct bp_location *tloc, + char ***tdp_actions, char ***stepping_actions); extern void validate_actionline (const char *, struct breakpoint *); extern void validate_trace_state_variable_name (const char *name); extern struct trace_state_variable *find_trace_state_variable (const char *name); +extern struct trace_state_variable * + find_trace_state_variable_by_number (int number); + extern struct trace_state_variable *create_trace_state_variable (const char *name); extern int encode_source_string (int num, ULONGEST addr, @@ -416,4 +455,8 @@ extern struct traceframe_info *parse_traceframe_info (const char *tframe_info); extern int traceframe_available_memory (VEC(mem_range_s) **result, CORE_ADDR memaddr, ULONGEST len); +extern struct traceframe_info *get_traceframe_info (void); + +extern struct bp_location *get_traceframe_location (int *stepping_frame_p); + #endif /* TRACEPOINT_H */ -- 1.7.7.6 ^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PATCH 5/6] New MI command -trace-frame-collected 2013-06-17 10:21 ` Yao Qi @ 2013-06-17 15:48 ` Eli Zaretskii 2013-06-18 14:09 ` Yao Qi 0 siblings, 1 reply; 36+ messages in thread From: Eli Zaretskii @ 2013-06-17 15:48 UTC (permalink / raw) To: Yao Qi; +Cc: gdb-patches > Date: Mon, 17 Jun 2013 18:12:09 +0800 > From: Yao Qi <yao@codesourcery.com> > CC: <gdb-patches@sourceware.org> > > On 06/14/2013 06:41 PM, Eli Zaretskii wrote: > > This is not described anywhere in the manual. In fact, the word > > "wholly" never appears in the manual and "whole" never appears in any > > context related to tracepoints. In the node "Tracepoint Actions", we > > don't make any distinction between collecting "in whole" and "in > > part". > > > > So if this distinction is important, please add to "Tracepoint > > Actions" the explanation similar to what you wrote above, and then > > make a cross-reference to that from the description of > > -trace-frame-collected. > > This distinction is important to the commands displaying contents in > a given traceframe, such as -trace-frame-collected, but this distinction > is not important to trace actions. How can it not be important, when (AFAIU) the collection commands are those that determine whether an object is collected in whole or only partially? By the time the user gets to displaying the collected data, it's too late to decide about that. Or am I missing something? If I'm right, then it is important to describe this with tracepoint actions because that is where the user needs to decide what to collect and how. On second thought, I still don't understand why is it so important to emphasize this issue. Isn't it trivially clear that in your example myVar is collected in its entirety, while for myArray, only its myIndex'th element is collected, and that the rest are expressions? Why do we need to explain that? Isn't it enough to say @item explicit-variables The set of objects that have been collected in their entirety (as opposed to collecting just a few elements of an array or a few struct members). If this is good enough, then this paragraph: > +This command returns the set of explicitly wholly collected (explained > +below with an example) objects, register names, trace state variable > +names, memory ranges and computed expressions that have been collected > +at a particular trace frame. The optional parameters to the command > +affect the output format in different ways. See the output description > +table below for more details. Needs to be rephrased to not mention the "explicitly wholly" thing. > What do you think? I don't like the result, sorry. First, "explicitly wholly" sounds awkward, so much so that the reader might decide this is a mistake of some kind. Please use "collected wholly" or "explicitly collected as a whole", if I didn't convince you that the entire point about this is moot. Second, this issue is too complicated to explain it with an example. You need to provide rules by which the user will be able to decide whether some data will be collected as a whole or not. Third, you need @noindent here: > +@smallexample > +collect myVar, myArray[myIndex] myObj.field, myPtr->field, myCount + 2 > +collect *(int*)0xaf02bef0@@40 > +@end smallexample > +the set of named objects explicitly wholly collected would be after the "@end smallexample" line. Thanks. ^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PATCH 5/6] New MI command -trace-frame-collected 2013-06-17 15:48 ` Eli Zaretskii @ 2013-06-18 14:09 ` Yao Qi 2013-06-18 17:24 ` Eli Zaretskii 2013-06-25 17:31 ` Pedro Alves 0 siblings, 2 replies; 36+ messages in thread From: Yao Qi @ 2013-06-18 14:09 UTC (permalink / raw) To: Eli Zaretskii; +Cc: gdb-patches On 06/17/2013 11:31 PM, Eli Zaretskii wrote: > How can it not be important, when (AFAIU) the collection commands are > those that determine whether an object is collected in whole or only > partially? By the time the user gets to displaying the collected > data, it's too late to decide about that. Or am I missing something? > > If I'm right, then it is important to describe this with tracepoint > actions because that is where the user needs to decide what to collect > and how. > > On second thought, I still don't understand why is it so important to > emphasize this issue. Isn't it trivially clear that in your example > myVar is collected in its entirety, while for myArray, only its > myIndex'th element is collected, and that the rest are expressions? Right. > Why do we need to explain that? Isn't it enough to say > > @item explicit-variables > The set of objects that have been collected in their entirety (as > opposed to collecting just a few elements of an array or a few struct > members). > It is simple to enough to explain "explicit-variables". > If this is good enough, then this paragraph: > >> >+This command returns the set of explicitly wholly collected (explained >> >+below with an example) objects, register names, trace state variable >> >+names, memory ranges and computed expressions that have been collected >> >+at a particular trace frame. The optional parameters to the command >> >+affect the output format in different ways. See the output description >> >+table below for more details. > Needs to be rephrased to not mention the "explicitly wholly" thing. > Agreed. I removed "explicitly wholly" thing. >> >What do you think? > I don't like the result, sorry. > > First, "explicitly wholly" sounds awkward, so much so that the reader > might decide this is a mistake of some kind. Please use "collected > wholly" or "explicitly collected as a whole", if I didn't convince you > that the entire point about this is moot. > > Second, this issue is too complicated to explain it with an example. > You need to provide rules by which the user will be able to decide > whether some data will be collected as a whole or not. > As "explicitly wholly" is removed from the patch, we don't need complicated explanation. So rules are not added. > Third, you need @noindent here: > >> >+@smallexample >> >+collect myVar, myArray[myIndex] myObj.field, myPtr->field, myCount + 2 >> >+collect *(int*)0xaf02bef0@@40 >> >+@end smallexample >> >+the set of named objects explicitly wholly collected would be > after the "@end smallexample" line. Fixed. -- Yao (é½å°§) gdb/doc: 2013-06-17 Pedro Alves <pedro@codesourcery.com> Yao Qi <yao@codesourcery.com> * gdb.texinfo (GDB/MI Tracepoint Commands): Document -trace-frame-collected. gdb: 2013-06-17 Pedro Alves <pedro@codesourcery.com> Yao Qi <yao@codesourcery.com> * mi/mi-cmds.c (mi_cmds): Register -trace-frame-collected. * mi/mi-cmds.h (mi_cmd_trace_frame_collected): Declare. * mi/mi-main.c (print_variable_or_computed): New function. (mi_cmd_trace_frame_collected): New function. * tracepoint.c (find_trace_state_variable_by_number): New. (struct traceframe_info): Move to tracepoint.h (struct collection_list): Likewise. (do_collect_symbol): Include locals and arguments in the wholly collected variables list. (clear_collection_list): Clear wholly collected variables list and computed variables list. (append_exp): New function. (encode_actions_1): Include variables in the wholly collected variables list. Include memory ranges and full-fledged expressions in the computed expressions list. (encode_actions): Move some code to ... Return the cleanup chain. (encode_actions_rsp): ... here. New function. (get_traceframe_location, get_traceframe_info): Remove static. * tracepoint.h (struct memrange): Moved from tracepoint.c. (struct collection_list): Moved from tracepoint.c. Add two new fields 'wholly_collected' and 'computed'. (find_trace_state_variable_by_number): Declare. (encode_actions): Adjust declaration. (encode_actions_rsp): Declare. (get_traceframe_info, get_traceframe_location): Declare. * NEWS: Mention new MI command -trace-frame-collected. --- gdb/NEWS | 3 + gdb/doc/gdb.texinfo | 117 ++++++++++++++++++++ gdb/mi/mi-cmds.c | 2 + gdb/mi/mi-cmds.h | 1 + gdb/mi/mi-main.c | 297 +++++++++++++++++++++++++++++++++++++++++++++++++++ gdb/remote.c | 2 +- gdb/tracepoint.c | 144 ++++++++++++++++--------- gdb/tracepoint.h | 47 ++++++++- 8 files changed, 559 insertions(+), 54 deletions(-) diff --git a/gdb/NEWS b/gdb/NEWS index 2c66db7..3d5c876 100644 --- a/gdb/NEWS +++ b/gdb/NEWS @@ -80,6 +80,9 @@ show range-stepping "--skip-unavailable" option. When used, only the available registers are displayed. + ** The new command -trace-frame-collected dumps collected variables, + computed expressions, tvars, memory and registers in a traceframe. + * New system-wide configuration scripts A GDB installation now provides scripts suitable for use as system-wide configuration scripts for the following systems: diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo index 3992704..8de1c2f 100644 --- a/gdb/doc/gdb.texinfo +++ b/gdb/doc/gdb.texinfo @@ -33161,6 +33161,123 @@ with the @samp{$} character. The corresponding @value{GDBN} command is @samp{tvariable}. +@subheading The @code{-trace-frame-collected} Command +@findex -trace-frame-collected + +@subsubheading Synopsis + +@smallexample + -trace-frame-collected + [--var-print-values @var{var_pval}] + [--comp-print-values @var{comp_pval}] + [--registers-format @var{regformat}] + [--memory-contents] +@end smallexample + +This command returns the set of collected objects, register names, +trace state variable names, memory ranges and computed expressions +that have been collected at a particular trace frame. The optional +parameters to the command affect the output format in different ways. +See the output description table below for more details. + +The reported names can be used in the normal manner to create +varobjs and inspect the objects themselves. The items returned by +this command are categorized so that it is clear which is a variable, +which is a register, which is a trace state variable, which is a +memory range and which is a computed expression. + +For instance, if the actions were +@smallexample +collect myVar, myArray[myIndex], myObj.field, myPtr->field, myCount + 2 +collect *(int*)0xaf02bef0@@40 +@end smallexample + +@noindent +the object collected in its entirety would be @code{myVar}. Object +@code{myArray} is partially collected, because only element on index +@code{myIndex} is collected. The rest of objects are computed +expressions. + +An example output would be: + +@smallexample +(gdb) +-trace-frame-collected +^done, + explicit-variables=[@{name="myVar",value="1"@}], + computed-expressions=[@{name="myArray[myIndex]",value="0"@}, + @{name="myObj.field",value="0"@}, + @{name="myPtr->field",value="1"@}, + @{name="myCount + 2",value="3"@}, + @{name="$tvar1 + 1",value="43970027"@}], + registers=[@{number="0",value="0x7fe2c6e79ec8"@}, + @{number="1",value="0x0"@}, + @{number="2",value="0x4"@}, + ... + @{number="125",value="0x0"@}], + tvars=[@{name="$tvar1",current="43970026"@}], + memory=[@{address="0x0000000000602264",length="4"@}, + @{address="0x0000000000615bc0",length="4"@}] +(gdb) +@end smallexample + +Where: + +@table @code +@item explicit-variables +The set of objects that have been collected in their entirety (as +opposed to collecting just a few elements of an array or a few struct +members). For each object, its name and value are printed. +The @code{--var-print-values} option affects how or whether the value +field is output. If @var{var_pval} is 0, then print only the names; +if it is 1, print also their values; and if it is 2, print the name, +type and value for simple data types, and the name and type for +arrays, structures and unions. + +@item computed-expressions +The set of computed expressions that have been collected at the +current trace frame. The @code{--comp-print-values} option affects +this set like the @code{--var-print-values} option affects the +@code{explicit-variables} set. See above. + +@item registers +The registers that have been collected at the current trace frame. +For each register collected, the name and current value are returned. +The value is formatted according to the @code{--registers-format} +option. See the @command{-data-list-register-values} command for a +list of the allowed formats. The default is @samp{x}. + +@item tvars +The trace state variables that have been collected at the current +trace frame. For each trace state variable collected, the name and +current value are returned. + +@item memory +The set of memory ranges that have been collected at the current trace +frame. Its content is a list of tuples. Each tuple represents a +collected memory range and has the following fields: + +@table @code +@item address +The start address of the memory range, as hexadecimal literal. + +@item length +The length of the memory range, as decimal literal. + +@item contents +The contents of the memory block, in hex. This field is only present +if the @code{--memory-contents} option is specified. + +@end table + +@end table + +@subsubheading @value{GDBN} Command + +There is no corresponding @value{GDBN} command. + +@subsubheading Example + @subheading -trace-list-variables @findex -trace-list-variables diff --git a/gdb/mi/mi-cmds.c b/gdb/mi/mi-cmds.c index eb67abe..0768b2a 100644 --- a/gdb/mi/mi-cmds.c +++ b/gdb/mi/mi-cmds.c @@ -148,6 +148,8 @@ static struct mi_cmd mi_cmds[] = DEF_MI_CMD_MI ("trace-define-variable", mi_cmd_trace_define_variable), DEF_MI_CMD_MI_1 ("trace-find", mi_cmd_trace_find, &mi_suppress_notification.traceframe), + DEF_MI_CMD_MI ("trace-frame-collected", + mi_cmd_trace_frame_collected), DEF_MI_CMD_MI ("trace-list-variables", mi_cmd_trace_list_variables), DEF_MI_CMD_MI ("trace-save", mi_cmd_trace_save), DEF_MI_CMD_MI ("trace-start", mi_cmd_trace_start), diff --git a/gdb/mi/mi-cmds.h b/gdb/mi/mi-cmds.h index 8839319..a472582 100644 --- a/gdb/mi/mi-cmds.h +++ b/gdb/mi/mi-cmds.h @@ -94,6 +94,7 @@ extern mi_cmd_argv_ftype mi_cmd_thread_list_ids; extern mi_cmd_argv_ftype mi_cmd_thread_select; extern mi_cmd_argv_ftype mi_cmd_trace_define_variable; extern mi_cmd_argv_ftype mi_cmd_trace_find; +extern mi_cmd_argv_ftype mi_cmd_trace_frame_collected; extern mi_cmd_argv_ftype mi_cmd_trace_list_variables; extern mi_cmd_argv_ftype mi_cmd_trace_save; extern mi_cmd_argv_ftype mi_cmd_trace_start; diff --git a/gdb/mi/mi-main.c b/gdb/mi/mi-main.c index 430d530..0b8740da 100644 --- a/gdb/mi/mi-main.c +++ b/gdb/mi/mi-main.c @@ -2585,3 +2585,300 @@ mi_cmd_ada_task_info (char *command, char **argv, int argc) print_ada_task_info (current_uiout, argv[0], current_inferior ()); } + +/* Print EXPRESSION according to VALUES. */ + +static void +print_variable_or_computed (char *expression, enum print_values values) +{ + struct expression *expr; + struct cleanup *old_chain; + struct value *val; + struct ui_file *stb; + struct value_print_options opts; + struct type *type; + struct ui_out *uiout = current_uiout; + + stb = mem_fileopen (); + old_chain = make_cleanup_ui_file_delete (stb); + + expr = parse_expression (expression); + + make_cleanup (free_current_contents, &expr); + + if (values == PRINT_SIMPLE_VALUES) + val = evaluate_type (expr); + else + val = evaluate_expression (expr); + + if (values != PRINT_NO_VALUES) + make_cleanup_ui_out_tuple_begin_end (uiout, NULL); + ui_out_field_string (uiout, "name", expression); + + switch (values) + { + case PRINT_SIMPLE_VALUES: + type = check_typedef (value_type (val)); + type_print (value_type (val), "", stb, -1); + ui_out_field_stream (uiout, "type", stb); + if (TYPE_CODE (type) != TYPE_CODE_ARRAY + && TYPE_CODE (type) != TYPE_CODE_STRUCT + && TYPE_CODE (type) != TYPE_CODE_UNION) + { + struct value_print_options opts; + + get_raw_print_options (&opts); + opts.deref_ref = 1; + common_val_print (val, stb, 0, &opts, current_language); + ui_out_field_stream (uiout, "value", stb); + } + break; + case PRINT_ALL_VALUES: + { + struct value_print_options opts; + + get_raw_print_options (&opts); + opts.deref_ref = 1; + common_val_print (val, stb, 0, &opts, current_language); + ui_out_field_stream (uiout, "value", stb); + } + break; + } + + do_cleanups (old_chain); +} + +/* Implement the "-trace-frame-collected" command. */ + +void +mi_cmd_trace_frame_collected (char *command, char **argv, int argc) +{ + struct cleanup *old_chain; + struct bp_location *tloc; + int stepping_frame; + struct collection_list *clist; + struct traceframe_info *tinfo; + int oind = 0; + int var_print_values = PRINT_ALL_VALUES; + int comp_print_values = PRINT_ALL_VALUES; + int registers_format = 'x'; + int memory_contents = 0; + struct ui_out *uiout = current_uiout; + enum opt + { + VAR_PRINT_VALUES, + COMP_PRINT_VALUES, + REGISTERS_FORMAT, + MEMORY_CONTENTS, + }; + static const struct mi_opt opts[] = + { + {"-var-print-values", VAR_PRINT_VALUES, 1}, + {"-comp-print-values", COMP_PRINT_VALUES, 1}, + {"-registers-format", REGISTERS_FORMAT, 1}, + {"-memory-contents", MEMORY_CONTENTS, 0}, + { 0, 0, 0 } + }; + + while (1) + { + char *oarg; + int opt = mi_getopt ("-trace-frame-collected", argc, argv, opts, + &oind, &oarg); + if (opt < 0) + break; + switch ((enum opt) opt) + { + case VAR_PRINT_VALUES: + var_print_values = mi_parse_print_values (oarg); + break; + case COMP_PRINT_VALUES: + comp_print_values = mi_parse_print_values (oarg); + break; + case REGISTERS_FORMAT: + registers_format = oarg[0]; + case MEMORY_CONTENTS: + memory_contents = 1; + break; + } + } + + if (oind != argc) + error (_("Usage: -trace-frame-collected " + "[--var-print-values PRINT_VALUES] " + "[--comp-print-values PRINT_VALUES] " + "[--registers-format FORMAT]" + "[--memory-contents]")); + + /* This throws an error is not inspecting a trace frame. */ + tloc = get_traceframe_location (&stepping_frame); + + /* This command only makes sense for the current frame, not the + selected frame. */ + old_chain = make_cleanup_restore_current_thread (); + select_frame (get_current_frame ()); + + { + struct collection_list tracepoint_list, stepping_list; + + encode_actions (tloc, &tracepoint_list, &stepping_list); + + if (stepping_frame) + clist = &stepping_list; + else + clist = &tracepoint_list; + } + + tinfo = get_traceframe_info (); + + /* Explicitly wholly collected variables. */ + { + struct cleanup *list_cleanup; + char *p; + int i; + + list_cleanup = make_cleanup_ui_out_list_begin_end (uiout, + "explicit-variables"); + for (i = 0; VEC_iterate (char_ptr, clist->wholly_collected, i, p); i++) + print_variable_or_computed (p, var_print_values); + do_cleanups (list_cleanup); + } + + /* Computed expressions. */ + { + struct cleanup *list_cleanup; + char *p; + int i; + + list_cleanup + = make_cleanup_ui_out_list_begin_end (uiout, + "computed-expressions"); + for (i = 0; VEC_iterate (char_ptr, clist->computed, i, p); i++) + print_variable_or_computed (p, comp_print_values); + do_cleanups (list_cleanup); + } + + /* Registers. Given pseudo-registers, and that some architectures + (like MIPS) actually hide the raw registers, we don't go through + the trace frame info, but instead consult the register cache for + register availability. */ + { + struct cleanup *list_cleanup; + struct frame_info *frame; + struct gdbarch *gdbarch; + int regnum; + int numregs; + + list_cleanup = make_cleanup_ui_out_list_begin_end (uiout, "registers"); + + frame = get_selected_frame (NULL); + gdbarch = get_frame_arch (frame); + numregs = gdbarch_num_regs (gdbarch) + gdbarch_num_pseudo_regs (gdbarch); + + for (regnum = 0; regnum < numregs; regnum++) + { + if (gdbarch_register_name (gdbarch, regnum) == NULL + || *(gdbarch_register_name (gdbarch, regnum)) == '\0') + continue; + + output_register (frame, regnum, registers_format, 1); + } + + do_cleanups (list_cleanup); + } + + /* Trace state variables. */ + { + struct cleanup *list_cleanup; + int tvar; + char *tsvname; + int i; + + list_cleanup = make_cleanup_ui_out_list_begin_end (uiout, "tvars"); + + tsvname = NULL; + make_cleanup (free_current_contents, &tsvname); + + for (i = 0; VEC_iterate (int, tinfo->tvars, i, tvar); i++) + { + struct cleanup *cleanup_child; + struct trace_state_variable *tsv; + + tsv = find_trace_state_variable_by_number (tvar); + + cleanup_child = make_cleanup_ui_out_tuple_begin_end (uiout, NULL); + + if (tsv != NULL) + { + tsvname = xrealloc (tsvname, strlen (tsv->name) + 2); + tsvname[0] = '$'; + strcpy (tsvname + 1, tsv->name); + ui_out_field_string (uiout, "name", tsvname); + + tsv->value_known = target_get_trace_state_variable_value (tsv->number, + &tsv->value); + ui_out_field_int (uiout, "current", tsv->value); + } + else + { + ui_out_field_skip (uiout, "name"); + ui_out_field_skip (uiout, "current"); + } + + do_cleanups (cleanup_child); + } + + do_cleanups (list_cleanup); + } + + /* Memory. */ + { + struct cleanup *list_cleanup; + VEC(mem_range_s) *available_memory = NULL; + struct mem_range *r; + int i; + + traceframe_available_memory (&available_memory, 0, ULONGEST_MAX); + make_cleanup (VEC_cleanup(mem_range_s), &available_memory); + + list_cleanup = make_cleanup_ui_out_list_begin_end (uiout, "memory"); + + for (i = 0; VEC_iterate (mem_range_s, available_memory, i, r); i++) + { + struct cleanup *cleanup_child; + gdb_byte *data; + struct gdbarch *gdbarch = target_gdbarch (); + + cleanup_child = make_cleanup_ui_out_tuple_begin_end (uiout, NULL); + + ui_out_field_core_addr (uiout, "address", gdbarch, r->start); + ui_out_field_int (uiout, "length", r->length); + + data = xmalloc (r->length); + make_cleanup (xfree, data); + + if (memory_contents) + { + if (target_read_memory (r->start, data, r->length) == 0) + { + int m; + char *data_str, *p; + + data_str = xmalloc (r->length * 2 + 1); + make_cleanup (xfree, data_str); + + for (m = 0, p = data_str; m < r->length; ++m, p += 2) + sprintf (p, "%02x", data[m]); + ui_out_field_string (uiout, "contents", data_str); + } + else + ui_out_field_skip (uiout, "contents"); + } + do_cleanups (cleanup_child); + } + + do_cleanups (list_cleanup); + } + + do_cleanups (old_chain); +} diff --git a/gdb/remote.c b/gdb/remote.c index 080d048..d06b1ed 100644 --- a/gdb/remote.c +++ b/gdb/remote.c @@ -10524,7 +10524,7 @@ remote_download_tracepoint (struct bp_location *loc) struct breakpoint *b = loc->owner; struct tracepoint *t = (struct tracepoint *) b; - encode_actions (loc, &tdp_actions, &stepping_actions); + encode_actions_rsp (loc, &tdp_actions, &stepping_actions); old_chain = make_cleanup (free_actions_list_cleanup_wrapper, tdp_actions); (void) make_cleanup (free_actions_list_cleanup_wrapper, diff --git a/gdb/tracepoint.c b/gdb/tracepoint.c index d7d0e88..4f10c93 100644 --- a/gdb/tracepoint.c +++ b/gdb/tracepoint.c @@ -340,6 +340,22 @@ find_trace_state_variable (const char *name) return NULL; } +/* Return the tsv if its number is NUMBER. Return NULL if not + found. */ + +struct trace_state_variable * +find_trace_state_variable_by_number (int number) +{ + struct trace_state_variable *tsv; + int ix; + + for (ix = 0; VEC_iterate (tsv_s, tvariables, ix, tsv); ++ix) + if (tsv->number == number) + return tsv; + + return NULL; +} + static void delete_trace_state_variable (const char *name) { @@ -853,29 +869,6 @@ enum { memrange_absolute = -1 }; -struct memrange -{ - int type; /* memrange_absolute for absolute memory range, - else basereg number. */ - bfd_signed_vma start; - bfd_signed_vma end; -}; - -struct collection_list - { - unsigned char regs_mask[32]; /* room for up to 256 regs */ - long listsize; - long next_memrange; - struct memrange *list; - long aexpr_listsize; /* size of array pointed to by expr_list elt */ - long next_aexpr_elt; - struct agent_expr **aexpr_list; - - /* True is the user requested a collection of "$_sdata", "static - tracepoint data". */ - int strace_data; - }; - /* MEMRANGE functions: */ static int memrange_cmp (const void *, const void *); @@ -1166,6 +1159,9 @@ do_collect_symbol (const char *print_name, collect_symbol (p->collect, 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)); } /* Add all locals (or args) symbols to collection list. */ @@ -1242,6 +1238,9 @@ clear_collection_list (struct collection_list *list) 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. */ @@ -1392,6 +1391,21 @@ stringify_collection_list (struct collection_list *list) return *str_list; } +/* Add the printed expression EXP to *LIST. */ + +static void +append_exp (struct expression *exp, VEC(char_ptr) **list) +{ + 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); + ui_file_delete (tmp_stream); +} static void encode_actions_1 (struct command_line *action, @@ -1537,16 +1551,25 @@ encode_actions_1 (struct command_line *action, check_typedef (exp->elts[1].type); add_memrange (collect, memrange_absolute, addr, TYPE_LENGTH (exp->elts[1].type)); + append_exp (exp, &collect->computed); break; case OP_VAR_VALUE: - collect_symbol (collect, - exp->elts[2].symbol, - tloc->gdbarch, - frame_reg, - frame_offset, - tloc->address, - trace_string); + { + 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); + } break; default: /* Full-fledged expression. */ @@ -1582,6 +1605,8 @@ encode_actions_1 (struct command_line *action, } } } + + append_exp (exp, &collect->computed); break; } /* switch */ do_cleanups (old_chain); @@ -1635,46 +1660,63 @@ encode_actions_1 (struct command_line *action, } /* for */ } -/* Render all actions into gdb protocol. */ +/* 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. */ -void -encode_actions (struct bp_location *tloc, char ***tdp_actions, - char ***stepping_actions) +struct cleanup * +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; - struct collection_list tracepoint_list, stepping_list; - - back_to = make_cleanup (null_cleanup, NULL); + struct cleanup *back_to, *return_chain; - init_collection_list (&tracepoint_list); - init_collection_list (&stepping_list); + 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); - - *tdp_actions = NULL; - *stepping_actions = NULL; + 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); actions = all_tracepoint_actions_and_cleanup (tloc->owner); encode_actions_1 (actions, tloc, frame_reg, frame_offset, - &tracepoint_list, &stepping_list); + tracepoint_list, stepping_list); - memrange_sortmerge (&tracepoint_list); - memrange_sortmerge (&stepping_list); + memrange_sortmerge (tracepoint_list); + memrange_sortmerge (stepping_list); + + do_cleanups (back_to); + return return_chain; +} + +/* Render all actions into gdb protocol. */ + +void +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 (tloc, &tracepoint_list, &stepping_list); *tdp_actions = stringify_collection_list (&tracepoint_list); *stepping_actions = stringify_collection_list (&stepping_list); - do_cleanups (back_to); + do_cleanups (cleanup); } static void @@ -2938,7 +2980,7 @@ trace_dump_actions (struct command_line *action, traceframe. Set *STEPPING_FRAME_P to 1 if the current traceframe is the stepping traceframe. */ -static struct bp_location * +struct bp_location * get_traceframe_location (int *stepping_frame_p) { struct tracepoint *t; @@ -5673,7 +5715,7 @@ parse_traceframe_info (const char *tframe_info) This is where we avoid re-fetching the object from the target if we already have it cached. */ -static struct traceframe_info * +struct traceframe_info * get_traceframe_info (void) { if (traceframe_info == NULL) diff --git a/gdb/tracepoint.h b/gdb/tracepoint.h index 350ab5e..e79ba3a 100644 --- a/gdb/tracepoint.h +++ b/gdb/tracepoint.h @@ -323,6 +323,38 @@ struct trace_file_writer const struct trace_file_write_ops *ops; }; +struct memrange +{ + /* memrange_absolute for absolute memory range, else basereg + number. */ + int type; + bfd_signed_vma start; + bfd_signed_vma end; +}; + +struct collection_list +{ + /* room for up to 256 regs */ + unsigned char regs_mask[32]; + long listsize; + long next_memrange; + struct memrange *list; + + /* size of array pointed to by expr_list elt. */ + long aexpr_listsize; + long next_aexpr_elt; + struct agent_expr **aexpr_list; + + /* True is the user requested a collection of "$_sdata", "static + tracepoint data". */ + int strace_data; + + /* A set of names of wholly collected objects. */ + VEC(char_ptr) *wholly_collected; + /* A set of computed expressions. */ + VEC(char_ptr) *computed; +}; + extern void parse_static_tracepoint_marker_definition (char *line, char **pp, struct static_tracepoint_marker *marker); @@ -360,13 +392,20 @@ void free_actions (struct breakpoint *); extern const char *decode_agent_options (const char *exp, int *trace_string); -extern void encode_actions (struct bp_location *tloc, - char ***tdp_actions, char ***stepping_actions); +extern struct cleanup *encode_actions (struct bp_location *tloc, + struct collection_list *tracepoint_list, + struct collection_list *stepping_list); + +extern void encode_actions_rsp (struct bp_location *tloc, + char ***tdp_actions, char ***stepping_actions); extern void validate_actionline (const char *, struct breakpoint *); extern void validate_trace_state_variable_name (const char *name); extern struct trace_state_variable *find_trace_state_variable (const char *name); +extern struct trace_state_variable * + find_trace_state_variable_by_number (int number); + extern struct trace_state_variable *create_trace_state_variable (const char *name); extern int encode_source_string (int num, ULONGEST addr, @@ -416,4 +455,8 @@ extern struct traceframe_info *parse_traceframe_info (const char *tframe_info); extern int traceframe_available_memory (VEC(mem_range_s) **result, CORE_ADDR memaddr, ULONGEST len); +extern struct traceframe_info *get_traceframe_info (void); + +extern struct bp_location *get_traceframe_location (int *stepping_frame_p); + #endif /* TRACEPOINT_H */ -- 1.7.7.6 ^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PATCH 5/6] New MI command -trace-frame-collected 2013-06-18 14:09 ` Yao Qi @ 2013-06-18 17:24 ` Eli Zaretskii 2013-06-25 17:31 ` Pedro Alves 1 sibling, 0 replies; 36+ messages in thread From: Eli Zaretskii @ 2013-06-18 17:24 UTC (permalink / raw) To: Yao Qi; +Cc: gdb-patches > Date: Tue, 18 Jun 2013 22:06:50 +0800 > From: Yao Qi <yao@codesourcery.com> > CC: <gdb-patches@sourceware.org> > > gdb/doc: > > 2013-06-17 Pedro Alves <pedro@codesourcery.com> > Yao Qi <yao@codesourcery.com> > > * gdb.texinfo (GDB/MI Tracepoint Commands): Document > -trace-frame-collected. Thanks, this version is fine. ^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PATCH 5/6] New MI command -trace-frame-collected 2013-06-18 14:09 ` Yao Qi 2013-06-18 17:24 ` Eli Zaretskii @ 2013-06-25 17:31 ` Pedro Alves 2013-06-26 8:29 ` Yao Qi 1 sibling, 1 reply; 36+ messages in thread From: Pedro Alves @ 2013-06-25 17:31 UTC (permalink / raw) To: Yao Qi; +Cc: Eli Zaretskii, gdb-patches On 06/18/2013 03:06 PM, Yao Qi wrote: > + > +This command returns the set of collected objects, register names, > +trace state variable names, memory ranges and computed expressions > +that have been collected at a particular trace frame. The optional > +parameters to the command affect the output format in different ways. > +See the output description table below for more details. > + > +The reported names can be used in the normal manner to create > +varobjs and inspect the objects themselves. The items returned by > +this command are categorized so that it is clear which is a variable, > +which is a register, which is a trace state variable, which is a > +memory range and which is a computed expression. > + > +For instance, if the actions were > +@smallexample > +collect myVar, myArray[myIndex], myObj.field, myPtr->field, myCount + 2 > +collect *(int*)0xaf02bef0@@40 > +@end smallexample > + > +@noindent > +the object collected in its entirety would be @code{myVar}. Object > +@code{myArray} is partially collected, because only element on index > +@code{myIndex} is collected. The rest of objects are computed > +expressions. #1 "If the actions were ... then foo would be." sounds right. #2 "If the actions are ... then foo is." would sound right. #3 "If the actions were ... then foo is." sounds odd. s/Object/The object/ "only the element at index" "rest of the objects", or "the remaining objects" That is, I suggest: For instance, if the actions were @smallexample collect myVar, myArray[myIndex], myObj.field, myPtr->field, myCount + 2 collect *(int*)0xaf02bef0@@40 @end smallexample @noindent the object collected in its entirety would be @code{myVar}. The object @code{myArray} would be partially collected, because only the element at index @code{myIndex} would be collected. The remaining objects would be computed expressions. > diff --git a/gdb/mi/mi-main.c b/gdb/mi/mi-main.c > index 430d530..0b8740da 100644 > --- a/gdb/mi/mi-main.c > +++ b/gdb/mi/mi-main.c > + > +/* Implement the "-trace-frame-collected" command. */ > + > +void > +mi_cmd_trace_frame_collected (char *command, char **argv, int argc) > +{ ... > + /* This command only makes sense for the current frame, not the > + selected frame. */ > + old_chain = make_cleanup_restore_current_thread (); > + select_frame (get_current_frame ()); ISTR a fix for tdump in the same vein as this. Is it in the queue? Maybe it's already in... > + > + { > + struct collection_list tracepoint_list, stepping_list; > + > + encode_actions (tloc, &tracepoint_list, &stepping_list); > + > + if (stepping_frame) > + clist = &stepping_list; > + else > + clist = &tracepoint_list; > + } This use of scoping is wrong. As soon as the scope ends, the life time of tracepoint_list and stepping_list's ends, so uses of clist's pointee beyond this scope are undefined. > diff --git a/gdb/remote.c b/gdb/remote.c > index 080d048..d06b1ed 100644 > --- a/gdb/remote.c > +++ b/gdb/remote.c > @@ -10524,7 +10524,7 @@ remote_download_tracepoint (struct bp_location *loc) > struct breakpoint *b = loc->owner; > struct tracepoint *t = (struct tracepoint *) b; > > - encode_actions (loc, &tdp_actions, &stepping_actions); > + encode_actions_rsp (loc, &tdp_actions, &stepping_actions); > old_chain = make_cleanup (free_actions_list_cleanup_wrapper, > tdp_actions); > (void) make_cleanup (free_actions_list_cleanup_wrapper, > diff --git a/gdb/tracepoint.c b/gdb/tracepoint.c > index d7d0e88..4f10c93 100644 > --- a/gdb/tracepoint.c > +++ b/gdb/tracepoint.c > @@ -340,6 +340,22 @@ find_trace_state_variable (const char *name) > return NULL; > } > > +/* Return the tsv if its number is NUMBER. Return NULL if not > + found. */ "if its number is" sounds a little odd. /* Return the tsv with number NUMBER. Return NULL if not found. */ Or based on find_trace_state_variable's comment: /* Look for a trace state variable with a given number. Return NULL if not found. */ > + > +struct trace_state_variable * > +find_trace_state_variable_by_number (int number) > +{ > -/* Render all actions into gdb protocol. */ > +/* 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. */ I think it'd be good to rename this as: encode_actions_and_make_cleanup Functions that return a cleanup aren't that frequent, and from reading the user code, one gets the impression a cleanup is missing, if there's no such hint. > > -void > -encode_actions (struct bp_location *tloc, char ***tdp_actions, > - char ***stepping_actions) > +struct cleanup * > +encode_actions (struct bp_location *tloc, > + struct collection_list *tracepoint_list, > + struct collection_list *stepping_list) > { This looks good to me with those changes. Thanks! -- Pedro Alves ^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PATCH 5/6] New MI command -trace-frame-collected 2013-06-25 17:31 ` Pedro Alves @ 2013-06-26 8:29 ` Yao Qi 2013-06-26 11:22 ` Pedro Alves 0 siblings, 1 reply; 36+ messages in thread From: Yao Qi @ 2013-06-26 8:29 UTC (permalink / raw) To: Pedro Alves; +Cc: Eli Zaretskii, gdb-patches On 06/26/2013 01:15 AM, Pedro Alves wrote: > #1 "If the actions were ... then foo would be." sounds right. > #2 "If the actions are ... then foo is." would sound right. > #3 "If the actions were ... then foo is." sounds odd. > > s/Object/The object/ > > "only the element at index" Fixed. > > "rest of the objects", or "the remaining objects" I am not sure "The rest of objects" is wrong. I search "The rest of objects" in google, and find a lot of usages. Anyway, "the remaining objects" is fine to me, and I use it in the updated patch. >> >diff --git a/gdb/mi/mi-main.c b/gdb/mi/mi-main.c >> >index 430d530..0b8740da 100644 >> >--- a/gdb/mi/mi-main.c >> >+++ b/gdb/mi/mi-main.c >> >+ >> >+/* Implement the "-trace-frame-collected" command. */ >> >+ >> >+void >> >+mi_cmd_trace_frame_collected (char *command, char **argv, int argc) >> >+{ > ... > >> >+ /* This command only makes sense for the current frame, not the >> >+ selected frame. */ >> >+ old_chain = make_cleanup_restore_current_thread (); >> >+ select_frame (get_current_frame ()); > ISTR a fix for tdump in the same vein as this. Is it in the queue? > Maybe it's already in... > Yes, it is in the queue. Will post it. >> >+ >> >+ { >> >+ struct collection_list tracepoint_list, stepping_list; >> >+ >> >+ encode_actions (tloc, &tracepoint_list, &stepping_list); >> >+ >> >+ if (stepping_frame) >> >+ clist = &stepping_list; >> >+ else >> >+ clist = &tracepoint_list; >> >+ } > This use of scoping is wrong. As soon as the scope ends, > the life time of tracepoint_list and stepping_list's ends, so > uses of clist's pointee beyond this scope are undefined. > Oops. Sorry about that. Fixed. >> >diff --git a/gdb/remote.c b/gdb/remote.c >> >index 080d048..d06b1ed 100644 >> >--- a/gdb/remote.c >> >+++ b/gdb/remote.c >> >@@ -10524,7 +10524,7 @@ remote_download_tracepoint (struct bp_location *loc) >> > struct breakpoint *b = loc->owner; >> > struct tracepoint *t = (struct tracepoint *) b; >> > >> >- encode_actions (loc, &tdp_actions, &stepping_actions); >> >+ encode_actions_rsp (loc, &tdp_actions, &stepping_actions); >> > old_chain = make_cleanup (free_actions_list_cleanup_wrapper, >> > tdp_actions); >> > (void) make_cleanup (free_actions_list_cleanup_wrapper, >> >diff --git a/gdb/tracepoint.c b/gdb/tracepoint.c >> >index d7d0e88..4f10c93 100644 >> >--- a/gdb/tracepoint.c >> >+++ b/gdb/tracepoint.c >> >@@ -340,6 +340,22 @@ find_trace_state_variable (const char *name) >> > return NULL; >> > } >> > >> >+/* Return the tsv if its number is NUMBER. Return NULL if not >> >+ found. */ > "if its number is" sounds a little odd. > > /* Return the tsv with number NUMBER. Return NULL if not > found. */ > > Or based on find_trace_state_variable's comment: > > /* Look for a trace state variable with a given number. Return NULL > if not found. */ > This one is good to me. >> >+ >> >+struct trace_state_variable * >> >+find_trace_state_variable_by_number (int number) >> >+{ > > >> >-/* Render all actions into gdb protocol. */ >> >+/* 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. */ > I think it'd be good to rename this as: > > encode_actions_and_make_cleanup > > Functions that return a cleanup aren't that frequent, and from > reading the user code, one gets the impression a cleanup is missing, > if there's no such hint. > Agreed. All your comments are addressed in the patch below, and the patch is committed. -- Yao (é½å°§) gdb/doc: 2013-06-26 Pedro Alves <pedro@codesourcery.com> Yao Qi <yao@codesourcery.com> * gdb.texinfo (GDB/MI Tracepoint Commands): Document -trace-frame-collected. gdb: 2013-06-26 Pedro Alves <pedro@codesourcery.com> Yao Qi <yao@codesourcery.com> * mi/mi-cmds.c (mi_cmds): Register -trace-frame-collected. * mi/mi-cmds.h (mi_cmd_trace_frame_collected): Declare. * mi/mi-main.c (print_variable_or_computed): New function. (mi_cmd_trace_frame_collected): New function. * tracepoint.c (find_trace_state_variable_by_number): New. (struct traceframe_info): Move to tracepoint.h (struct collection_list): Likewise. (do_collect_symbol): Include locals and arguments in the wholly collected variables list. (clear_collection_list): Clear wholly collected variables list and computed variables list. (append_exp): New function. (encode_actions_1): Include variables in the wholly collected variables list. Include memory ranges and full-fledged expressions in the computed expressions list. (encode_actions): Move some code to ... Return the cleanup chain. (encode_actions_rsp): ... here. New function. (encode_actions_and_make_cleanup): New. Renamed from encode_actions. All callers changed. (get_traceframe_location, get_traceframe_info): Remove static. * tracepoint.h (struct memrange): Moved from tracepoint.c. (struct collection_list): Moved from tracepoint.c. Add two new fields 'wholly_collected' and 'computed'. (find_trace_state_variable_by_number): Declare. (encode_actions): Remove declaration. (encode_actions_and_make_cleanup, encode_actions_rsp): Declare. (get_traceframe_info, get_traceframe_location): Declare. * NEWS: Mention new MI command -trace-frame-collected. --- gdb/NEWS | 3 + gdb/doc/gdb.texinfo | 117 ++++++++++++++++++++ gdb/mi/mi-cmds.c | 2 + gdb/mi/mi-cmds.h | 1 + gdb/mi/mi-main.c | 295 +++++++++++++++++++++++++++++++++++++++++++++++++++ gdb/remote.c | 2 +- gdb/tracepoint.c | 145 ++++++++++++++++--------- gdb/tracepoint.h | 48 ++++++++- 8 files changed, 559 insertions(+), 54 deletions(-) diff --git a/gdb/NEWS b/gdb/NEWS index ab8f283..e469f1e 100644 --- a/gdb/NEWS +++ b/gdb/NEWS @@ -81,6 +81,9 @@ show range-stepping "--skip-unavailable" option. When used, only the available registers are displayed. + ** The new command -trace-frame-collected dumps collected variables, + computed expressions, tvars, memory and registers in a traceframe. + * New system-wide configuration scripts A GDB installation now provides scripts suitable for use as system-wide configuration scripts for the following systems: diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo index 3992704..d75a3d1 100644 --- a/gdb/doc/gdb.texinfo +++ b/gdb/doc/gdb.texinfo @@ -33161,6 +33161,123 @@ with the @samp{$} character. The corresponding @value{GDBN} command is @samp{tvariable}. +@subheading The @code{-trace-frame-collected} Command +@findex -trace-frame-collected + +@subsubheading Synopsis + +@smallexample + -trace-frame-collected + [--var-print-values @var{var_pval}] + [--comp-print-values @var{comp_pval}] + [--registers-format @var{regformat}] + [--memory-contents] +@end smallexample + +This command returns the set of collected objects, register names, +trace state variable names, memory ranges and computed expressions +that have been collected at a particular trace frame. The optional +parameters to the command affect the output format in different ways. +See the output description table below for more details. + +The reported names can be used in the normal manner to create +varobjs and inspect the objects themselves. The items returned by +this command are categorized so that it is clear which is a variable, +which is a register, which is a trace state variable, which is a +memory range and which is a computed expression. + +For instance, if the actions were +@smallexample +collect myVar, myArray[myIndex], myObj.field, myPtr->field, myCount + 2 +collect *(int*)0xaf02bef0@@40 +@end smallexample + +@noindent +the object collected in its entirety would be @code{myVar}. The +object @code{myArray} would be partially collected, because only the +element at index @code{myIndex} would be collected. The remaining +objects would be computed expressions. + +An example output would be: + +@smallexample +(gdb) +-trace-frame-collected +^done, + explicit-variables=[@{name="myVar",value="1"@}], + computed-expressions=[@{name="myArray[myIndex]",value="0"@}, + @{name="myObj.field",value="0"@}, + @{name="myPtr->field",value="1"@}, + @{name="myCount + 2",value="3"@}, + @{name="$tvar1 + 1",value="43970027"@}], + registers=[@{number="0",value="0x7fe2c6e79ec8"@}, + @{number="1",value="0x0"@}, + @{number="2",value="0x4"@}, + ... + @{number="125",value="0x0"@}], + tvars=[@{name="$tvar1",current="43970026"@}], + memory=[@{address="0x0000000000602264",length="4"@}, + @{address="0x0000000000615bc0",length="4"@}] +(gdb) +@end smallexample + +Where: + +@table @code +@item explicit-variables +The set of objects that have been collected in their entirety (as +opposed to collecting just a few elements of an array or a few struct +members). For each object, its name and value are printed. +The @code{--var-print-values} option affects how or whether the value +field is output. If @var{var_pval} is 0, then print only the names; +if it is 1, print also their values; and if it is 2, print the name, +type and value for simple data types, and the name and type for +arrays, structures and unions. + +@item computed-expressions +The set of computed expressions that have been collected at the +current trace frame. The @code{--comp-print-values} option affects +this set like the @code{--var-print-values} option affects the +@code{explicit-variables} set. See above. + +@item registers +The registers that have been collected at the current trace frame. +For each register collected, the name and current value are returned. +The value is formatted according to the @code{--registers-format} +option. See the @command{-data-list-register-values} command for a +list of the allowed formats. The default is @samp{x}. + +@item tvars +The trace state variables that have been collected at the current +trace frame. For each trace state variable collected, the name and +current value are returned. + +@item memory +The set of memory ranges that have been collected at the current trace +frame. Its content is a list of tuples. Each tuple represents a +collected memory range and has the following fields: + +@table @code +@item address +The start address of the memory range, as hexadecimal literal. + +@item length +The length of the memory range, as decimal literal. + +@item contents +The contents of the memory block, in hex. This field is only present +if the @code{--memory-contents} option is specified. + +@end table + +@end table + +@subsubheading @value{GDBN} Command + +There is no corresponding @value{GDBN} command. + +@subsubheading Example + @subheading -trace-list-variables @findex -trace-list-variables diff --git a/gdb/mi/mi-cmds.c b/gdb/mi/mi-cmds.c index eb67abe..0768b2a 100644 --- a/gdb/mi/mi-cmds.c +++ b/gdb/mi/mi-cmds.c @@ -148,6 +148,8 @@ static struct mi_cmd mi_cmds[] = DEF_MI_CMD_MI ("trace-define-variable", mi_cmd_trace_define_variable), DEF_MI_CMD_MI_1 ("trace-find", mi_cmd_trace_find, &mi_suppress_notification.traceframe), + DEF_MI_CMD_MI ("trace-frame-collected", + mi_cmd_trace_frame_collected), DEF_MI_CMD_MI ("trace-list-variables", mi_cmd_trace_list_variables), DEF_MI_CMD_MI ("trace-save", mi_cmd_trace_save), DEF_MI_CMD_MI ("trace-start", mi_cmd_trace_start), diff --git a/gdb/mi/mi-cmds.h b/gdb/mi/mi-cmds.h index 8839319..a472582 100644 --- a/gdb/mi/mi-cmds.h +++ b/gdb/mi/mi-cmds.h @@ -94,6 +94,7 @@ extern mi_cmd_argv_ftype mi_cmd_thread_list_ids; extern mi_cmd_argv_ftype mi_cmd_thread_select; extern mi_cmd_argv_ftype mi_cmd_trace_define_variable; extern mi_cmd_argv_ftype mi_cmd_trace_find; +extern mi_cmd_argv_ftype mi_cmd_trace_frame_collected; extern mi_cmd_argv_ftype mi_cmd_trace_list_variables; extern mi_cmd_argv_ftype mi_cmd_trace_save; extern mi_cmd_argv_ftype mi_cmd_trace_start; diff --git a/gdb/mi/mi-main.c b/gdb/mi/mi-main.c index 430d530..d6c763e 100644 --- a/gdb/mi/mi-main.c +++ b/gdb/mi/mi-main.c @@ -2585,3 +2585,298 @@ mi_cmd_ada_task_info (char *command, char **argv, int argc) print_ada_task_info (current_uiout, argv[0], current_inferior ()); } + +/* Print EXPRESSION according to VALUES. */ + +static void +print_variable_or_computed (char *expression, enum print_values values) +{ + struct expression *expr; + struct cleanup *old_chain; + struct value *val; + struct ui_file *stb; + struct value_print_options opts; + struct type *type; + struct ui_out *uiout = current_uiout; + + stb = mem_fileopen (); + old_chain = make_cleanup_ui_file_delete (stb); + + expr = parse_expression (expression); + + make_cleanup (free_current_contents, &expr); + + if (values == PRINT_SIMPLE_VALUES) + val = evaluate_type (expr); + else + val = evaluate_expression (expr); + + if (values != PRINT_NO_VALUES) + make_cleanup_ui_out_tuple_begin_end (uiout, NULL); + ui_out_field_string (uiout, "name", expression); + + switch (values) + { + case PRINT_SIMPLE_VALUES: + type = check_typedef (value_type (val)); + type_print (value_type (val), "", stb, -1); + ui_out_field_stream (uiout, "type", stb); + if (TYPE_CODE (type) != TYPE_CODE_ARRAY + && TYPE_CODE (type) != TYPE_CODE_STRUCT + && TYPE_CODE (type) != TYPE_CODE_UNION) + { + struct value_print_options opts; + + get_raw_print_options (&opts); + opts.deref_ref = 1; + common_val_print (val, stb, 0, &opts, current_language); + ui_out_field_stream (uiout, "value", stb); + } + break; + case PRINT_ALL_VALUES: + { + struct value_print_options opts; + + get_raw_print_options (&opts); + opts.deref_ref = 1; + common_val_print (val, stb, 0, &opts, current_language); + ui_out_field_stream (uiout, "value", stb); + } + break; + } + + do_cleanups (old_chain); +} + +/* Implement the "-trace-frame-collected" command. */ + +void +mi_cmd_trace_frame_collected (char *command, char **argv, int argc) +{ + struct cleanup *old_chain; + struct bp_location *tloc; + int stepping_frame; + struct collection_list *clist; + struct collection_list tracepoint_list, stepping_list; + struct traceframe_info *tinfo; + int oind = 0; + int var_print_values = PRINT_ALL_VALUES; + int comp_print_values = PRINT_ALL_VALUES; + int registers_format = 'x'; + int memory_contents = 0; + struct ui_out *uiout = current_uiout; + enum opt + { + VAR_PRINT_VALUES, + COMP_PRINT_VALUES, + REGISTERS_FORMAT, + MEMORY_CONTENTS, + }; + static const struct mi_opt opts[] = + { + {"-var-print-values", VAR_PRINT_VALUES, 1}, + {"-comp-print-values", COMP_PRINT_VALUES, 1}, + {"-registers-format", REGISTERS_FORMAT, 1}, + {"-memory-contents", MEMORY_CONTENTS, 0}, + { 0, 0, 0 } + }; + + while (1) + { + char *oarg; + int opt = mi_getopt ("-trace-frame-collected", argc, argv, opts, + &oind, &oarg); + if (opt < 0) + break; + switch ((enum opt) opt) + { + case VAR_PRINT_VALUES: + var_print_values = mi_parse_print_values (oarg); + break; + case COMP_PRINT_VALUES: + comp_print_values = mi_parse_print_values (oarg); + break; + case REGISTERS_FORMAT: + registers_format = oarg[0]; + case MEMORY_CONTENTS: + memory_contents = 1; + break; + } + } + + if (oind != argc) + error (_("Usage: -trace-frame-collected " + "[--var-print-values PRINT_VALUES] " + "[--comp-print-values PRINT_VALUES] " + "[--registers-format FORMAT]" + "[--memory-contents]")); + + /* This throws an error is not inspecting a trace frame. */ + tloc = get_traceframe_location (&stepping_frame); + + /* This command only makes sense for the current frame, not the + selected frame. */ + old_chain = make_cleanup_restore_current_thread (); + select_frame (get_current_frame ()); + + encode_actions_and_make_cleanup (tloc, &tracepoint_list, + &stepping_list); + + if (stepping_frame) + clist = &stepping_list; + else + clist = &tracepoint_list; + + tinfo = get_traceframe_info (); + + /* Explicitly wholly collected variables. */ + { + struct cleanup *list_cleanup; + char *p; + int i; + + list_cleanup = make_cleanup_ui_out_list_begin_end (uiout, + "explicit-variables"); + for (i = 0; VEC_iterate (char_ptr, clist->wholly_collected, i, p); i++) + print_variable_or_computed (p, var_print_values); + do_cleanups (list_cleanup); + } + + /* Computed expressions. */ + { + struct cleanup *list_cleanup; + char *p; + int i; + + list_cleanup + = make_cleanup_ui_out_list_begin_end (uiout, + "computed-expressions"); + for (i = 0; VEC_iterate (char_ptr, clist->computed, i, p); i++) + print_variable_or_computed (p, comp_print_values); + do_cleanups (list_cleanup); + } + + /* Registers. Given pseudo-registers, and that some architectures + (like MIPS) actually hide the raw registers, we don't go through + the trace frame info, but instead consult the register cache for + register availability. */ + { + struct cleanup *list_cleanup; + struct frame_info *frame; + struct gdbarch *gdbarch; + int regnum; + int numregs; + + list_cleanup = make_cleanup_ui_out_list_begin_end (uiout, "registers"); + + frame = get_selected_frame (NULL); + gdbarch = get_frame_arch (frame); + numregs = gdbarch_num_regs (gdbarch) + gdbarch_num_pseudo_regs (gdbarch); + + for (regnum = 0; regnum < numregs; regnum++) + { + if (gdbarch_register_name (gdbarch, regnum) == NULL + || *(gdbarch_register_name (gdbarch, regnum)) == '\0') + continue; + + output_register (frame, regnum, registers_format, 1); + } + + do_cleanups (list_cleanup); + } + + /* Trace state variables. */ + { + struct cleanup *list_cleanup; + int tvar; + char *tsvname; + int i; + + list_cleanup = make_cleanup_ui_out_list_begin_end (uiout, "tvars"); + + tsvname = NULL; + make_cleanup (free_current_contents, &tsvname); + + for (i = 0; VEC_iterate (int, tinfo->tvars, i, tvar); i++) + { + struct cleanup *cleanup_child; + struct trace_state_variable *tsv; + + tsv = find_trace_state_variable_by_number (tvar); + + cleanup_child = make_cleanup_ui_out_tuple_begin_end (uiout, NULL); + + if (tsv != NULL) + { + tsvname = xrealloc (tsvname, strlen (tsv->name) + 2); + tsvname[0] = '$'; + strcpy (tsvname + 1, tsv->name); + ui_out_field_string (uiout, "name", tsvname); + + tsv->value_known = target_get_trace_state_variable_value (tsv->number, + &tsv->value); + ui_out_field_int (uiout, "current", tsv->value); + } + else + { + ui_out_field_skip (uiout, "name"); + ui_out_field_skip (uiout, "current"); + } + + do_cleanups (cleanup_child); + } + + do_cleanups (list_cleanup); + } + + /* Memory. */ + { + struct cleanup *list_cleanup; + VEC(mem_range_s) *available_memory = NULL; + struct mem_range *r; + int i; + + traceframe_available_memory (&available_memory, 0, ULONGEST_MAX); + make_cleanup (VEC_cleanup(mem_range_s), &available_memory); + + list_cleanup = make_cleanup_ui_out_list_begin_end (uiout, "memory"); + + for (i = 0; VEC_iterate (mem_range_s, available_memory, i, r); i++) + { + struct cleanup *cleanup_child; + gdb_byte *data; + struct gdbarch *gdbarch = target_gdbarch (); + + cleanup_child = make_cleanup_ui_out_tuple_begin_end (uiout, NULL); + + ui_out_field_core_addr (uiout, "address", gdbarch, r->start); + ui_out_field_int (uiout, "length", r->length); + + data = xmalloc (r->length); + make_cleanup (xfree, data); + + if (memory_contents) + { + if (target_read_memory (r->start, data, r->length) == 0) + { + int m; + char *data_str, *p; + + data_str = xmalloc (r->length * 2 + 1); + make_cleanup (xfree, data_str); + + for (m = 0, p = data_str; m < r->length; ++m, p += 2) + sprintf (p, "%02x", data[m]); + ui_out_field_string (uiout, "contents", data_str); + } + else + ui_out_field_skip (uiout, "contents"); + } + do_cleanups (cleanup_child); + } + + do_cleanups (list_cleanup); + } + + do_cleanups (old_chain); +} diff --git a/gdb/remote.c b/gdb/remote.c index 7928f57..a29fe23 100644 --- a/gdb/remote.c +++ b/gdb/remote.c @@ -10527,7 +10527,7 @@ remote_download_tracepoint (struct bp_location *loc) struct breakpoint *b = loc->owner; struct tracepoint *t = (struct tracepoint *) b; - encode_actions (loc, &tdp_actions, &stepping_actions); + encode_actions_rsp (loc, &tdp_actions, &stepping_actions); old_chain = make_cleanup (free_actions_list_cleanup_wrapper, tdp_actions); (void) make_cleanup (free_actions_list_cleanup_wrapper, diff --git a/gdb/tracepoint.c b/gdb/tracepoint.c index 62b1a2c..4277843 100644 --- a/gdb/tracepoint.c +++ b/gdb/tracepoint.c @@ -340,6 +340,22 @@ find_trace_state_variable (const char *name) return NULL; } +/* Look for a trace state variable of the given number. Return NULL if + not found. */ + +struct trace_state_variable * +find_trace_state_variable_by_number (int number) +{ + struct trace_state_variable *tsv; + int ix; + + for (ix = 0; VEC_iterate (tsv_s, tvariables, ix, tsv); ++ix) + if (tsv->number == number) + return tsv; + + return NULL; +} + static void delete_trace_state_variable (const char *name) { @@ -853,29 +869,6 @@ enum { memrange_absolute = -1 }; -struct memrange -{ - int type; /* memrange_absolute for absolute memory range, - else basereg number. */ - bfd_signed_vma start; - bfd_signed_vma end; -}; - -struct collection_list - { - unsigned char regs_mask[32]; /* room for up to 256 regs */ - long listsize; - long next_memrange; - struct memrange *list; - long aexpr_listsize; /* size of array pointed to by expr_list elt */ - long next_aexpr_elt; - struct agent_expr **aexpr_list; - - /* True is the user requested a collection of "$_sdata", "static - tracepoint data". */ - int strace_data; - }; - /* MEMRANGE functions: */ static int memrange_cmp (const void *, const void *); @@ -1166,6 +1159,9 @@ do_collect_symbol (const char *print_name, collect_symbol (p->collect, 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)); } /* Add all locals (or args) symbols to collection list. */ @@ -1242,6 +1238,9 @@ clear_collection_list (struct collection_list *list) 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. */ @@ -1392,6 +1391,21 @@ stringify_collection_list (struct collection_list *list) return *str_list; } +/* Add the printed expression EXP to *LIST. */ + +static void +append_exp (struct expression *exp, VEC(char_ptr) **list) +{ + 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); + ui_file_delete (tmp_stream); +} static void encode_actions_1 (struct command_line *action, @@ -1537,16 +1551,25 @@ encode_actions_1 (struct command_line *action, check_typedef (exp->elts[1].type); add_memrange (collect, memrange_absolute, addr, TYPE_LENGTH (exp->elts[1].type)); + append_exp (exp, &collect->computed); break; case OP_VAR_VALUE: - collect_symbol (collect, - exp->elts[2].symbol, - tloc->gdbarch, - frame_reg, - frame_offset, - tloc->address, - trace_string); + { + 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); + } break; default: /* Full-fledged expression. */ @@ -1582,6 +1605,8 @@ encode_actions_1 (struct command_line *action, } } } + + append_exp (exp, &collect->computed); break; } /* switch */ do_cleanups (old_chain); @@ -1635,46 +1660,64 @@ encode_actions_1 (struct command_line *action, } /* for */ } -/* Render all actions into gdb protocol. */ +/* 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. */ -void -encode_actions (struct bp_location *tloc, char ***tdp_actions, - char ***stepping_actions) +struct cleanup * +encode_actions_and_make_cleanup (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; - struct collection_list tracepoint_list, stepping_list; - - back_to = make_cleanup (null_cleanup, NULL); + struct cleanup *back_to, *return_chain; - init_collection_list (&tracepoint_list); - init_collection_list (&stepping_list); + 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); - - *tdp_actions = NULL; - *stepping_actions = NULL; + 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); actions = all_tracepoint_actions_and_cleanup (tloc->owner); encode_actions_1 (actions, tloc, frame_reg, frame_offset, - &tracepoint_list, &stepping_list); + tracepoint_list, stepping_list); + + memrange_sortmerge (tracepoint_list); + memrange_sortmerge (stepping_list); + + do_cleanups (back_to); + return return_chain; +} + +/* Render all actions into gdb protocol. */ + +void +encode_actions_rsp (struct bp_location *tloc, char ***tdp_actions, + char ***stepping_actions) +{ + struct collection_list tracepoint_list, stepping_list; + struct cleanup *cleanup; - memrange_sortmerge (&tracepoint_list); - memrange_sortmerge (&stepping_list); + *tdp_actions = NULL; + *stepping_actions = NULL; + + cleanup = encode_actions_and_make_cleanup (tloc, &tracepoint_list, + &stepping_list); *tdp_actions = stringify_collection_list (&tracepoint_list); *stepping_actions = stringify_collection_list (&stepping_list); - do_cleanups (back_to); + do_cleanups (cleanup); } static void @@ -2938,7 +2981,7 @@ trace_dump_actions (struct command_line *action, traceframe. Set *STEPPING_FRAME_P to 1 if the current traceframe is a stepping traceframe. */ -static struct bp_location * +struct bp_location * get_traceframe_location (int *stepping_frame_p) { struct tracepoint *t; @@ -5673,7 +5716,7 @@ parse_traceframe_info (const char *tframe_info) This is where we avoid re-fetching the object from the target if we already have it cached. */ -static struct traceframe_info * +struct traceframe_info * get_traceframe_info (void) { if (traceframe_info == NULL) diff --git a/gdb/tracepoint.h b/gdb/tracepoint.h index 350ab5e..9a874eb 100644 --- a/gdb/tracepoint.h +++ b/gdb/tracepoint.h @@ -323,6 +323,38 @@ struct trace_file_writer const struct trace_file_write_ops *ops; }; +struct memrange +{ + /* memrange_absolute for absolute memory range, else basereg + number. */ + int type; + bfd_signed_vma start; + bfd_signed_vma end; +}; + +struct collection_list +{ + /* room for up to 256 regs */ + unsigned char regs_mask[32]; + long listsize; + long next_memrange; + struct memrange *list; + + /* size of array pointed to by expr_list elt. */ + long aexpr_listsize; + long next_aexpr_elt; + struct agent_expr **aexpr_list; + + /* True is the user requested a collection of "$_sdata", "static + tracepoint data". */ + int strace_data; + + /* A set of names of wholly collected objects. */ + VEC(char_ptr) *wholly_collected; + /* A set of computed expressions. */ + VEC(char_ptr) *computed; +}; + extern void parse_static_tracepoint_marker_definition (char *line, char **pp, struct static_tracepoint_marker *marker); @@ -360,13 +392,21 @@ void free_actions (struct breakpoint *); extern const char *decode_agent_options (const char *exp, int *trace_string); -extern void encode_actions (struct bp_location *tloc, - char ***tdp_actions, char ***stepping_actions); +extern struct cleanup * + encode_actions_and_make_cleanup (struct bp_location *tloc, + struct collection_list *tracepoint_list, + struct collection_list *stepping_list); + +extern void encode_actions_rsp (struct bp_location *tloc, + char ***tdp_actions, char ***stepping_actions); extern void validate_actionline (const char *, struct breakpoint *); extern void validate_trace_state_variable_name (const char *name); extern struct trace_state_variable *find_trace_state_variable (const char *name); +extern struct trace_state_variable * + find_trace_state_variable_by_number (int number); + extern struct trace_state_variable *create_trace_state_variable (const char *name); extern int encode_source_string (int num, ULONGEST addr, @@ -416,4 +456,8 @@ extern struct traceframe_info *parse_traceframe_info (const char *tframe_info); extern int traceframe_available_memory (VEC(mem_range_s) **result, CORE_ADDR memaddr, ULONGEST len); +extern struct traceframe_info *get_traceframe_info (void); + +extern struct bp_location *get_traceframe_location (int *stepping_frame_p); + #endif /* TRACEPOINT_H */ -- 1.7.7.6 ^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PATCH 5/6] New MI command -trace-frame-collected 2013-06-26 8:29 ` Yao Qi @ 2013-06-26 11:22 ` Pedro Alves 0 siblings, 0 replies; 36+ messages in thread From: Pedro Alves @ 2013-06-26 11:22 UTC (permalink / raw) To: Yao Qi; +Cc: Eli Zaretskii, gdb-patches On 06/26/2013 09:19 AM, Yao Qi wrote: >> "rest of the objects", or "the remaining objects" > > > I am not sure "The rest of objects" is wrong. I search "The rest of > objects" in google, and find a lot of usages. It may look like a lot in isolation, but google finds 89700 uses without "the" vs 51000000 (51M) with "the". It just looks like ~0.18% didn't know better to me. Anyway, "the remaining > objects" is fine to me, and I use it in the updated patch. Thanks. > Agreed. All your comments are addressed in the patch below, and the > patch is committed. Thanks again, -- Pedro Alves ^ permalink raw reply [flat|nested] 36+ messages in thread
* [PATCH 4/6] Add id of TSV into traceframe_info. 2013-06-13 1:29 ` [PATCH 0/6 V2] New MI command -trace-frame-collected Yao Qi 2013-06-13 1:29 ` [PATCH 5/6] " Yao Qi @ 2013-06-13 1:29 ` Yao Qi 2013-06-13 3:40 ` Eli Zaretskii 2013-06-25 16:18 ` Pedro Alves 2013-06-13 1:29 ` [PATCH 2/6] Emit error in tdump command when traceframe is not selected Yao Qi ` (4 subsequent siblings) 6 siblings, 2 replies; 36+ messages in thread From: Yao Qi @ 2013-06-13 1:29 UTC (permalink / raw) To: gdb-patches Hi, This patch extends the qXfer:traceframe-info object to report the set of collected trace state variables in the current traceframe. Since VEC(int) is used in tracepoint.h, to avoid duplicated definition error, this patch also moves DEF_VEC_I(int) to gdb_vecs.h, and include it in other files instead of defining it by their own. When GDB reads from trace file (tfile or ctf), the traceframe_ifo object should be updated for trace state variables as well. gdb: 2013-06-13 Pedro Alves <pedro@codesourcery.com> Yao Qi <yao@codesourcery.com> * ctf.c (ctf_traceframe_info): Push trace state variables present in the trace data into the traceframe info object. * breakpoint.c (DEF_VEC_I): Remove. * common/filestuff.c (DEF_VEC_I): Likewise. * dwarf2loc.c (DEF_VEC_I): Likewise. * mi/mi-main.c (DEF_VEC_I): Likewise. * common/gdb_vecs.h (DEF_VEC_I): Define vector for int. * features/traceframe-info.dtd: Add tvar element and its attributes. * tracepoint.c (free_traceframe_info): Free vector 'tvars'. (build_traceframe_info): Push trace state variables present in the trace data into the traceframe info object. (traceframe_info_start_tvar): New function. (tvar_attributes): New. (traceframe_info_children): Add "tvar" element. * tracepoint.h (struct traceframe_info) <tvars>: New field. * NEWS: Mention the change in GDB and GDBserver. gdb/doc: 2013-06-13 Pedro Alves <pedro@codesourcery.com> * gdb.texinfo (Traceframe Info Format): Document tvar element and its attributes. gdb/gdbserver: 2013-06-13 Pedro Alves <pedro@codesourcery.com> * tracepoint.c (build_traceframe_info_xml): Output trace state variables present in the trace buffer. --- gdb/NEWS | 7 +++++++ gdb/breakpoint.c | 2 -- gdb/common/filestuff.c | 2 -- gdb/common/gdb_vecs.h | 2 ++ gdb/ctf.c | 12 ++++++++++++ gdb/doc/gdb.texinfo | 12 +++++++++++- gdb/dwarf2loc.c | 2 -- gdb/features/traceframe-info.dtd | 5 ++++- gdb/gdbserver/tracepoint.c | 7 +++++++ gdb/mi/mi-main.c | 2 -- gdb/tracepoint.c | 30 ++++++++++++++++++++++++++++++ gdb/tracepoint.h | 3 +++ 12 files changed, 76 insertions(+), 10 deletions(-) diff --git a/gdb/NEWS b/gdb/NEWS index ed1c32f..2c66db7 100644 --- a/gdb/NEWS +++ b/gdb/NEWS @@ -91,6 +91,9 @@ show range-stepping the number of control packets from/to GDB. See "New remote packets" below. +* GDB now understands the element 'tvar' in the XML traceframe info. + It has the id of the collected trace state variables. + * New remote packets vCont;r @@ -112,6 +115,10 @@ qXfer:libraries-svr4:read's annex ** GDBserver now supports target-assisted range stepping. Currently enabled on x86/x86_64 GNU/Linux targets. + ** GDBserver now adds element 'tvar' in the XML in the reply to + 'qXfer:traceframe-info:read'. It has the id of the collected + trace state variables. + *** Changes in GDB 7.6 * Target record has been renamed to record-full. diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c index d4ccc81..6054ef4 100644 --- a/gdb/breakpoint.c +++ b/gdb/breakpoint.c @@ -5788,8 +5788,6 @@ bptype_string (enum bptype type) return bptypes[(int) type].description; } -DEF_VEC_I(int); - /* For MI, output a field named 'thread-groups' with a list as the value. For CLI, prefix the list with the string 'inf'. */ diff --git a/gdb/common/filestuff.c b/gdb/common/filestuff.c index daf96d9..7d1a69a 100644 --- a/gdb/common/filestuff.c +++ b/gdb/common/filestuff.c @@ -157,8 +157,6 @@ fdwalk (int (*func) (void *, int), void *arg) don't use a hashtab because libiberty isn't linked into gdbserver; and anyway we don't expect there to be many open fds. */ -DEF_VEC_I (int); - static VEC (int) *open_fds; /* An fdwalk callback function used by notice_open_fds. It puts the diff --git a/gdb/common/gdb_vecs.h b/gdb/common/gdb_vecs.h index 1b05b0c..7df3001 100644 --- a/gdb/common/gdb_vecs.h +++ b/gdb/common/gdb_vecs.h @@ -29,6 +29,8 @@ DEF_VEC_P (char_ptr); DEF_VEC_P (const_char_ptr); +DEF_VEC_I (int); + extern void free_char_ptr_vec (VEC (char_ptr) *char_ptr_vec); extern struct cleanup * diff --git a/gdb/ctf.c b/gdb/ctf.c index 278f950..1f6402d 100644 --- a/gdb/ctf.c +++ b/gdb/ctf.c @@ -1778,6 +1778,18 @@ ctf_traceframe_info (void) def = bt_ctf_get_field (event, scope, "length"); r->length = (uint16_t) bt_ctf_get_uint64 (def); } + else if (strcmp (name, "tsv") == 0) + { + int32_t vnum; + const struct bt_definition *scope + = bt_ctf_get_top_level_scope (event, + BT_EVENT_FIELDS); + const struct bt_definition *def; + + def = bt_ctf_get_field (event, scope, "num"); + vnum = (int32_t) bt_ctf_get_uint64 (def); + VEC_safe_push (int, info->tvars, vnum); + } else { warning (_("Unhandled trace block type (%s) " diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo index d25cdae..3992704 100644 --- a/gdb/doc/gdb.texinfo +++ b/gdb/doc/gdb.texinfo @@ -41789,17 +41789,27 @@ A region of collected memory starting at @var{addr} and extending for <memory start="@var{addr}" length="@var{length}"/> @end smallexample +@item +A block indicating trace state variable numbered @var{number} has been +collected: + +@smallexample +<tvar id="@var{number}"/> +@end smallexample + @end itemize The formal DTD for the traceframe info format is given below: @smallexample -<!ELEMENT traceframe-info (memory)* > +<!ELEMENT traceframe-info (memory | tvar)* > <!ATTLIST traceframe-info version CDATA #FIXED "1.0"> <!ELEMENT memory EMPTY> <!ATTLIST memory start CDATA #REQUIRED length CDATA #REQUIRED> +<!ELEMENT tvar> +<!ATTLIST tvar id CDATA #REQUIRED> @end smallexample @node Branch Trace Format diff --git a/gdb/dwarf2loc.c b/gdb/dwarf2loc.c index 9e44096..aac2a1a 100644 --- a/gdb/dwarf2loc.c +++ b/gdb/dwarf2loc.c @@ -42,8 +42,6 @@ #include "gdb_string.h" #include "gdb_assert.h" -DEF_VEC_I(int); - extern int dwarf2_always_disassemble; static void dwarf_expr_frame_base_1 (struct symbol *framefunc, CORE_ADDR pc, diff --git a/gdb/features/traceframe-info.dtd b/gdb/features/traceframe-info.dtd index 0da2bec..b811122 100644 --- a/gdb/features/traceframe-info.dtd +++ b/gdb/features/traceframe-info.dtd @@ -5,9 +5,12 @@ notice and this notice are preserved. --> <!-- traceframe-info: Root element with versioning --> -<!ELEMENT traceframe-info (memory)* > +<!ELEMENT traceframe-info (memory | tvar)* > <!ATTLIST traceframe-info version CDATA #FIXED "1.0"> <!ELEMENT memory EMPTY> <!ATTLIST memory start CDATA #REQUIRED length CDATA #REQUIRED> + +<!ELEMENT tvar EMPTY> +<!ATTLIST tvar id CDATA #REQUIRED> diff --git a/gdb/gdbserver/tracepoint.c b/gdb/gdbserver/tracepoint.c index d237e7f..6492b5a 100644 --- a/gdb/gdbserver/tracepoint.c +++ b/gdb/gdbserver/tracepoint.c @@ -5401,6 +5401,13 @@ build_traceframe_info_xml (char blocktype, unsigned char *dataptr, void *data) break; } case 'V': + { + int vnum; + + memcpy (&vnum, dataptr, sizeof (vnum)); + buffer_xml_printf (buffer, "<tvar id=\"%d\"/>\n", vnum); + break; + } case 'R': case 'S': { diff --git a/gdb/mi/mi-main.c b/gdb/mi/mi-main.c index 127f6ff..430d530 100644 --- a/gdb/mi/mi-main.c +++ b/gdb/mi/mi-main.c @@ -513,8 +513,6 @@ mi_cmd_thread_info (char *command, char **argv, int argc) print_thread_info (current_uiout, argv[0], -1); } -DEF_VEC_I(int); - struct collect_cores_data { int pid; diff --git a/gdb/tracepoint.c b/gdb/tracepoint.c index 86a573e..d7d0e88 100644 --- a/gdb/tracepoint.c +++ b/gdb/tracepoint.c @@ -235,6 +235,7 @@ free_traceframe_info (struct traceframe_info *info) if (info != NULL) { VEC_free (mem_range_s, info->memory); + VEC_free (int, info->tvars); xfree (info); } @@ -5224,6 +5225,12 @@ build_traceframe_info (char blocktype, void *data) break; } case 'V': + { + int vnum; + + tfile_read ((gdb_byte *) &vnum, 4); + VEC_safe_push (int, info->tvars, vnum); + } case 'R': case 'S': { @@ -5581,6 +5588,21 @@ traceframe_info_start_memory (struct gdb_xml_parser *parser, r->length = *length_p; } +/* Handle the start of a <tvar> element. */ + +static void +traceframe_info_start_tvar (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; + const char *id_attrib = xml_find_attribute (attributes, "id")->value; + int id = gdb_xml_parse_ulongest (parser, id_attrib); + + VEC_safe_push (int, info->tvars, id); +} + /* Discard the constructed trace frame info (if an error occurs). */ static void @@ -5599,10 +5621,18 @@ static const struct gdb_xml_attribute memory_attributes[] = { { NULL, GDB_XML_AF_NONE, NULL, NULL } }; +static const struct gdb_xml_attribute tvar_attributes[] = { + { "id", GDB_XML_AF_NONE, NULL, NULL }, + { NULL, GDB_XML_AF_NONE, NULL, NULL } +}; + static const struct gdb_xml_element traceframe_info_children[] = { { "memory", memory_attributes, NULL, GDB_XML_EF_REPEATABLE | GDB_XML_EF_OPTIONAL, traceframe_info_start_memory, NULL }, + { "tvar", tvar_attributes, NULL, + GDB_XML_EF_REPEATABLE | GDB_XML_EF_OPTIONAL, + traceframe_info_start_tvar, NULL }, { NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL } }; diff --git a/gdb/tracepoint.h b/gdb/tracepoint.h index 3b09ca8..350ab5e 100644 --- a/gdb/tracepoint.h +++ b/gdb/tracepoint.h @@ -30,6 +30,9 @@ struct traceframe_info { /* Collected memory. */ VEC(mem_range_s) *memory; + + /* Collected trace state variables. */ + VEC(int) *tvars; }; /* A trace state variable is a value managed by a target being -- 1.7.7.6 ^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PATCH 4/6] Add id of TSV into traceframe_info. 2013-06-13 1:29 ` [PATCH 4/6] Add id of TSV into traceframe_info Yao Qi @ 2013-06-13 3:40 ` Eli Zaretskii 2013-06-25 16:18 ` Pedro Alves 1 sibling, 0 replies; 36+ messages in thread From: Eli Zaretskii @ 2013-06-13 3:40 UTC (permalink / raw) To: Yao Qi; +Cc: gdb-patches > From: Yao Qi <yao@codesourcery.com> > Date: Thu, 13 Jun 2013 09:28:32 +0800 > > Hi, > This patch extends the qXfer:traceframe-info object to report the set > of collected trace state variables in the current traceframe. > > Since VEC(int) is used in tracepoint.h, to avoid duplicated definition > error, this patch also moves DEF_VEC_I(int) to gdb_vecs.h, and include > it in other files instead of defining it by their own. > > When GDB reads from trace file (tfile or ctf), the traceframe_ifo > object should be updated for trace state variables as well. > > gdb: > > 2013-06-13 Pedro Alves <pedro@codesourcery.com> > Yao Qi <yao@codesourcery.com> > > * ctf.c (ctf_traceframe_info): Push trace state variables > present in the trace data into the traceframe info object. > * breakpoint.c (DEF_VEC_I): Remove. > * common/filestuff.c (DEF_VEC_I): Likewise. > * dwarf2loc.c (DEF_VEC_I): Likewise. > * mi/mi-main.c (DEF_VEC_I): Likewise. > * common/gdb_vecs.h (DEF_VEC_I): Define vector for int. > * features/traceframe-info.dtd: Add tvar element and its > attributes. > * tracepoint.c (free_traceframe_info): Free vector 'tvars'. > (build_traceframe_info): Push trace state variables present in the > trace data into the traceframe info object. > (traceframe_info_start_tvar): New function. > (tvar_attributes): New. > (traceframe_info_children): Add "tvar" element. > * tracepoint.h (struct traceframe_info) <tvars>: New field. > > * NEWS: Mention the change in GDB and GDBserver. > > gdb/doc: > > 2013-06-13 Pedro Alves <pedro@codesourcery.com> > > * gdb.texinfo (Traceframe Info Format): Document tvar element and > its attributes. > > gdb/gdbserver: > > 2013-06-13 Pedro Alves <pedro@codesourcery.com> > > * tracepoint.c (build_traceframe_info_xml): Output trace state > variables present in the trace buffer. The documentation parts are OK. Thanks. ^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PATCH 4/6] Add id of TSV into traceframe_info. 2013-06-13 1:29 ` [PATCH 4/6] Add id of TSV into traceframe_info Yao Qi 2013-06-13 3:40 ` Eli Zaretskii @ 2013-06-25 16:18 ` Pedro Alves 2013-06-26 8:19 ` Yao Qi 1 sibling, 1 reply; 36+ messages in thread From: Pedro Alves @ 2013-06-25 16:18 UTC (permalink / raw) To: Yao Qi; +Cc: gdb-patches On 06/13/2013 02:28 AM, Yao Qi wrote: > diff --git a/gdb/ctf.c b/gdb/ctf.c > index 278f950..1f6402d 100644 > --- a/gdb/ctf.c > +++ b/gdb/ctf.c > @@ -1778,6 +1778,18 @@ ctf_traceframe_info (void) > def = bt_ctf_get_field (event, scope, "length"); > r->length = (uint16_t) bt_ctf_get_uint64 (def); > } > + else if (strcmp (name, "tsv") == 0) > + { > + int32_t vnum; > + const struct bt_definition *scope > + = bt_ctf_get_top_level_scope (event, > + BT_EVENT_FIELDS); > + const struct bt_definition *def; > + > + def = bt_ctf_get_field (event, scope, "num"); > + vnum = (int32_t) bt_ctf_get_uint64 (def); > + VEC_safe_push (int, info->tvars, vnum); The VEC holds "int", so this passing through int32_looks a little odd. And why uint64, if the id is always written as int32 ? Both are written as int32_t: ... /* number */ ctf_save_write_int32 (&writer->tcs, tsv->number); ... static void ctf_write_frame_v_block (struct trace_file_writer *self, int32_t num, uint64_t val) { ... /* num. */ ctf_save_align_write (&writer->tcs, (gdb_byte *) &num, 4, 4); ... BTW, this made me look at the ctf definitions, and I notice that: ctf_save_write_metadata (&writer->tcs, "\n"); ctf_save_write_metadata (&writer->tcs, "event {\n\tname = \"tsv_def\";\n" "\tid = %u;\n\tfields := struct { \n" "\t\tint64_t initial_value;\n" "\t\tint32_t number;\n" "\t\tint32_t builtin;\n" "\t\tchars name;\n" "\t};\n" "};\n", CTF_EVENT_ID_TSV_DEF); "number" here is int32_t, but here ctf_save_write_metadata (&writer->tcs, "\n"); ctf_save_write_metadata (&writer->tcs, "event {\n\tname = \"tsv\";\n\tid = %u;\n" "\tfields := struct { \n" "\t\tuint64_t val;\n" "\t\tuint32_t num;\n" "\t};\n" "};\n", CTF_EVENT_ID_TSV); "num" is uint32_t. Otherwise this is OK. Thanks, -- Pedro Alves ^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PATCH 4/6] Add id of TSV into traceframe_info. 2013-06-25 16:18 ` Pedro Alves @ 2013-06-26 8:19 ` Yao Qi 0 siblings, 0 replies; 36+ messages in thread From: Yao Qi @ 2013-06-26 8:19 UTC (permalink / raw) To: Pedro Alves; +Cc: gdb-patches On 06/26/2013 12:01 AM, Pedro Alves wrote: > The VEC holds "int", so this passing through int32_looks a > little odd. And why uint64, if the id is always written > as int32 ? > babeltrace has two APIs to access integers bt_ctf_get_uint64 and bt_ctf_get_int64. We have to use them to read 32-bit integer. In the updated patch, I define "vnum" with type "int" and use bt_ctf_get_int64 to read it from ctf trace. > Both are written as int32_t: > > ... > /* number */ > ctf_save_write_int32 (&writer->tcs, tsv->number); > ... > static void > ctf_write_frame_v_block (struct trace_file_writer *self, > int32_t num, uint64_t val) > { > ... > /* num. */ > ctf_save_align_write (&writer->tcs, (gdb_byte *) &num, 4, 4); > ... > > > BTW, this made me look at the ctf definitions, and I notice that: > > ctf_save_write_metadata (&writer->tcs, "\n"); > ctf_save_write_metadata (&writer->tcs, > "event {\n\tname = \"tsv_def\";\n" > "\tid = %u;\n\tfields := struct { \n" > "\t\tint64_t initial_value;\n" > "\t\tint32_t number;\n" > "\t\tint32_t builtin;\n" > "\t\tchars name;\n" > "\t};\n" > "};\n", CTF_EVENT_ID_TSV_DEF); > > "number" here is int32_t, but here > > ctf_save_write_metadata (&writer->tcs, "\n"); > ctf_save_write_metadata (&writer->tcs, > "event {\n\tname = \"tsv\";\n\tid = %u;\n" > "\tfields := struct { \n" > "\t\tuint64_t val;\n" > "\t\tuint32_t num;\n" > "\t};\n" > "};\n", CTF_EVENT_ID_TSV); > > > "num" is uint32_t. Thanks for pointing this out. "num" should be int32_t here. I'll fix it separately. > > Otherwise this is OK. Patch below is what I committed. -- Yao (é½å°§) gdb: 2013-06-26 Pedro Alves <pedro@codesourcery.com> Yao Qi <yao@codesourcery.com> * ctf.c (ctf_traceframe_info): Push trace state variables present in the trace data into the traceframe info object. * breakpoint.c (DEF_VEC_I): Remove. * common/filestuff.c (DEF_VEC_I): Likewise. * dwarf2loc.c (DEF_VEC_I): Likewise. * mi/mi-main.c (DEF_VEC_I): Likewise. * common/gdb_vecs.h (DEF_VEC_I): Define vector for int. * features/traceframe-info.dtd: Add tvar element and its attributes. * tracepoint.c (free_traceframe_info): Free vector 'tvars'. (build_traceframe_info): Push trace state variables present in the trace data into the traceframe info object. (traceframe_info_start_tvar): New function. (tvar_attributes): New. (traceframe_info_children): Add "tvar" element. * tracepoint.h (struct traceframe_info) <tvars>: New field. * NEWS: Mention the change in GDB and GDBserver. gdb/doc: 2013-06-26 Pedro Alves <pedro@codesourcery.com> * gdb.texinfo (Traceframe Info Format): Document tvar element and its attributes. gdb/gdbserver: 2013-06-26 Pedro Alves <pedro@codesourcery.com> * tracepoint.c (build_traceframe_info_xml): Output trace state variables present in the trace buffer. --- gdb/NEWS | 7 +++++++ gdb/breakpoint.c | 2 -- gdb/common/filestuff.c | 2 -- gdb/common/gdb_vecs.h | 2 ++ gdb/ctf.c | 12 ++++++++++++ gdb/doc/gdb.texinfo | 12 +++++++++++- gdb/dwarf2loc.c | 2 -- gdb/features/traceframe-info.dtd | 5 ++++- gdb/gdbserver/tracepoint.c | 7 +++++++ gdb/mi/mi-main.c | 2 -- gdb/tracepoint.c | 30 ++++++++++++++++++++++++++++++ gdb/tracepoint.h | 3 +++ 12 files changed, 76 insertions(+), 10 deletions(-) diff --git a/gdb/NEWS b/gdb/NEWS index b86e8d8..ab8f283 100644 --- a/gdb/NEWS +++ b/gdb/NEWS @@ -92,6 +92,9 @@ show range-stepping the number of control packets from/to GDB. See "New remote packets" below. +* GDB now understands the element 'tvar' in the XML traceframe info. + It has the id of the collected trace state variables. + * New remote packets vCont;r @@ -113,6 +116,10 @@ qXfer:libraries-svr4:read's annex ** GDBserver now supports target-assisted range stepping. Currently enabled on x86/x86_64 GNU/Linux targets. + ** GDBserver now adds element 'tvar' in the XML in the reply to + 'qXfer:traceframe-info:read'. It has the id of the collected + trace state variables. + *** Changes in GDB 7.6 * Target record has been renamed to record-full. diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c index ccd05d9..af6a42a 100644 --- a/gdb/breakpoint.c +++ b/gdb/breakpoint.c @@ -5799,8 +5799,6 @@ bptype_string (enum bptype type) return bptypes[(int) type].description; } -DEF_VEC_I(int); - /* For MI, output a field named 'thread-groups' with a list as the value. For CLI, prefix the list with the string 'inf'. */ diff --git a/gdb/common/filestuff.c b/gdb/common/filestuff.c index daf96d9..7d1a69a 100644 --- a/gdb/common/filestuff.c +++ b/gdb/common/filestuff.c @@ -157,8 +157,6 @@ fdwalk (int (*func) (void *, int), void *arg) don't use a hashtab because libiberty isn't linked into gdbserver; and anyway we don't expect there to be many open fds. */ -DEF_VEC_I (int); - static VEC (int) *open_fds; /* An fdwalk callback function used by notice_open_fds. It puts the diff --git a/gdb/common/gdb_vecs.h b/gdb/common/gdb_vecs.h index 1b05b0c..7df3001 100644 --- a/gdb/common/gdb_vecs.h +++ b/gdb/common/gdb_vecs.h @@ -29,6 +29,8 @@ DEF_VEC_P (char_ptr); DEF_VEC_P (const_char_ptr); +DEF_VEC_I (int); + extern void free_char_ptr_vec (VEC (char_ptr) *char_ptr_vec); extern struct cleanup * diff --git a/gdb/ctf.c b/gdb/ctf.c index 278f950..23ee36d 100644 --- a/gdb/ctf.c +++ b/gdb/ctf.c @@ -1778,6 +1778,18 @@ ctf_traceframe_info (void) def = bt_ctf_get_field (event, scope, "length"); r->length = (uint16_t) bt_ctf_get_uint64 (def); } + else if (strcmp (name, "tsv") == 0) + { + int vnum; + const struct bt_definition *scope + = bt_ctf_get_top_level_scope (event, + BT_EVENT_FIELDS); + const struct bt_definition *def; + + def = bt_ctf_get_field (event, scope, "num"); + vnum = (int) bt_ctf_get_int64 (def); + VEC_safe_push (int, info->tvars, vnum); + } else { warning (_("Unhandled trace block type (%s) " diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo index d25cdae..3992704 100644 --- a/gdb/doc/gdb.texinfo +++ b/gdb/doc/gdb.texinfo @@ -41789,17 +41789,27 @@ A region of collected memory starting at @var{addr} and extending for <memory start="@var{addr}" length="@var{length}"/> @end smallexample +@item +A block indicating trace state variable numbered @var{number} has been +collected: + +@smallexample +<tvar id="@var{number}"/> +@end smallexample + @end itemize The formal DTD for the traceframe info format is given below: @smallexample -<!ELEMENT traceframe-info (memory)* > +<!ELEMENT traceframe-info (memory | tvar)* > <!ATTLIST traceframe-info version CDATA #FIXED "1.0"> <!ELEMENT memory EMPTY> <!ATTLIST memory start CDATA #REQUIRED length CDATA #REQUIRED> +<!ELEMENT tvar> +<!ATTLIST tvar id CDATA #REQUIRED> @end smallexample @node Branch Trace Format diff --git a/gdb/dwarf2loc.c b/gdb/dwarf2loc.c index bb600d1..02afcdf 100644 --- a/gdb/dwarf2loc.c +++ b/gdb/dwarf2loc.c @@ -42,8 +42,6 @@ #include "gdb_string.h" #include "gdb_assert.h" -DEF_VEC_I(int); - extern int dwarf2_always_disassemble; static void dwarf_expr_frame_base_1 (struct symbol *framefunc, CORE_ADDR pc, diff --git a/gdb/features/traceframe-info.dtd b/gdb/features/traceframe-info.dtd index 0da2bec..b811122 100644 --- a/gdb/features/traceframe-info.dtd +++ b/gdb/features/traceframe-info.dtd @@ -5,9 +5,12 @@ notice and this notice are preserved. --> <!-- traceframe-info: Root element with versioning --> -<!ELEMENT traceframe-info (memory)* > +<!ELEMENT traceframe-info (memory | tvar)* > <!ATTLIST traceframe-info version CDATA #FIXED "1.0"> <!ELEMENT memory EMPTY> <!ATTLIST memory start CDATA #REQUIRED length CDATA #REQUIRED> + +<!ELEMENT tvar EMPTY> +<!ATTLIST tvar id CDATA #REQUIRED> diff --git a/gdb/gdbserver/tracepoint.c b/gdb/gdbserver/tracepoint.c index d237e7f..6492b5a 100644 --- a/gdb/gdbserver/tracepoint.c +++ b/gdb/gdbserver/tracepoint.c @@ -5401,6 +5401,13 @@ build_traceframe_info_xml (char blocktype, unsigned char *dataptr, void *data) break; } case 'V': + { + int vnum; + + memcpy (&vnum, dataptr, sizeof (vnum)); + buffer_xml_printf (buffer, "<tvar id=\"%d\"/>\n", vnum); + break; + } case 'R': case 'S': { diff --git a/gdb/mi/mi-main.c b/gdb/mi/mi-main.c index 127f6ff..430d530 100644 --- a/gdb/mi/mi-main.c +++ b/gdb/mi/mi-main.c @@ -513,8 +513,6 @@ mi_cmd_thread_info (char *command, char **argv, int argc) print_thread_info (current_uiout, argv[0], -1); } -DEF_VEC_I(int); - struct collect_cores_data { int pid; diff --git a/gdb/tracepoint.c b/gdb/tracepoint.c index 61e9efa..62b1a2c 100644 --- a/gdb/tracepoint.c +++ b/gdb/tracepoint.c @@ -235,6 +235,7 @@ free_traceframe_info (struct traceframe_info *info) if (info != NULL) { VEC_free (mem_range_s, info->memory); + VEC_free (int, info->tvars); xfree (info); } @@ -5224,6 +5225,12 @@ build_traceframe_info (char blocktype, void *data) break; } case 'V': + { + int vnum; + + tfile_read ((gdb_byte *) &vnum, 4); + VEC_safe_push (int, info->tvars, vnum); + } case 'R': case 'S': { @@ -5581,6 +5588,21 @@ traceframe_info_start_memory (struct gdb_xml_parser *parser, r->length = *length_p; } +/* Handle the start of a <tvar> element. */ + +static void +traceframe_info_start_tvar (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; + const char *id_attrib = xml_find_attribute (attributes, "id")->value; + int id = gdb_xml_parse_ulongest (parser, id_attrib); + + VEC_safe_push (int, info->tvars, id); +} + /* Discard the constructed trace frame info (if an error occurs). */ static void @@ -5599,10 +5621,18 @@ static const struct gdb_xml_attribute memory_attributes[] = { { NULL, GDB_XML_AF_NONE, NULL, NULL } }; +static const struct gdb_xml_attribute tvar_attributes[] = { + { "id", GDB_XML_AF_NONE, NULL, NULL }, + { NULL, GDB_XML_AF_NONE, NULL, NULL } +}; + static const struct gdb_xml_element traceframe_info_children[] = { { "memory", memory_attributes, NULL, GDB_XML_EF_REPEATABLE | GDB_XML_EF_OPTIONAL, traceframe_info_start_memory, NULL }, + { "tvar", tvar_attributes, NULL, + GDB_XML_EF_REPEATABLE | GDB_XML_EF_OPTIONAL, + traceframe_info_start_tvar, NULL }, { NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL } }; diff --git a/gdb/tracepoint.h b/gdb/tracepoint.h index 3b09ca8..350ab5e 100644 --- a/gdb/tracepoint.h +++ b/gdb/tracepoint.h @@ -30,6 +30,9 @@ struct traceframe_info { /* Collected memory. */ VEC(mem_range_s) *memory; + + /* Collected trace state variables. */ + VEC(int) *tvars; }; /* A trace state variable is a value managed by a target being -- 1.7.7.6 ^ permalink raw reply [flat|nested] 36+ messages in thread
* [PATCH 2/6] Emit error in tdump command when traceframe is not selected. 2013-06-13 1:29 ` [PATCH 0/6 V2] New MI command -trace-frame-collected Yao Qi 2013-06-13 1:29 ` [PATCH 5/6] " Yao Qi 2013-06-13 1:29 ` [PATCH 4/6] Add id of TSV into traceframe_info Yao Qi @ 2013-06-13 1:29 ` Yao Qi 2013-06-25 15:32 ` Pedro Alves 2013-06-13 1:29 ` [PATCH 3/6] Move code to get_traceframe_location Yao Qi ` (3 subsequent siblings) 6 siblings, 1 reply; 36+ messages in thread From: Yao Qi @ 2013-06-13 1:29 UTC (permalink / raw) To: gdb-patches gdb: 2013-06-13 Pedro Alves <pedro@codesourcery.com> Yao Qi <yao@codesourcery.com> * tracepoint.c (trace_dump_command): GDB emits an error instead of a warning when the traceframe is not selected. --- gdb/tracepoint.c | 5 +---- 1 files changed, 1 insertions(+), 4 deletions(-) diff --git a/gdb/tracepoint.c b/gdb/tracepoint.c index 9646090..05f51ea 100644 --- a/gdb/tracepoint.c +++ b/gdb/tracepoint.c @@ -2982,10 +2982,7 @@ trace_dump_command (char *args, int from_tty) struct cleanup *old_chain; if (tracepoint_number == -1) - { - warning (_("No current trace frame.")); - return; - } + error (_("No current trace frame.")); old_chain = make_cleanup (null_cleanup, NULL); t = get_tracepoint (tracepoint_number); -- 1.7.7.6 ^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PATCH 2/6] Emit error in tdump command when traceframe is not selected. 2013-06-13 1:29 ` [PATCH 2/6] Emit error in tdump command when traceframe is not selected Yao Qi @ 2013-06-25 15:32 ` Pedro Alves 0 siblings, 0 replies; 36+ messages in thread From: Pedro Alves @ 2013-06-25 15:32 UTC (permalink / raw) To: Yao Qi; +Cc: gdb-patches On 06/13/2013 02:28 AM, Yao Qi wrote: > gdb: > > 2013-06-13 Pedro Alves <pedro@codesourcery.com> > Yao Qi <yao@codesourcery.com> > > * tracepoint.c (trace_dump_command): GDB emits an error instead > of a warning when the traceframe is not selected. s/when the/when a/ OK. -- Pedro Alves ^ permalink raw reply [flat|nested] 36+ messages in thread
* [PATCH 3/6] Move code to get_traceframe_location. 2013-06-13 1:29 ` [PATCH 0/6 V2] New MI command -trace-frame-collected Yao Qi ` (2 preceding siblings ...) 2013-06-13 1:29 ` [PATCH 2/6] Emit error in tdump command when traceframe is not selected Yao Qi @ 2013-06-13 1:29 ` Yao Qi 2013-06-25 15:43 ` Pedro Alves 2013-06-13 1:29 ` [PATCH 6/6] New test: gdb.trace/mi-trace-frame-collected.exp Yao Qi ` (2 subsequent siblings) 6 siblings, 1 reply; 36+ messages in thread From: Yao Qi @ 2013-06-13 1:29 UTC (permalink / raw) To: gdb-patches This patch is a refactor patch. It moves some code into a new function get_traceframe_location, which will be shared in the next patch in this series. gdb: 2013-06-13 Pedro Alves <pedro@codesourcery.com> Yao Qi <yao@codesourcery.com> * tracepoint.c (trace_dump_command): Move code to ... (get_traceframe_location): ... here. New. --- gdb/tracepoint.c | 76 +++++++++++++++++++++++++++++++++-------------------- 1 files changed, 47 insertions(+), 29 deletions(-) diff --git a/gdb/tracepoint.c b/gdb/tracepoint.c index 05f51ea..86a573e 100644 --- a/gdb/tracepoint.c +++ b/gdb/tracepoint.c @@ -2933,6 +2933,48 @@ trace_dump_actions (struct command_line *action, } } +/* Return bp_location of the tracepoint associated with the current + traceframe. Set *STEPPING_FRAME_P to 1 if the current traceframe + is the stepping traceframe. */ + +static struct bp_location * +get_traceframe_location (int *stepping_frame_p) +{ + struct tracepoint *t; + struct bp_location *tloc; + struct regcache *regcache; + + if (tracepoint_number == -1) + error (_("No current trace frame.")); + + t = get_tracepoint (tracepoint_number); + + if (t == NULL) + error (_("No known tracepoint matches 'current' tracepoint #%d."), + tracepoint_number); + + /* The current frame is a trap frame if the frame PC is equal to the + tracepoint PC. If not, then the current frame was collected + during single-stepping. */ + regcache = get_current_regcache (); + + /* If the traceframe's address matches any of the tracepoint's + locations, assume it is a direct hit rather than a while-stepping + frame. (FIXME this is not reliable, should record each frame's + type.) */ + for (tloc = t->base.loc; tloc; tloc = tloc->next) + if (tloc->address == regcache_read_pc (regcache)) + { + *stepping_frame_p = 0; + return tloc; + } + + /* If this is a stepping frame, we don't know which location + triggered. The first is as good (or bad) a guess as any... */ + *stepping_frame_p = 1; + return t->base.loc; +} + /* Return all the actions, including default collect, of a tracepoint T. It constructs cleanups into the chain, and leaves the caller to handle them (call do_cleanups). */ @@ -2973,43 +3015,19 @@ all_tracepoint_actions_and_cleanup (struct breakpoint *t) static void trace_dump_command (char *args, int from_tty) { - struct regcache *regcache; - struct tracepoint *t; int stepping_frame = 0; struct bp_location *loc; - char *default_collect_line = NULL; - struct command_line *actions, *default_collect_action = NULL; struct cleanup *old_chain; + struct command_line *actions; - if (tracepoint_number == -1) - error (_("No current trace frame.")); - - old_chain = make_cleanup (null_cleanup, NULL); - t = get_tracepoint (tracepoint_number); - - if (t == NULL) - error (_("No known tracepoint matches 'current' tracepoint #%d."), - tracepoint_number); + /* This throws an error is not inspecting a trace frame. */ + loc = get_traceframe_location (&stepping_frame); printf_filtered ("Data collected at tracepoint %d, trace frame %d:\n", tracepoint_number, traceframe_number); - /* The current frame is a trap frame if the frame PC is equal - to the tracepoint PC. If not, then the current frame was - collected during single-stepping. */ - - regcache = get_current_regcache (); - - /* If the traceframe's address matches any of the tracepoint's - locations, assume it is a direct hit rather than a while-stepping - frame. (FIXME this is not reliable, should record each frame's - type.) */ - stepping_frame = 1; - for (loc = t->base.loc; loc; loc = loc->next) - if (loc->address == regcache_read_pc (regcache)) - stepping_frame = 0; - - actions = all_tracepoint_actions_and_cleanup (&t->base); + old_chain = make_cleanup (null_cleanup, NULL); + actions = all_tracepoint_actions_and_cleanup (loc->owner); trace_dump_actions (actions, 0, stepping_frame, from_tty); -- 1.7.7.6 ^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PATCH 3/6] Move code to get_traceframe_location. 2013-06-13 1:29 ` [PATCH 3/6] Move code to get_traceframe_location Yao Qi @ 2013-06-25 15:43 ` Pedro Alves 0 siblings, 0 replies; 36+ messages in thread From: Pedro Alves @ 2013-06-25 15:43 UTC (permalink / raw) To: Yao Qi; +Cc: gdb-patches On 06/13/2013 02:28 AM, Yao Qi wrote: > This patch is a refactor patch. It moves some code into a new > function get_traceframe_location, which will be shared in the next > patch in this series. > +/* Return bp_location of the tracepoint associated with the current > + traceframe. Set *STEPPING_FRAME_P to 1 if the current traceframe > + is the stepping traceframe. */ s/is the/is a/ > 2013-06-13 Pedro Alves <pedro@codesourcery.com> > Yao Qi <yao@codesourcery.com> > > * tracepoint.c (trace_dump_command): Move code to ... > (get_traceframe_location): ... here. New. OK. Thanks, -- Pedro Alves ^ permalink raw reply [flat|nested] 36+ messages in thread
* [PATCH 6/6] New test: gdb.trace/mi-trace-frame-collected.exp 2013-06-13 1:29 ` [PATCH 0/6 V2] New MI command -trace-frame-collected Yao Qi ` (3 preceding siblings ...) 2013-06-13 1:29 ` [PATCH 3/6] Move code to get_traceframe_location Yao Qi @ 2013-06-13 1:29 ` Yao Qi 2013-06-25 18:42 ` Pedro Alves 2013-06-13 2:46 ` [PATCH 1/6] Remove global variable tracepoint_list and stepping_list Yao Qi 2013-06-24 15:25 ` [ping]: [PATCH 0/6 V2] New MI command -trace-frame-collected Yao Qi 6 siblings, 1 reply; 36+ messages in thread From: Yao Qi @ 2013-06-13 1:29 UTC (permalink / raw) To: gdb-patches gdb/testsuite 2013-06-13 Yao Qi <yao@codesourcery.com> * gdb.trace/mi-trace-frame-collected.exp: New. --- .../gdb.trace/mi-trace-frame-collected.exp | 154 ++++++++++++++++++++ 1 files changed, 154 insertions(+), 0 deletions(-) create mode 100644 gdb/testsuite/gdb.trace/mi-trace-frame-collected.exp diff --git a/gdb/testsuite/gdb.trace/mi-trace-frame-collected.exp b/gdb/testsuite/gdb.trace/mi-trace-frame-collected.exp new file mode 100644 index 0000000..d79eaa7 --- /dev/null +++ b/gdb/testsuite/gdb.trace/mi-trace-frame-collected.exp @@ -0,0 +1,154 @@ +# Copyright 2013 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +load_lib trace-support.exp + +standard_testfile actions.c + +if { [prepare_for_testing ${testfile}.exp ${testfile} ${srcfile} {debug}] } { + return -1 +} + +if ![runto_main] { + fail "Can't run to main to check for trace support" + return -1 +} + +if ![gdb_target_supports_trace] { + unsupported "Current target does not support trace" + return -1 +} + +gdb_exit + +load_lib mi-support.exp +set MIFLAGS "-i=mi" + +if [mi_gdb_start] { + return +} +mi_run_to_main + +mi_gdb_test "-break-insert end" \ + "\\^done,bkpt=\{number=\"${decimal}\",type=\"breakpoint\".*\"\}" \ + "insert tracepoint on end" +mi_gdb_test "-break-insert -a gdb_recursion_test" \ + "\\^done,bkpt=\{number=\"${decimal}\",type=\"tracepoint\".*\"\}" \ + "insert tracepoint on gdb_recursion_test" + +mi_gdb_test "-trace-define-variable \$tsv 1" {.*\^done} \ + "-trace-define-variable" + +# Define an action. +set pcreg "" +if [is_amd64_regs_target] { + set pcreg "rip" +} elseif [is_x86_like_target] { + set pcreg "eip" +} else { + # Other ports support tracepoing should set the name of pc + # register. + fail "set the number and the name of pc register" + return -1 +} + +mi_gdb_test "-break-commands 3 \"collect gdb_char_test\" \"collect gdb_union1_test\" \"collect gdb_struct1_test.l\" \"collect gdb_arr_test\[0\]\" \"collect $${pcreg}\" \"teval \$tsv += 1\" \"collect \$tsv\" \"end\" " \ + {\^done} "set action" + +mi_gdb_test "-break-insert -a gdb_c_test" \ + "\\^done,bkpt=\{number=\"${decimal}\",type=\"tracepoint\".*\"\}" \ + "insert tracepoint on gdb_c_test" +# Collect a global variable to make sure no registers are collected +# expect PC. +mi_gdb_test "-break-commands 4 \"collect gdb_char_test\" \"end\" " \ + {\^done} "set action on tracepoint 4" + +mi_gdb_test "-trace-start" {.*\^done} "trace start" +mi_send_resuming_command "exec-continue" "continuing to end" +mi_expect_stop \ + "breakpoint-hit" "end" ".*" ".*" ".*" {"" "disp=\"keep\""} \ + "stop at end" +mi_gdb_test "-trace-stop" {.*\^done,stop-reason=.*} "trace stop" + +# Save trace frames to tfile. +set tracefile [standard_output_file ${testfile}] +mi_gdb_test "-trace-save ${tracefile}.tf" ".*\\^done" \ + "save tfile trace file" +# Save trace frames to ctf. +mi_gdb_test "-trace-save -ctf ${tracefile}.ctf" ".*\\^done" \ + "save ctf trace file" + +# Test MI command '-trace-frame-collected' from different data source. + +proc test_trace_frame_collected { data_source } { + global decimal hex + global mi_gdb_prompt + + with_test_prefix "$data_source" { + mi_gdb_test "-trace-find frame-number 0" \ + ".*\\^done,found=\"1\",tracepoint=\"${decimal}\",traceframe=\"0\",frame=\{.*" \ + "-trace-find frame-number 0" + + # Test MI command '-trace-frame-collected' dumps only + # collected registers. + mi_gdb_test "-trace-frame-collected" \ + "\\^done,explicit-variables=\\\[\{name=\"gdb_char_test\",value=\".*\"\}\\\],computed-expressions=\\\[\\\],registers=\\\[\{number=\"$decimal\",value=\"$hex\"\}\\\],tvars=\\\[\\\],memory=\\\[\{address=\"$hex\",length=\"1\"\}\\\]"\ + "-trace-frame-collected (register)" + + mi_gdb_test "-trace-find frame-number 1" \ + ".*\\^done,found=\"1\",tracepoint=\"${decimal}\",traceframe=\"1\",frame=\{.*" \ + "-trace-find frame-number 1" + + # Test MI command '-trace-frame-collected' + mi_gdb_test "-trace-frame-collected" \ + "\\^done,explicit-variables=\\\[\{name=\"gdb_char_test\",value=\".*\"\},\{name=\"gdb_union1_test\",value=\".*\"\}\\\],computed-expressions=\\\[\{name=\"gdb_struct1_test\.l\",.*\},\{name=\"gdb_arr_test\\\[0\\\]\",.*\}\\\],registers=\\\[.*\\\],tvars=\\\[\{name=\"\\\$tsv\",current=\"2\"\}\\\],memory=\\\[\{address=\"$hex\",length=\"1\"\},.*\\\]"\ + "-trace-frame-collected" + mi_gdb_test "-trace-frame-collected --var-print-values 2 --comp-print-values --simple-values --registers-format x --memory-contents" \ + "\\^done,explicit-variables=\\\[\{name=\"gdb_char_test\",type=\"char\",value=\".*\"\},\{name=\"gdb_union1_test\",type=\"union GDB_UNION_TEST\"\}\\\],computed-expressions=\\\[.*\\\],registers=\\\[.*\\\],tvars=\\\[\{name=\"\\\$tsv\",current=\"2\"\}\\\],memory=\\\[\{address=\"$hex\",length=\"1\",contents=\".*\"\},.*\\\]" \ + "-trace-frame-collected --var-print-values 2 --comp-print-values --simple-values --registers-format x --memory-contents" + + mi_gdb_test "-trace-find none" ".*\\^done,found=\"0\".*" \ + "-trace-find none" + } +} + +test_trace_frame_collected "live" + +# Change target to ctf if GDB supports it. +set msg "-target-select ctf" +send_gdb "-target-select ctf ${tracefile}.ctf\n" +gdb_expect { + -re ".*\\^connected.*${mi_gdb_prompt}$" { + # GDB supports ctf, do the test. + test_trace_frame_collected "ctf" + } + -re ".*\\^error,msg=\"Undefined target command.*${mi_gdb_prompt}$" { + # GDB doesn't support ctf, skip the test. + unsupported "gdb does not support ctf target" + } + -re ".*$mi_gdb_prompt$" { + fail "$msg" + } + timeout { + fail "$msg (timeout)" + } +} + +# Change target to tfile. +mi_gdb_test "-target-select tfile ${tracefile}.tf" ".*\\^connected.*" \ + "-target-select tfile" +test_trace_frame_collected "tfile" + +mi_gdb_exit -- 1.7.7.6 ^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PATCH 6/6] New test: gdb.trace/mi-trace-frame-collected.exp 2013-06-13 1:29 ` [PATCH 6/6] New test: gdb.trace/mi-trace-frame-collected.exp Yao Qi @ 2013-06-25 18:42 ` Pedro Alves 2013-06-26 10:32 ` Yao Qi 0 siblings, 1 reply; 36+ messages in thread From: Pedro Alves @ 2013-06-25 18:42 UTC (permalink / raw) To: Yao Qi; +Cc: gdb-patches On 06/13/2013 02:28 AM, Yao Qi wrote: > +# Define an action. > +set pcreg "" Suggest giving it an empty line after the comment, as the set is not yet defining the action. > +if [is_amd64_regs_target] { > + set pcreg "rip" > +} elseif [is_x86_like_target] { > + set pcreg "eip" > +} else { > + # Other ports support tracepoing should set the name of pc > + # register. # Other ports that support tracepoints should set the name # of the pc register here. > + fail "set the number and the name of pc register" > + return -1 > +} > + > +mi_gdb_test "-break-commands 3 \"collect gdb_char_test\" \"collect gdb_union1_test\" \"collect gdb_struct1_test.l\" \"collect gdb_arr_test\[0\]\" \"collect $${pcreg}\" \"teval \$tsv += 1\" \"collect \$tsv\" \"end\" " \ > + {\^done} "set action" > + > +mi_gdb_test "-break-insert -a gdb_c_test" \ > + "\\^done,bkpt=\{number=\"${decimal}\",type=\"tracepoint\".*\"\}" \ > + "insert tracepoint on gdb_c_test" > +# Collect a global variable to make sure no registers are collected > +# expect PC. Typo: except. I do that one often too. :-) Suggest s/make sure/be sure/. > +# Test MI command '-trace-frame-collected' from different data source. "from different" threw me off a second (different compared to what?). Suggest: # Test the MI command '-trace-frame-collected' with DATA_SOURCE as # trace data source. > + > +proc test_trace_frame_collected { data_source } { > + global decimal hex > + global mi_gdb_prompt > + This looks OK to me with those changes. Thanks! -- Pedro Alves ^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PATCH 6/6] New test: gdb.trace/mi-trace-frame-collected.exp 2013-06-25 18:42 ` Pedro Alves @ 2013-06-26 10:32 ` Yao Qi 0 siblings, 0 replies; 36+ messages in thread From: Yao Qi @ 2013-06-26 10:32 UTC (permalink / raw) To: Pedro Alves; +Cc: gdb-patches On 06/26/2013 01:31 AM, Pedro Alves wrote: >> +# Define an action. >> >+set pcreg "" > Suggest giving it an empty line after the comment, as the set > is not yet defining the action. > Right. I move this line of comment to the place really defines an action. >> >+if [is_amd64_regs_target] { >> >+ set pcreg "rip" >> >+} elseif [is_x86_like_target] { >> >+ set pcreg "eip" >> >+} else { >> >+ # Other ports support tracepoing should set the name of pc >> >+ # register. > # Other ports that support tracepoints should set the name > # of the pc register here. > Fixed. >> >+ fail "set the number and the name of pc register" >> >+ return -1 >> >+} >> >+ >> >+mi_gdb_test "-break-commands 3 \"collect gdb_char_test\" \"collect gdb_union1_test\" \"collect gdb_struct1_test.l\" \"collect gdb_arr_test\[0\]\" \"collect $${pcreg}\" \"teval \$tsv += 1\" \"collect \$tsv\" \"end\" " \ >> >+ {\^done} "set action" >> >+ >> >+mi_gdb_test "-break-insert -a gdb_c_test" \ >> >+ "\\^done,bkpt=\{number=\"${decimal}\",type=\"tracepoint\".*\"\}" \ >> >+ "insert tracepoint on gdb_c_test" >> >+# Collect a global variable to make sure no registers are collected >> >+# expect PC. > Typo: except. I do that one often too.:-) > Fixed. > Suggest s/make sure/be sure/. > >> >+# Test MI command '-trace-frame-collected' from different data source. > "from different" threw me off a second (different compared to what?). > > Suggest: > > # Test the MI command '-trace-frame-collected' with DATA_SOURCE as > # trace data source. > OK, your suggestion is good. Patch is updated to address your comments and committed. -- Yao (é½å°§) gdb/testsuite 2013-06-26 Yao Qi <yao@codesourcery.com> * gdb.trace/mi-trace-frame-collected.exp: New. --- .../gdb.trace/mi-trace-frame-collected.exp | 156 ++++++++++++++++++++ 1 files changed, 156 insertions(+), 0 deletions(-) create mode 100644 gdb/testsuite/gdb.trace/mi-trace-frame-collected.exp diff --git a/gdb/testsuite/gdb.trace/mi-trace-frame-collected.exp b/gdb/testsuite/gdb.trace/mi-trace-frame-collected.exp new file mode 100644 index 0000000..ecfa098 --- /dev/null +++ b/gdb/testsuite/gdb.trace/mi-trace-frame-collected.exp @@ -0,0 +1,156 @@ +# Copyright 2013 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +load_lib trace-support.exp + +standard_testfile actions.c + +if { [prepare_for_testing ${testfile}.exp ${testfile} ${srcfile} {debug}] } { + return -1 +} + +if ![runto_main] { + fail "Can't run to main to check for trace support" + return -1 +} + +if ![gdb_target_supports_trace] { + unsupported "Current target does not support trace" + return -1 +} + +gdb_exit + +load_lib mi-support.exp +set MIFLAGS "-i=mi" + +if [mi_gdb_start] { + return +} +mi_run_to_main + +mi_gdb_test "-break-insert end" \ + "\\^done,bkpt=\{number=\"${decimal}\",type=\"breakpoint\".*\"\}" \ + "insert tracepoint on end" +mi_gdb_test "-break-insert -a gdb_recursion_test" \ + "\\^done,bkpt=\{number=\"${decimal}\",type=\"tracepoint\".*\"\}" \ + "insert tracepoint on gdb_recursion_test" + +mi_gdb_test "-trace-define-variable \$tsv 1" {.*\^done} \ + "-trace-define-variable" + +set pcreg "" +if [is_amd64_regs_target] { + set pcreg "rip" +} elseif [is_x86_like_target] { + set pcreg "eip" +} else { + # Other ports that support tracepoints should set the name of pc + # register here. + fail "set the name of pc register" + return -1 +} + +mi_gdb_test "-break-commands 3 \"collect gdb_char_test\" \"collect gdb_union1_test\" \"collect gdb_struct1_test.l\" \"collect gdb_arr_test\[0\]\" \"collect $${pcreg}\" \"teval \$tsv += 1\" \"collect \$tsv\" \"end\" " \ + {\^done} "set action" + +mi_gdb_test "-break-insert -a gdb_c_test" \ + "\\^done,bkpt=\{number=\"${decimal}\",type=\"tracepoint\".*\"\}" \ + "insert tracepoint on gdb_c_test" + +# Define an action. +# Collect a global variable to be sure no registers are collected +# except PC. +mi_gdb_test "-break-commands 4 \"collect gdb_char_test\" \"end\" " \ + {\^done} "set action on tracepoint 4" + +mi_gdb_test "-trace-start" {.*\^done} "trace start" +mi_send_resuming_command "exec-continue" "continuing to end" +mi_expect_stop \ + "breakpoint-hit" "end" ".*" ".*" ".*" {"" "disp=\"keep\""} \ + "stop at end" +mi_gdb_test "-trace-stop" {.*\^done,stop-reason=.*} "trace stop" + +# Save trace frames to tfile. +set tracefile [standard_output_file ${testfile}] +mi_gdb_test "-trace-save ${tracefile}.tf" ".*\\^done" \ + "save tfile trace file" +# Save trace frames to ctf. +mi_gdb_test "-trace-save -ctf ${tracefile}.ctf" ".*\\^done" \ + "save ctf trace file" + +# Test the MI command '-trace-frame-collected' with DATA_SOURCE as +# trace data source. + +proc test_trace_frame_collected { data_source } { + global decimal hex + global mi_gdb_prompt + + with_test_prefix "$data_source" { + mi_gdb_test "-trace-find frame-number 0" \ + ".*\\^done,found=\"1\",tracepoint=\"${decimal}\",traceframe=\"0\",frame=\{.*" \ + "-trace-find frame-number 0" + + # Test MI command '-trace-frame-collected' dumps only + # collected registers. + mi_gdb_test "-trace-frame-collected" \ + "\\^done,explicit-variables=\\\[\{name=\"gdb_char_test\",value=\".*\"\}\\\],computed-expressions=\\\[\\\],registers=\\\[\{number=\"$decimal\",value=\"$hex\"\}\\\],tvars=\\\[\\\],memory=\\\[\{address=\"$hex\",length=\"1\"\}\\\]"\ + "-trace-frame-collected (register)" + + mi_gdb_test "-trace-find frame-number 1" \ + ".*\\^done,found=\"1\",tracepoint=\"${decimal}\",traceframe=\"1\",frame=\{.*" \ + "-trace-find frame-number 1" + + # Test MI command '-trace-frame-collected' + mi_gdb_test "-trace-frame-collected" \ + "\\^done,explicit-variables=\\\[\{name=\"gdb_char_test\",value=\".*\"\},\{name=\"gdb_union1_test\",value=\".*\"\}\\\],computed-expressions=\\\[\{name=\"gdb_struct1_test\.l\",.*\},\{name=\"gdb_arr_test\\\[0\\\]\",.*\}\\\],registers=\\\[.*\\\],tvars=\\\[\{name=\"\\\$tsv\",current=\"2\"\}\\\],memory=\\\[\{address=\"$hex\",length=\"1\"\},.*\\\]"\ + "-trace-frame-collected" + mi_gdb_test "-trace-frame-collected --var-print-values 2 --comp-print-values --simple-values --registers-format x --memory-contents" \ + "\\^done,explicit-variables=\\\[\{name=\"gdb_char_test\",type=\"char\",value=\".*\"\},\{name=\"gdb_union1_test\",type=\"union GDB_UNION_TEST\"\}\\\],computed-expressions=\\\[.*\\\],registers=\\\[.*\\\],tvars=\\\[\{name=\"\\\$tsv\",current=\"2\"\}\\\],memory=\\\[\{address=\"$hex\",length=\"1\",contents=\".*\"\},.*\\\]" \ + "-trace-frame-collected --var-print-values 2 --comp-print-values --simple-values --registers-format x --memory-contents" + + mi_gdb_test "-trace-find none" ".*\\^done,found=\"0\".*" \ + "-trace-find none" + } +} + +test_trace_frame_collected "live" + +# Change target to ctf if GDB supports it. +set msg "-target-select ctf" +send_gdb "-target-select ctf ${tracefile}.ctf\n" +gdb_expect { + -re ".*\\^connected.*${mi_gdb_prompt}$" { + # GDB supports ctf, do the test. + test_trace_frame_collected "ctf" + } + -re ".*\\^error,msg=\"Undefined target command.*${mi_gdb_prompt}$" { + # GDB doesn't support ctf, skip the test. + unsupported "gdb does not support ctf target" + } + -re ".*$mi_gdb_prompt$" { + fail "$msg" + } + timeout { + fail "$msg (timeout)" + } +} + +# Change target to tfile. +mi_gdb_test "-target-select tfile ${tracefile}.tf" ".*\\^connected.*" \ + "-target-select tfile" +test_trace_frame_collected "tfile" + +mi_gdb_exit -- 1.7.7.6 ^ permalink raw reply [flat|nested] 36+ messages in thread
* [PATCH 1/6] Remove global variable tracepoint_list and stepping_list. 2013-06-13 1:29 ` [PATCH 0/6 V2] New MI command -trace-frame-collected Yao Qi ` (4 preceding siblings ...) 2013-06-13 1:29 ` [PATCH 6/6] New test: gdb.trace/mi-trace-frame-collected.exp Yao Qi @ 2013-06-13 2:46 ` Yao Qi 2013-06-25 15:28 ` Pedro Alves 2013-06-24 15:25 ` [ping]: [PATCH 0/6 V2] New MI command -trace-frame-collected Yao Qi 6 siblings, 1 reply; 36+ messages in thread From: Yao Qi @ 2013-06-13 2:46 UTC (permalink / raw) To: gdb-patches This patch is a refactor patch. Simply, it removes two global variables tracepoint_list and stepping_list. gdb: 2013-06-13 Pedro Alves <pedro@codesourcery.com> Yao Qi <yao@codesourcery.com> * tracepoint.c (tracepoint_list, stepping_list): Remove. (clear_collection_list): Free fields 'aexpre_list' and 'list' in collection_list. (do_clear_collection_list, init_collection_list): New. (encode_actions): Add local variables 'tracepoint_list' and 'stepping_list'. Call init_collection_list and make cleanup which calls do_clear_collection_list. Don't call clear_collection_list. (_initialize_tracepoint): Delete references to 'tracepoint_list' and 'stepping_list'. --- gdb/tracepoint.c | 67 +++++++++++++++++++++++++++++------------------------- 1 files changed, 36 insertions(+), 31 deletions(-) diff --git a/gdb/tracepoint.c b/gdb/tracepoint.c index 5bad3e8..9646090 100644 --- a/gdb/tracepoint.c +++ b/gdb/tracepoint.c @@ -873,8 +873,7 @@ struct collection_list /* True is the user requested a collection of "$_sdata", "static tracepoint data". */ int strace_data; - } -tracepoint_list, stepping_list; + }; /* MEMRANGE functions: */ @@ -1239,6 +1238,35 @@ 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; + + xfree (list->aexpr_list); + xfree (list->list); +} + +/* 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); +} + +/* Initialize collection_list CLIST. */ + +static void +init_collection_list (struct collection_list *clist) +{ + 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 *)); } /* Reduce a collection list to string form (for gdb protocol). */ @@ -1618,11 +1646,15 @@ encode_actions (struct bp_location *tloc, char ***tdp_actions, int frame_reg; LONGEST frame_offset; struct cleanup *back_to; + struct collection_list tracepoint_list, stepping_list; back_to = make_cleanup (null_cleanup, NULL); - clear_collection_list (&tracepoint_list); - clear_collection_list (&stepping_list); + 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); *tdp_actions = NULL; *stepping_actions = NULL; @@ -5673,33 +5705,6 @@ _initialize_tracepoint (void) traceframe_number = -1; tracepoint_number = -1; - if (tracepoint_list.list == NULL) - { - tracepoint_list.listsize = 128; - tracepoint_list.list = xmalloc - (tracepoint_list.listsize * sizeof (struct memrange)); - } - if (tracepoint_list.aexpr_list == NULL) - { - tracepoint_list.aexpr_listsize = 128; - tracepoint_list.aexpr_list = xmalloc - (tracepoint_list.aexpr_listsize * sizeof (struct agent_expr *)); - } - - if (stepping_list.list == NULL) - { - stepping_list.listsize = 128; - stepping_list.list = xmalloc - (stepping_list.listsize * sizeof (struct memrange)); - } - - if (stepping_list.aexpr_list == NULL) - { - stepping_list.aexpr_listsize = 128; - stepping_list.aexpr_list = xmalloc - (stepping_list.aexpr_listsize * sizeof (struct agent_expr *)); - } - add_info ("scope", scope_info, _("List the variables local to a scope")); -- 1.7.7.6 ^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PATCH 1/6] Remove global variable tracepoint_list and stepping_list. 2013-06-13 2:46 ` [PATCH 1/6] Remove global variable tracepoint_list and stepping_list Yao Qi @ 2013-06-25 15:28 ` Pedro Alves 0 siblings, 0 replies; 36+ messages in thread From: Pedro Alves @ 2013-06-25 15:28 UTC (permalink / raw) To: Yao Qi; +Cc: gdb-patches On 06/13/2013 02:28 AM, Yao Qi wrote: > This patch is a refactor patch. Simply, it removes two global > variables tracepoint_list and stepping_list. > > gdb: > > 2013-06-13 Pedro Alves <pedro@codesourcery.com> > Yao Qi <yao@codesourcery.com> > > * tracepoint.c (tracepoint_list, stepping_list): Remove. > (clear_collection_list): Free fields 'aexpre_list' and 'list' in > collection_list. > (do_clear_collection_list, init_collection_list): New. > (encode_actions): Add local variables 'tracepoint_list' and > 'stepping_list'. Call init_collection_list and make cleanup which > calls do_clear_collection_list. Don't call clear_collection_list. > (_initialize_tracepoint): Delete references to 'tracepoint_list' > and 'stepping_list'. OK, thanks. -- Pedro Alves ^ permalink raw reply [flat|nested] 36+ messages in thread
* [ping]: [PATCH 0/6 V2] New MI command -trace-frame-collected 2013-06-13 1:29 ` [PATCH 0/6 V2] New MI command -trace-frame-collected Yao Qi ` (5 preceding siblings ...) 2013-06-13 2:46 ` [PATCH 1/6] Remove global variable tracepoint_list and stepping_list Yao Qi @ 2013-06-24 15:25 ` Yao Qi 6 siblings, 0 replies; 36+ messages in thread From: Yao Qi @ 2013-06-24 15:25 UTC (permalink / raw) To: gdb-patches On 06/13/2013 09:28 AM, Yao Qi wrote: > In a given traceframe, there are explicitly collected variables, > registers, trace state variables, memories, and computed expressions. > In MI, we don't have a command to dump these contents, and this patch > adds -trace-frame-collected to do so. > > Patch 5/6 is the major part of this series, and patch 6/6 is the test > to -trace-frame-collected. GDB needs to know what trace state > variables are collected in a traceframe, so we extended the > qXfer:traceframe-info object to report the set of collected trace > state variables in the current traceframe. That is what patch 4/5 does. > Patch 1/6, 2/6 and 3/6 is code refactor. > > The whole series are tested on x86_64-linux with native and gdbserver. > > This is the V2 of this series. In V2, there are several changes: > > - Mention some changes in ChangeLog entry and correct comments. > - Split the changes on encode_actions in a different way, which is more > readable. > - Move the change from warning to error to a separate patch. > - Explain what 'tvar' element does in NEWS. > > The V1 can be found<http://sourceware.org/ml/gdb-patches/2013-06/msg00148.html> Ping. -- Yao (é½å°§) ^ permalink raw reply [flat|nested] 36+ messages in thread
end of thread, other threads:[~2013-06-26 10:57 UTC | newest] Thread overview: 36+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2013-06-07 13:07 [PATCH 0/5] New MI command -trace-frame-collected Yao Qi 2013-06-07 13:07 ` [PATCH 4/5] " Yao Qi 2013-06-07 13:07 ` [PATCH 1/5] Remove global variable tracepoint_list and stepping_list Yao Qi 2013-06-07 20:50 ` Pedro Alves 2013-06-07 13:07 ` [PATCH 3/5] Add id of TSV into traceframe_info Yao Qi 2013-06-07 14:39 ` Eli Zaretskii 2013-06-08 11:06 ` Yao Qi 2013-06-07 13:07 ` [PATCH 2/5] Move code to get_traceframe_location Yao Qi 2013-06-07 21:09 ` Pedro Alves 2013-06-07 13:07 ` [PATCH 5/5] New test: gdb.trace/mi-trace-frame-collected.exp Yao Qi 2013-06-13 1:29 ` [PATCH 0/6 V2] New MI command -trace-frame-collected Yao Qi 2013-06-13 1:29 ` [PATCH 5/6] " Yao Qi 2013-06-13 14:27 ` Eli Zaretskii 2013-06-14 9:52 ` Yao Qi 2013-06-14 12:34 ` Eli Zaretskii 2013-06-17 10:21 ` Yao Qi 2013-06-17 15:48 ` Eli Zaretskii 2013-06-18 14:09 ` Yao Qi 2013-06-18 17:24 ` Eli Zaretskii 2013-06-25 17:31 ` Pedro Alves 2013-06-26 8:29 ` Yao Qi 2013-06-26 11:22 ` Pedro Alves 2013-06-13 1:29 ` [PATCH 4/6] Add id of TSV into traceframe_info Yao Qi 2013-06-13 3:40 ` Eli Zaretskii 2013-06-25 16:18 ` Pedro Alves 2013-06-26 8:19 ` Yao Qi 2013-06-13 1:29 ` [PATCH 2/6] Emit error in tdump command when traceframe is not selected Yao Qi 2013-06-25 15:32 ` Pedro Alves 2013-06-13 1:29 ` [PATCH 3/6] Move code to get_traceframe_location Yao Qi 2013-06-25 15:43 ` Pedro Alves 2013-06-13 1:29 ` [PATCH 6/6] New test: gdb.trace/mi-trace-frame-collected.exp Yao Qi 2013-06-25 18:42 ` Pedro Alves 2013-06-26 10:32 ` Yao Qi 2013-06-13 2:46 ` [PATCH 1/6] Remove global variable tracepoint_list and stepping_list Yao Qi 2013-06-25 15:28 ` Pedro Alves 2013-06-24 15:25 ` [ping]: [PATCH 0/6 V2] New MI command -trace-frame-collected Yao Qi
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox