diff options
author | Stan Shebs <shebs@codesourcery.com> | 2011-11-02 23:44:21 +0000 |
---|---|---|
committer | Stan Shebs <shebs@codesourcery.com> | 2011-11-02 23:44:21 +0000 |
commit | 3065dfb6b4e2e605b3601c5f71fa25de5dd4970e (patch) | |
tree | ac641720c021164a841a9c669e88e599134191e6 | |
parent | 39f4f51d8bf1d516a5cca652a1d9efe8f3ef9863 (diff) | |
download | gdb-3065dfb6b4e2e605b3601c5f71fa25de5dd4970e.zip gdb-3065dfb6b4e2e605b3601c5f71fa25de5dd4970e.tar.gz gdb-3065dfb6b4e2e605b3601c5f71fa25de5dd4970e.tar.bz2 |
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.
-rw-r--r-- | gdb/ChangeLog | 24 | ||||
-rw-r--r-- | gdb/NEWS | 8 | ||||
-rw-r--r-- | gdb/ax-gdb.c | 50 | ||||
-rw-r--r-- | gdb/ax-gdb.h | 1 | ||||
-rw-r--r-- | gdb/common/ax.def | 3 | ||||
-rw-r--r-- | gdb/doc/ChangeLog | 6 | ||||
-rw-r--r-- | gdb/doc/agentexpr.texi | 5 | ||||
-rw-r--r-- | gdb/doc/gdb.texinfo | 21 | ||||
-rw-r--r-- | gdb/gdbserver/ChangeLog | 6 | ||||
-rw-r--r-- | gdb/gdbserver/server.c | 1 | ||||
-rw-r--r-- | gdb/gdbserver/tracepoint.c | 70 | ||||
-rw-r--r-- | gdb/remote.c | 24 | ||||
-rw-r--r-- | gdb/target.c | 4 | ||||
-rw-r--r-- | gdb/target.h | 6 | ||||
-rw-r--r-- | gdb/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gdb/testsuite/gdb.trace/collection.c | 16 | ||||
-rw-r--r-- | gdb/testsuite/gdb.trace/collection.exp | 50 | ||||
-rw-r--r-- | gdb/tracepoint.c | 52 | ||||
-rw-r--r-- | gdb/tracepoint.h | 3 |
19 files changed, 349 insertions, 6 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog index b4fa9a6..18f8bf7 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -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> @@ -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 diff --git a/gdb/ax-gdb.c b/gdb/ax-gdb.c index bd8800c..e59c735 100644 --- a/gdb/ax-gdb.c +++ b/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) diff --git a/gdb/ax-gdb.h b/gdb/ax-gdb.h index a25d994..951ec1f 100644 --- a/gdb/ax-gdb.h +++ b/gdb/ax-gdb.h @@ -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 */ diff --git a/gdb/common/ax.def b/gdb/common/ax.def index 5fe2ebf..d2e1b4f 100644 --- a/gdb/common/ax.def +++ b/gdb/common/ax.def @@ -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) diff --git a/gdb/doc/ChangeLog b/gdb/doc/ChangeLog index 1108974..f459be2 100644 --- a/gdb/doc/ChangeLog +++ b/gdb/doc/ChangeLog @@ -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. diff --git a/gdb/doc/agentexpr.texi b/gdb/doc/agentexpr.texi index f2d51b7..2104235 100644 --- a/gdb/doc/agentexpr.texi +++ b/gdb/doc/agentexpr.texi @@ -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 diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo index 0f37e6e..19236b3 100644 --- a/gdb/doc/gdb.texinfo +++ b/gdb/doc/gdb.texinfo @@ -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:: diff --git a/gdb/gdbserver/ChangeLog b/gdb/gdbserver/ChangeLog index e04cacc..cb2412e 100644 --- a/gdb/gdbserver/ChangeLog +++ b/gdb/gdbserver/ChangeLog @@ -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. diff --git a/gdb/gdbserver/server.c b/gdb/gdbserver/server.c index 5ba08ea..4612457 100644 --- a/gdb/gdbserver/server.c +++ b/gdb/gdbserver/server.c @@ -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; diff --git a/gdb/gdbserver/tracepoint.c b/gdb/gdbserver/tracepoint.c index eaa54f5..139e30e 100644 --- a/gdb/gdbserver/tracepoint.c +++ b/gdb/gdbserver/tracepoint.c @@ -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 diff --git a/gdb/remote.c b/gdb/remote.c index d9cc97c..5182ef1 100644 --- a/gdb/remote.c +++ b/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 diff --git a/gdb/target.c b/gdb/target.c index e6328a1..41ff6cf 100644 --- a/gdb/target.c +++ b/gdb/target.c @@ -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); diff --git a/gdb/target.h b/gdb/target.h index af7d3d9..352f2df 100644 --- a/gdb/target.h +++ b/gdb/target.h @@ -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); diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog index af1be7b..01c7705 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -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. diff --git a/gdb/testsuite/gdb.trace/collection.c b/gdb/testsuite/gdb.trace/collection.c index 6c66637..5901baf 100644 --- a/gdb/testsuite/gdb.trace/collection.c +++ b/gdb/testsuite/gdb.trace/collection.c @@ -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. */ diff --git a/gdb/testsuite/gdb.trace/collection.exp b/gdb/testsuite/gdb.trace/collection.exp index 6b73184..b1ed30a 100644 --- a/gdb/testsuite/gdb.trace/collection.exp +++ b/gdb/testsuite/gdb.trace/collection.exp @@ -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 diff --git a/gdb/tracepoint.c b/gdb/tracepoint.c index d88fcd7..4ca4ec2 100644 --- a/gdb/tracepoint.c +++ b/gdb/tracepoint.c @@ -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. */ diff --git a/gdb/tracepoint.h b/gdb/tracepoint.h index 99d8922..bf8fa44 100644 --- a/gdb/tracepoint.h +++ b/gdb/tracepoint.h @@ -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); |