2011-11-02 Stan Shebs <stan@codesourcery.com>
authorStan Shebs <shebs@codesourcery.com>
Wed, 2 Nov 2011 23:44:21 +0000 (23:44 +0000)
committerStan Shebs <shebs@codesourcery.com>
Wed, 2 Nov 2011 23:44:21 +0000 (23:44 +0000)
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.

19 files changed:
gdb/ChangeLog
gdb/NEWS
gdb/ax-gdb.c
gdb/ax-gdb.h
gdb/common/ax.def
gdb/doc/ChangeLog
gdb/doc/agentexpr.texi
gdb/doc/gdb.texinfo
gdb/gdbserver/ChangeLog
gdb/gdbserver/server.c
gdb/gdbserver/tracepoint.c
gdb/remote.c
gdb/target.c
gdb/target.h
gdb/testsuite/ChangeLog
gdb/testsuite/gdb.trace/collection.c
gdb/testsuite/gdb.trace/collection.exp
gdb/tracepoint.c
gdb/tracepoint.h

index b4fa9a60c68dc5b9b0298c6032ae93dddc942394..18f8bf7869060d79f24f548fb4a54ad27a6a1fad 100644 (file)
@@ -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>
 
index 9a27b646e25a89851908107558095b04b5eba8c0..1713049aa51a1c5d835499ce8b1aea9573546424 100644 (file)
--- a/gdb/NEWS
+++ b/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
index bd8800c60c5a64a68a800e346a5939d7987c3eec..e59c73541c99824f510c4575d46ff480d41d18fa 100644 (file)
@@ -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)
index a25d994754147d40e33d46541a1141559d5a1458..951ec1fbaf23a48422df5d826a6ca4cdb14e5ca4 100644 (file)
@@ -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 */
index 5fe2ebfdd2557ed06bbc64febbb92d2b711e6550..d2e1b4fa097691f06e80696b706fc5327c06714d 100644 (file)
@@ -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)
index 1108974f7836ece5b791fcf44dc4dde852b26d59..f459be267e041498c9c7a36f0f7425fa47e86a71 100644 (file)
@@ -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.
index f2d51b740531d5a5f0c544fda68bb9d09f50acd1..21042351ebb948b8999727be8fc7d93a4e47abc0 100644 (file)
@@ -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
index 0f37e6eac1c63669556f4dab7bea4125374aec4c..19236b3e785766321c39529ac57f72636fbbc291 100644 (file)
@@ -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::
index e04cacc2a5a1441ce1860e56b5fc34784e06d069..cb2412e405a841742526c32e9105de5cec23bd7a 100644 (file)
@@ -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.
index 5ba08eada6ee8c54f44bc5d1c2911fe8cebb726d..4612457ed7ef02763450adf47004a1e1659e706e 100644 (file)
@@ -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;
index eaa54f520d0f2efddb8c31703ed29fecbdeecf2a..139e30e0141817a8cb31274bbad82697348eccea 100644 (file)
@@ -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
index d9cc97c468e07896947b98ade093188c98ba459f..5182ef1ae59db673c7873ccc358e3b7b65bc4d15 100644 (file)
@@ -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
index e6328a1225887d399a330b13d9f11aeccd37c643..41ff6cfc873960b3c8cfbfa6a5918df8bbaea363 100644 (file)
@@ -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);
index af7d3d9e5befa90ab717e8be52674655ebee41d1..352f2df5b1d6601195d292d6aeafedfc84ed1eac 100644 (file)
@@ -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);
 
index af1be7b1b16825fb545cbb1f8a91124947bd5244..01c7705ec528c15e1e90182153d7278cadd09153 100644 (file)
@@ -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.
index 6c666374fbbca7ddcfffc7af5ba2b3210f2c1882..5901baf03954152d68d86fb98c8ca1f347bc6187 100644 (file)
@@ -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.  */
index 6b731841f8cfe6dffa53c2db8cfb914b3abc9880..b1ed30a8bea8cee53275f47148733eca425d2e2b 100644 (file)
@@ -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
index d88fcd7c9950187f95ab9f5513b783a1836dbc4a..4ca4ec2a1d572663164aaa9a1f79168e3a78dfc3 100644 (file)
@@ -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.  */
index 99d89222aab7417ffe8bc5a9591d52f33a746dd8..bf8fa443b43fcb5f3a7c7d80240ff7514ad940b9 100644 (file)
@@ -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);