Re: [PATCH 5/6] New MI command -trace-frame-collected

Yao Qi
2013-06-17T10:12:38Z

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