2011-11-02 Stan Shebs <stan@codesourcery.com>
String collection for tracepoints. * NEWS: Mention string collection. * common/ax.def (tracenz): New bytecode. * ax-gdb.h (trace_string_kludge): Declare. * ax-gdb.c: Include valprint.h and c-lang.h. (trace_string_kludge): New global. (gen_traced_pop): Add string case. (agent_command): Add string case. * tracepoint.h (decode_agent_options): Declare. * tracepoint.c: Include cli-utils.h. (decode_agent_options): New function. (validate_actionline): Call it. (encode_actions_1): Ditto. * target.h (struct target_ops): New method to_supports_string_tracing. (target_supports_string_tracing): New macro. * target.c (update_current_target): Add to_supports_string_tracing. * remote.c (struct remote_state): New field string_tracing. (remote_string_tracing_feature): New function. (remote_protocol_features): New feature tracenz. (remote_supports_string_tracing): New function. (init_remote_ops): Set to_supports_string_tracing. * tracepoint.c (agent_mem_read_string): New function. (eval_agent_expr): Call it for tracenz. * server.c (handle_query): Report support for tracenz. * gdb.texinfo (Tracepoint Action Lists): Document collect/s. (General Query Packets): Describe tracenz feature. * agentexpr.texi (Bytecode Descriptions): Describe tracenz. * gdb.trace/collection.c: Add code using strings. * gdb.trace/collection.exp: Add tests of string collection.
This commit is contained in:
parent
39f4f51d8b
commit
3065dfb6b4
@ -1,3 +1,27 @@
|
||||
2011-11-02 Stan Shebs <stan@codesourcery.com>
|
||||
|
||||
String collection for tracepoints.
|
||||
* NEWS: Mention string collection.
|
||||
* common/ax.def (tracenz): New bytecode.
|
||||
* ax-gdb.h (trace_string_kludge): Declare.
|
||||
* ax-gdb.c: Include valprint.h and c-lang.h.
|
||||
(trace_string_kludge): New global.
|
||||
(gen_traced_pop): Add string case.
|
||||
(agent_command): Add string case.
|
||||
* tracepoint.h (decode_agent_options): Declare.
|
||||
* tracepoint.c: Include cli-utils.h.
|
||||
(decode_agent_options): New function.
|
||||
(validate_actionline): Call it.
|
||||
(encode_actions_1): Ditto.
|
||||
* target.h (struct target_ops): New method to_supports_string_tracing.
|
||||
(target_supports_string_tracing): New macro.
|
||||
* target.c (update_current_target): Add to_supports_string_tracing.
|
||||
* remote.c (struct remote_state): New field string_tracing.
|
||||
(remote_string_tracing_feature): New function.
|
||||
(remote_protocol_features): New feature tracenz.
|
||||
(remote_supports_string_tracing): New function.
|
||||
(init_remote_ops): Set to_supports_string_tracing.
|
||||
|
||||
2011-11-02 Pedro Alves <pedro@codesourcery.com>
|
||||
Jan Kratochvil <jan.kratochvil@redhat.com>
|
||||
|
||||
|
8
gdb/NEWS
8
gdb/NEWS
@ -114,6 +114,14 @@ info auto-load-scripts [REGEXP]
|
||||
This command was formerly named "maintenance print section-scripts".
|
||||
It is now generally useful and is no longer a maintenance-only command.
|
||||
|
||||
collect[/s] EXPRESSIONS
|
||||
The tracepoint collect command now takes an optional modifier "/s"
|
||||
that directs it to dereference pointer-to-character types and
|
||||
collect the bytes of memory up to a zero byte. The behavior is
|
||||
similar to what you see when you use the regular print command on a
|
||||
string. An optional integer following the "/s" sets a bound on the
|
||||
number of bytes that will be collected.
|
||||
|
||||
* Tracepoints can now be enabled and disabled at any time after a trace
|
||||
experiment has been started using the standard "enable" and "disable"
|
||||
commands. It is now possible to start a trace experiment with no enabled
|
||||
|
50
gdb/ax-gdb.c
50
gdb/ax-gdb.c
@ -42,6 +42,9 @@
|
||||
#include "cp-support.h"
|
||||
#include "arch-utils.h"
|
||||
|
||||
#include "valprint.h"
|
||||
#include "c-lang.h"
|
||||
|
||||
/* To make sense of this file, you should read doc/agentexpr.texi.
|
||||
Then look at the types and enums in ax-gdb.h. For the code itself,
|
||||
look at gen_expr, towards the bottom; that's the main function that
|
||||
@ -335,6 +338,11 @@ maybe_const_expr (union exp_element **pc)
|
||||
emits the trace bytecodes at the appropriate points. */
|
||||
int trace_kludge;
|
||||
|
||||
/* Inspired by trace_kludge, this indicates that pointers to chars
|
||||
should get an added tracenz bytecode to record nonzero bytes, up to
|
||||
a length that is the value of trace_string_kludge. */
|
||||
int trace_string_kludge;
|
||||
|
||||
/* Scan for all static fields in the given class, including any base
|
||||
classes, and generate tracing bytecodes for each. */
|
||||
|
||||
@ -393,19 +401,35 @@ static void
|
||||
gen_traced_pop (struct gdbarch *gdbarch,
|
||||
struct agent_expr *ax, struct axs_value *value)
|
||||
{
|
||||
int string_trace = 0;
|
||||
if (trace_string_kludge
|
||||
&& TYPE_CODE (value->type) == TYPE_CODE_PTR
|
||||
&& c_textual_element_type (check_typedef (TYPE_TARGET_TYPE (value->type)),
|
||||
's'))
|
||||
string_trace = 1;
|
||||
|
||||
if (trace_kludge)
|
||||
switch (value->kind)
|
||||
{
|
||||
case axs_rvalue:
|
||||
/* We don't trace rvalues, just the lvalues necessary to
|
||||
produce them. So just dispose of this value. */
|
||||
ax_simple (ax, aop_pop);
|
||||
if (string_trace)
|
||||
{
|
||||
ax_const_l (ax, trace_string_kludge);
|
||||
ax_simple (ax, aop_tracenz);
|
||||
}
|
||||
else
|
||||
/* We don't trace rvalues, just the lvalues necessary to
|
||||
produce them. So just dispose of this value. */
|
||||
ax_simple (ax, aop_pop);
|
||||
break;
|
||||
|
||||
case axs_lvalue_memory:
|
||||
{
|
||||
int length = TYPE_LENGTH (check_typedef (value->type));
|
||||
|
||||
if (string_trace)
|
||||
ax_simple (ax, aop_dup);
|
||||
|
||||
/* There's no point in trying to use a trace_quick bytecode
|
||||
here, since "trace_quick SIZE pop" is three bytes, whereas
|
||||
"const8 SIZE trace" is also three bytes, does the same
|
||||
@ -413,6 +437,13 @@ gen_traced_pop (struct gdbarch *gdbarch,
|
||||
work correctly for objects with large sizes. */
|
||||
ax_const_l (ax, length);
|
||||
ax_simple (ax, aop_trace);
|
||||
|
||||
if (string_trace)
|
||||
{
|
||||
ax_simple (ax, aop_ref32);
|
||||
ax_const_l (ax, trace_string_kludge);
|
||||
ax_simple (ax, aop_tracenz);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
@ -422,6 +453,15 @@ gen_traced_pop (struct gdbarch *gdbarch,
|
||||
larger than will fit in a stack, so just mark it for
|
||||
collection and be done with it. */
|
||||
ax_reg_mask (ax, value->u.reg);
|
||||
|
||||
/* But if the register points to a string, assume the value
|
||||
will fit on the stack and push it anyway. */
|
||||
if (string_trace)
|
||||
{
|
||||
ax_reg (ax, value->u.reg);
|
||||
ax_const_l (ax, trace_string_kludge);
|
||||
ax_simple (ax, aop_tracenz);
|
||||
}
|
||||
break;
|
||||
}
|
||||
else
|
||||
@ -2489,6 +2529,10 @@ agent_command (char *exp, int from_tty)
|
||||
if (exp == 0)
|
||||
error_no_arg (_("expression to translate"));
|
||||
|
||||
trace_string_kludge = 0;
|
||||
if (*exp == '/')
|
||||
exp = decode_agent_options (exp);
|
||||
|
||||
/* Recognize the return address collection directive specially. Note
|
||||
that it is not really an expression of any sort. */
|
||||
if (strcmp (exp, "$_ret") == 0)
|
||||
|
@ -112,5 +112,6 @@ extern struct agent_expr *gen_trace_for_return_address (CORE_ADDR,
|
||||
extern struct agent_expr *gen_eval_for_expr (CORE_ADDR, struct expression *);
|
||||
|
||||
extern int trace_kludge;
|
||||
extern int trace_string_kludge;
|
||||
|
||||
#endif /* AX_GDB_H */
|
||||
|
@ -86,8 +86,7 @@ DEFOP (swap, 0, 0, 2, 2, 0x2b)
|
||||
DEFOP (getv, 2, 0, 0, 1, 0x2c)
|
||||
DEFOP (setv, 2, 0, 0, 1, 0x2d)
|
||||
DEFOP (tracev, 2, 0, 0, 1, 0x2e)
|
||||
/* We need something here just to make the tables come out ok. */
|
||||
DEFOP (invalid, 0, 0, 0, 0, 0x2f)
|
||||
DEFOP (tracenz, 0, 0, 2, 0, 0x2f)
|
||||
DEFOP (trace16, 2, 0, 1, 1, 0x30)
|
||||
/* We need something here just to make the tables come out ok. */
|
||||
DEFOP (invalid2, 0, 0, 0, 0, 0x31)
|
||||
|
@ -1,3 +1,9 @@
|
||||
2011-11-02 Stan Shebs <stan@codesourcery.com>
|
||||
|
||||
* gdb.texinfo (Tracepoint Action Lists): Document collect/s.
|
||||
(General Query Packets): Describe tracenz feature.
|
||||
* agentexpr.texi (Bytecode Descriptions): Describe tracenz.
|
||||
|
||||
2011-10-28 Paul Koning <paul_koning@dell.com>
|
||||
|
||||
* gdb.texinfo (gdb.types): Rename deepitems to deep_items.
|
||||
|
@ -489,6 +489,11 @@ named @code{trace_quick16}, for consistency.
|
||||
Record the value of trace state variable number @var{n} in the trace
|
||||
buffer. The handling of @var{n} is as described for @code{getv}.
|
||||
|
||||
@item @code{tracenz} (0x2f) @var{addr} @var{size} @result{}
|
||||
Record the bytes at @var{addr} in a trace buffer, for later retrieval
|
||||
by GDB. Stop at either the first zero byte, or when @var{size} bytes
|
||||
have been recorded, whichever occurs first.
|
||||
|
||||
@item @code{end} (0x27): @result{}
|
||||
Stop executing bytecode; the result should be the top element of the
|
||||
stack. If the purpose of the expression was to compute an lvalue or a
|
||||
|
@ -10666,7 +10666,7 @@ end
|
||||
@end smallexample
|
||||
|
||||
@kindex collect @r{(tracepoints)}
|
||||
@item collect @var{expr1}, @var{expr2}, @dots{}
|
||||
@item collect@r{[}/@var{mods}@r{]} @var{expr1}, @var{expr2}, @dots{}
|
||||
Collect values of the given expressions when the tracepoint is hit.
|
||||
This command accepts a comma-separated list of any valid expressions.
|
||||
In addition to global, static, or local variables, the following
|
||||
@ -10712,6 +10712,15 @@ You can give several consecutive @code{collect} commands, each one
|
||||
with a single argument, or one @code{collect} command with several
|
||||
arguments separated by commas; the effect is the same.
|
||||
|
||||
The optional @var{mods} changes the usual handling of the arguments.
|
||||
@code{s} requests that pointers to chars be handled as strings, in
|
||||
particular collecting the contents of the memory being pointed at, up
|
||||
to the first zero. The upper bound is by default the value of the
|
||||
@code{print elements} variable; if @code{s} is followed by a decimal
|
||||
number, that is the upper bound instead. So for instance
|
||||
@samp{collect/s25 mystr} collects as many as 25 characters at
|
||||
@samp{mystr}.
|
||||
|
||||
The command @code{info scope} (@pxref{Symbols, info scope}) is
|
||||
particularly useful for figuring out what data to collect.
|
||||
|
||||
@ -34707,6 +34716,11 @@ These are the currently defined stub features and their properties:
|
||||
@tab @samp{-}
|
||||
@tab No
|
||||
|
||||
@item @samp{tracenz}
|
||||
@tab No
|
||||
@tab @samp{-}
|
||||
@tab No
|
||||
|
||||
@end multitable
|
||||
|
||||
These are the currently defined stub features, in more detail:
|
||||
@ -34831,6 +34845,11 @@ The remote stub supports the @samp{QTEnable} (@pxref{QTEnable}) and
|
||||
@samp{QTDisable} (@pxref{QTDisable}) packets that allow tracepoints
|
||||
to be enabled and disabled while a trace experiment is running.
|
||||
|
||||
@item tracenz
|
||||
@cindex string tracing, in remote protocol
|
||||
The remote stub supports the @samp{tracenz} bytecode for collecting strings.
|
||||
See @ref{Bytecode Descriptions} for details about the bytecode.
|
||||
|
||||
@end table
|
||||
|
||||
@item qSymbol::
|
||||
|
@ -1,3 +1,9 @@
|
||||
2011-11-02 Stan Shebs <stan@codesourcery.com>
|
||||
|
||||
* tracepoint.c (agent_mem_read_string): New function.
|
||||
(eval_agent_expr): Call it for tracenz.
|
||||
* server.c (handle_query): Report support for tracenz.
|
||||
|
||||
2011-11-02 Yao Qi <yao@codesourcery.com>
|
||||
|
||||
* tracepoint.c (cmd_qtstart): Remove unused local variables.
|
||||
|
@ -1587,6 +1587,7 @@ handle_query (char *own_buf, int packet_len, int *new_packet_len_p)
|
||||
strcat (own_buf, ";qXfer:statictrace:read+");
|
||||
strcat (own_buf, ";qXfer:traceframe-info:read+");
|
||||
strcat (own_buf, ";EnableDisableTracepoints+");
|
||||
strcat (own_buf, ";tracenz+");
|
||||
}
|
||||
|
||||
return;
|
||||
|
@ -1209,6 +1209,9 @@ static enum eval_result_type eval_agent_expr (struct tracepoint_hit_ctx *ctx,
|
||||
|
||||
static int agent_mem_read (struct traceframe *tframe,
|
||||
unsigned char *to, CORE_ADDR from, ULONGEST len);
|
||||
static int agent_mem_read_string (struct traceframe *tframe,
|
||||
unsigned char *to, CORE_ADDR from,
|
||||
ULONGEST len);
|
||||
static int agent_tsv_read (struct traceframe *tframe, int n);
|
||||
|
||||
#ifndef IN_PROCESS_AGENT
|
||||
@ -4644,6 +4647,13 @@ eval_agent_expr (struct tracepoint_hit_ctx *ctx,
|
||||
agent_tsv_read (tframe, arg);
|
||||
break;
|
||||
|
||||
case gdb_agent_op_tracenz:
|
||||
agent_mem_read_string (tframe, NULL, (CORE_ADDR) stack[--sp],
|
||||
(ULONGEST) top);
|
||||
if (--sp >= 0)
|
||||
top = stack[sp];
|
||||
break;
|
||||
|
||||
/* GDB never (currently) generates any of these ops. */
|
||||
case gdb_agent_op_float:
|
||||
case gdb_agent_op_ref_float:
|
||||
@ -4727,6 +4737,66 @@ agent_mem_read (struct traceframe *tframe,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
agent_mem_read_string (struct traceframe *tframe,
|
||||
unsigned char *to, CORE_ADDR from, ULONGEST len)
|
||||
{
|
||||
unsigned char *buf, *mspace;
|
||||
ULONGEST remaining = len;
|
||||
unsigned short blocklen, i;
|
||||
|
||||
/* To save a bit of space, block lengths are 16-bit, so break large
|
||||
requests into multiple blocks. Bordering on overkill for strings,
|
||||
but it could happen that someone specifies a large max length. */
|
||||
while (remaining > 0)
|
||||
{
|
||||
size_t sp;
|
||||
|
||||
blocklen = (remaining > 65535 ? 65535 : remaining);
|
||||
/* We want working space to accumulate nonzero bytes, since
|
||||
traceframes must have a predecided size (otherwise it gets
|
||||
harder to wrap correctly for the circular case, etc). */
|
||||
buf = (unsigned char *) xmalloc (blocklen + 1);
|
||||
for (i = 0; i < blocklen; ++i)
|
||||
{
|
||||
/* Read the string one byte at a time, in case the string is
|
||||
at the end of a valid memory area - we don't want a
|
||||
correctly-terminated string to engender segvio
|
||||
complaints. */
|
||||
read_inferior_memory (from + i, buf + i, 1);
|
||||
|
||||
if (buf[i] == '\0')
|
||||
{
|
||||
blocklen = i + 1;
|
||||
/* Make sure outer loop stops now too. */
|
||||
remaining = blocklen;
|
||||
break;
|
||||
}
|
||||
}
|
||||
sp = 1 + sizeof (from) + sizeof (blocklen) + blocklen;
|
||||
mspace = add_traceframe_block (tframe, sp);
|
||||
if (mspace == NULL)
|
||||
{
|
||||
xfree (buf);
|
||||
return 1;
|
||||
}
|
||||
/* Identify block as a memory block. */
|
||||
*mspace = 'M';
|
||||
++mspace;
|
||||
/* Record address and size. */
|
||||
memcpy ((void *) mspace, (void *) &from, sizeof (from));
|
||||
mspace += sizeof (from);
|
||||
memcpy ((void *) mspace, (void *) &blocklen, sizeof (blocklen));
|
||||
mspace += sizeof (blocklen);
|
||||
/* Copy the string contents. */
|
||||
memcpy ((void *) mspace, (void *) buf, blocklen);
|
||||
remaining -= blocklen;
|
||||
from += blocklen;
|
||||
xfree (buf);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Record the value of a trace state variable. */
|
||||
|
||||
static int
|
||||
|
24
gdb/remote.c
24
gdb/remote.c
@ -331,6 +331,9 @@ struct remote_state
|
||||
tracepoints while a trace experiment is running. */
|
||||
int enable_disable_tracepoints;
|
||||
|
||||
/* True if the stub can collect strings using tracenz bytecode. */
|
||||
int string_tracing;
|
||||
|
||||
/* Nonzero if the user has pressed Ctrl-C, but the target hasn't
|
||||
responded to that. */
|
||||
int ctrlc_pending_p;
|
||||
@ -3712,6 +3715,16 @@ remote_enable_disable_tracepoint_feature (const struct protocol_feature *feature
|
||||
rs->enable_disable_tracepoints = (support == PACKET_ENABLE);
|
||||
}
|
||||
|
||||
static void
|
||||
remote_string_tracing_feature (const struct protocol_feature *feature,
|
||||
enum packet_support support,
|
||||
const char *value)
|
||||
{
|
||||
struct remote_state *rs = get_remote_state ();
|
||||
|
||||
rs->string_tracing = (support == PACKET_ENABLE);
|
||||
}
|
||||
|
||||
static struct protocol_feature remote_protocol_features[] = {
|
||||
{ "PacketSize", PACKET_DISABLE, remote_packet_size, -1 },
|
||||
{ "qXfer:auxv:read", PACKET_DISABLE, remote_supported_packet,
|
||||
@ -3764,6 +3777,8 @@ static struct protocol_feature remote_protocol_features[] = {
|
||||
PACKET_qXfer_fdpic },
|
||||
{ "QDisableRandomization", PACKET_DISABLE, remote_supported_packet,
|
||||
PACKET_QDisableRandomization },
|
||||
{ "tracenz", PACKET_DISABLE,
|
||||
remote_string_tracing_feature, -1 },
|
||||
};
|
||||
|
||||
static char *remote_support_xml;
|
||||
@ -9740,6 +9755,14 @@ remote_supports_enable_disable_tracepoint (void)
|
||||
return rs->enable_disable_tracepoints;
|
||||
}
|
||||
|
||||
static int
|
||||
remote_supports_string_tracing (void)
|
||||
{
|
||||
struct remote_state *rs = get_remote_state ();
|
||||
|
||||
return rs->string_tracing;
|
||||
}
|
||||
|
||||
static void
|
||||
remote_trace_init (void)
|
||||
{
|
||||
@ -10459,6 +10482,7 @@ Specify the serial device it is connected to\n\
|
||||
remote_ops.to_supports_disable_randomization
|
||||
= remote_supports_disable_randomization;
|
||||
remote_ops.to_supports_enable_disable_tracepoint = remote_supports_enable_disable_tracepoint;
|
||||
remote_ops.to_supports_string_tracing = remote_supports_string_tracing;
|
||||
remote_ops.to_trace_init = remote_trace_init;
|
||||
remote_ops.to_download_tracepoint = remote_download_tracepoint;
|
||||
remote_ops.to_download_trace_state_variable
|
||||
|
@ -672,6 +672,7 @@ update_current_target (void)
|
||||
/* Do not inherit to_search_memory. */
|
||||
INHERIT (to_supports_multi_process, t);
|
||||
INHERIT (to_supports_enable_disable_tracepoint, t);
|
||||
INHERIT (to_supports_string_tracing, t);
|
||||
INHERIT (to_trace_init, t);
|
||||
INHERIT (to_download_tracepoint, t);
|
||||
INHERIT (to_download_trace_state_variable, t);
|
||||
@ -840,6 +841,9 @@ update_current_target (void)
|
||||
de_fault (to_supports_enable_disable_tracepoint,
|
||||
(int (*) (void))
|
||||
return_zero);
|
||||
de_fault (to_supports_string_tracing,
|
||||
(int (*) (void))
|
||||
return_zero);
|
||||
de_fault (to_trace_init,
|
||||
(void (*) (void))
|
||||
tcomplain);
|
||||
|
@ -659,6 +659,9 @@ struct target_ops
|
||||
/* Does this target support disabling address space randomization? */
|
||||
int (*to_supports_disable_randomization) (void);
|
||||
|
||||
/* Does this target support the tracenz bytecode for string collection? */
|
||||
int (*to_supports_string_tracing) (void);
|
||||
|
||||
/* Determine current architecture of thread PTID.
|
||||
|
||||
The target is supposed to determine the architecture of the code where
|
||||
@ -904,6 +907,9 @@ int target_supports_disable_randomization (void);
|
||||
#define target_supports_enable_disable_tracepoint() \
|
||||
(*current_target.to_supports_enable_disable_tracepoint) ()
|
||||
|
||||
#define target_supports_string_tracing() \
|
||||
(*current_target.to_supports_string_tracing) ()
|
||||
|
||||
/* Invalidate all target dcaches. */
|
||||
extern void target_dcache_invalidate (void);
|
||||
|
||||
|
@ -1,3 +1,8 @@
|
||||
2011-11-02 Stan Shebs <stan@codesourcery.com>
|
||||
|
||||
* gdb.trace/collection.c: Add code using strings.
|
||||
* gdb.trace/collection.exp: Add tests of string collection.
|
||||
|
||||
2011-11-02 Jan Kratochvil <jan.kratochvil@redhat.com>
|
||||
|
||||
* gdb.base/skip-solib.exp (executable_main): New variable.
|
||||
|
@ -201,6 +201,21 @@ int globals_test_func ()
|
||||
return i; /* Set_Tracepoint_Here */
|
||||
}
|
||||
|
||||
int strings_test_func ()
|
||||
{
|
||||
int i = 0;
|
||||
char *locstr, *longloc;
|
||||
|
||||
locstr = "abcdef";
|
||||
longloc = malloc(500);
|
||||
strcpy(longloc, "how now brown cow spam spam spam wonderful wonderful spam");
|
||||
|
||||
i += strlen (locstr);
|
||||
i += strlen (longloc);
|
||||
|
||||
return i; /* Set_Tracepoint_Here */
|
||||
}
|
||||
|
||||
int
|
||||
main (argc, argv, envp)
|
||||
int argc;
|
||||
@ -263,6 +278,7 @@ main (argc, argv, envp)
|
||||
i += reglocal_test_func ();
|
||||
i += statlocal_test_func ();
|
||||
i += globals_test_func ();
|
||||
i += strings_test_func ();
|
||||
|
||||
/* Values of globals at end of test should be different from
|
||||
values that they had when trace data was captured. */
|
||||
|
@ -619,6 +619,49 @@ proc gdb_collect_return_test { } {
|
||||
"collect \$_ret: cease trace debugging"
|
||||
}
|
||||
|
||||
proc gdb_collect_strings_test { func mystr myrslt mylim msg } {
|
||||
global hex
|
||||
global cr
|
||||
global gdb_prompt
|
||||
|
||||
prepare_for_trace_test
|
||||
|
||||
# Find the comment-identified line for setting this tracepoint.
|
||||
set testline 0
|
||||
gdb_test_multiple "list $func, +30" "collect $msg: find tracepoint line" {
|
||||
-re "\[\r\n\](\[0-9\]+)\[^\r\n\]+ Set_Tracepoint_Here .*$gdb_prompt" {
|
||||
set testline $expect_out(1,string)
|
||||
pass "collect $msg: find tracepoint line"
|
||||
}
|
||||
-re ".*$gdb_prompt " {
|
||||
fail "collect $msg: find tracepoint line (skipping strings test)"
|
||||
return
|
||||
}
|
||||
timeout {
|
||||
fail "collect $msg: find tracepoint line (skipping strings test)"
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
gdb_test "trace $testline" \
|
||||
"Tracepoint \[0-9\]+ at .*" \
|
||||
"collect $msg: set tracepoint"
|
||||
gdb_trace_setactions "collect $msg: define actions" \
|
||||
"" \
|
||||
"collect/s$mylim $mystr" "^$"
|
||||
|
||||
# Begin the test.
|
||||
run_trace_experiment $msg $func
|
||||
|
||||
gdb_test "print $mystr" \
|
||||
"\\$\[0-9\]+ = $hex \"$myrslt\".*$cr" \
|
||||
"collect $msg: collected local string"
|
||||
|
||||
gdb_test "tfind none" \
|
||||
"#0 end .*" \
|
||||
"collect $msg: cease trace debugging"
|
||||
}
|
||||
|
||||
proc gdb_trace_collection_test {} {
|
||||
global fpreg
|
||||
global spreg
|
||||
@ -728,6 +771,13 @@ proc gdb_trace_collection_test {} {
|
||||
"globalarr\[\(l6, l7\)\]" "7" "a\[\(b, c\)\]"
|
||||
|
||||
gdb_collect_return_test
|
||||
|
||||
gdb_collect_strings_test strings_test_func "locstr" "abcdef" "" \
|
||||
"local string"
|
||||
|
||||
gdb_collect_strings_test strings_test_func "longloc" "how now brown c" 15 \
|
||||
"long local string"
|
||||
|
||||
}
|
||||
|
||||
clean_restart $executable
|
||||
|
@ -52,6 +52,7 @@
|
||||
#include "ax-gdb.h"
|
||||
#include "memrange.h"
|
||||
#include "exceptions.h"
|
||||
#include "cli/cli-utils.h"
|
||||
|
||||
/* readline include files */
|
||||
#include "readline/readline.h"
|
||||
@ -574,6 +575,46 @@ teval_pseudocommand (char *args, int from_tty)
|
||||
error (_("This command can only be used in a tracepoint actions list."));
|
||||
}
|
||||
|
||||
/* Parse any collection options, such as /s for strings. */
|
||||
|
||||
char *
|
||||
decode_agent_options (char *exp)
|
||||
{
|
||||
struct value_print_options opts;
|
||||
|
||||
if (*exp != '/')
|
||||
return exp;
|
||||
|
||||
/* Call this to borrow the print elements default for collection
|
||||
size. */
|
||||
get_user_print_options (&opts);
|
||||
|
||||
exp++;
|
||||
if (*exp == 's')
|
||||
{
|
||||
if (target_supports_string_tracing ())
|
||||
{
|
||||
/* Allow an optional decimal number giving an explicit maximum
|
||||
string length, defaulting it to the "print elements" value;
|
||||
so "collect/s80 mystr" gets at most 80 bytes of string. */
|
||||
trace_string_kludge = opts.print_max;
|
||||
exp++;
|
||||
if (*exp >= '0' && *exp <= '9')
|
||||
trace_string_kludge = atoi (exp);
|
||||
while (*exp >= '0' && *exp <= '9')
|
||||
exp++;
|
||||
}
|
||||
else
|
||||
error (_("Target does not support \"/s\" option for string tracing."));
|
||||
}
|
||||
else
|
||||
error (_("Undefined collection format \"%c\"."), *exp);
|
||||
|
||||
exp = skip_spaces (exp);
|
||||
|
||||
return exp;
|
||||
}
|
||||
|
||||
/* Enter a list of actions for a tracepoint. */
|
||||
static void
|
||||
trace_actions_command (char *args, int from_tty)
|
||||
@ -656,6 +697,10 @@ validate_actionline (char **line, struct breakpoint *b)
|
||||
|
||||
if (cmd_cfunc_eq (c, collect_pseudocommand))
|
||||
{
|
||||
trace_string_kludge = 0;
|
||||
if (*p == '/')
|
||||
p = decode_agent_options (p);
|
||||
|
||||
do
|
||||
{ /* Repeat over a comma-separated list. */
|
||||
QUIT; /* Allow user to bail out with ^C. */
|
||||
@ -1313,6 +1358,10 @@ encode_actions_1 (struct command_line *action,
|
||||
|
||||
if (cmd_cfunc_eq (cmd, collect_pseudocommand))
|
||||
{
|
||||
trace_string_kludge = 0;
|
||||
if (*action_exp == '/')
|
||||
action_exp = decode_agent_options (action_exp);
|
||||
|
||||
do
|
||||
{ /* Repeat over a comma-separated list. */
|
||||
QUIT; /* Allow user to bail out with ^C. */
|
||||
@ -2581,6 +2630,9 @@ trace_dump_actions (struct command_line *action,
|
||||
STEPPING_ACTIONS should be equal. */
|
||||
if (stepping_frame == stepping_actions)
|
||||
{
|
||||
if (*action_exp == '/')
|
||||
action_exp = decode_agent_options (action_exp);
|
||||
|
||||
do
|
||||
{ /* Repeat over a comma-separated list. */
|
||||
QUIT; /* Allow user to bail out with ^C. */
|
||||
|
@ -212,6 +212,9 @@ struct cleanup *make_cleanup_restore_current_traceframe (void);
|
||||
struct cleanup *make_cleanup_restore_traceframe_number (void);
|
||||
|
||||
void free_actions (struct breakpoint *);
|
||||
|
||||
extern char *decode_agent_options (char *exp);
|
||||
|
||||
extern void validate_actionline (char **, struct breakpoint *);
|
||||
|
||||
extern void end_actions_pseudocommand (char *args, int from_tty);
|
||||
|
Loading…
x
Reference in New Issue
Block a user