2010-03-25 Stan Shebs <stan@codesourcery.com>
authorStan Shebs <shebs@codesourcery.com>
Fri, 26 Mar 2010 01:46:29 +0000 (01:46 +0000)
committerStan Shebs <shebs@codesourcery.com>
Fri, 26 Mar 2010 01:46:29 +0000 (01:46 +0000)
* tracepoint.h (trace_stop_reason): Add tracepoint_error.
(struct trace_status): New field error_desc.
* tracepoint.c (stop_reason_names): Add terror.
(current_trace_status): Ensure non-NULL error description.
(trace_status_command): Add error report.
(trace_status_mi): Ditto.
(trace_save): Add special case for error description.
(parse_trace_status): Add case for errors.

* gdb.texinfo (Tracepoint Packets): Document trace error status.

* gdb.trace/tfile.c: Generate an additional trace file, improve
portability.
* gdb.trace/tfile.exp: Test trace file with an error stop, delete
files in a better way.

gdb/ChangeLog
gdb/doc/ChangeLog
gdb/doc/gdb.texinfo
gdb/testsuite/ChangeLog
gdb/testsuite/gdb.trace/tfile.c
gdb/testsuite/gdb.trace/tfile.exp
gdb/tracepoint.c
gdb/tracepoint.h

index 3bf68362309975b51074083eaaf88de2b8d13fab..6dff8952be6e96e6aa674b179397f7a11227986e 100644 (file)
@@ -1,3 +1,14 @@
+2010-03-25  Stan Shebs  <stan@codesourcery.com>
+
+       * tracepoint.h (trace_stop_reason): Add tracepoint_error.
+       (struct trace_status): New field error_desc.
+       * tracepoint.c (stop_reason_names): Add terror.
+       (current_trace_status): Ensure non-NULL error description.
+       (trace_status_command): Add error report.
+       (trace_status_mi): Ditto.
+       (trace_save): Add special case for error description.
+       (parse_trace_status): Add case for errors.
+
 2010-03-25  Keith Seitz  <keiths@redhat.com>
 
        * dwarf2read.c (read_subroutine_type): If the compilation unit
index d99937aefb7992fba66da42019853fe6a99fc180..dfb8a8d5d43fbcbcbf93b0341fe55b66a964b35f 100644 (file)
@@ -1,3 +1,7 @@
+2010-03-24  Stan Shebs  <stan@codesourcery.com>
+
+       * gdb.texinfo (Tracepoint Packets): Document trace error status.
+
 2010-03-24  Tom Tromey  <tromey@redhat.com>
 
        PR breakpoints/9352:
index 369556d6569f0a6591ee77e36100501a638d4651..3c7d669b31962c81f0c07efe34c8a093cfcdbc2d 100644 (file)
@@ -31362,6 +31362,15 @@ The trace stopped because @value{GDBN} disconnected from the target.
 @item tpasscount:@var{tpnum}
 The trace stopped because tracepoint @var{tpnum} exceeded its pass count.
 
+@item terror:@var{text}:@var{tpnum}
+The trace stopped because tracepoint @var{tpnum} had an error.  The
+string @var{text} is available to describe the nature of the error
+(for instance, a divide by zero in the condition expression).
+@var{text} may take either of two forms; it may be plain text, but
+with the restriction that no colons or other special characters are
+allowed, or it may be an @code{X} followed by hex digits encoding the
+text string.
+
 @item tunknown:0
 The trace stopped for some other reason.
 
index 3ee9fb5fbe5f3eb2fd49aec7e8ef4d6a314942ad..3800958806f1685a3e16b8f0b1bc1098ed80bb31 100644 (file)
@@ -1,3 +1,10 @@
+2010-03-25  Stan Shebs  <stan@codesourcery.com>
+
+       * gdb.trace/tfile.c: Generate an additional trace file, improve
+       portability.
+       * gdb.trace/tfile.exp: Test trace file with an error stop, delete
+       files in a better way.
+
 2010-03-25  Keith Seitz  <keiths@redhat.com>
 
        * gdb.java/jprint.exp: XFAIL printing of static class members
index 9ffc37164aaee15e7f1d163610095275c041cae2..5d4c797e94aba2410285692212e2712b2eb47f44 100644 (file)
@@ -41,9 +41,11 @@ finish_trace_file (int fd)
 }
 
 void
-write_basic_trace_file ()
+write_basic_trace_file (void)
 {
-  int fd;
+  int fd, int_x;
+  short short_x;
+  long long ll_x;
 
   fd = start_trace_file ("basic.tf");
 
@@ -61,6 +63,7 @@ write_basic_trace_file ()
 
   /* Dump tracepoint definitions, in syntax similar to that used
      for reconnection uploads.  */
+  /* FIXME need a portable way to print function address in hex */
   snprintf (spbuf, sizeof spbuf, "tp T1:%lx:E:0:0\n",
            (long) &write_basic_trace_file);
   write (fd, spbuf, strlen (spbuf));
@@ -71,28 +74,73 @@ write_basic_trace_file ()
   write (fd, "\n", 1);
 
   /* Make up a simulated trace buffer.  */
-  /* (Encapsulate better if we're going to do lots of this.) */
+  /* (Encapsulate better if we're going to do lots of this; note that
+     buffer endianness is the target program's enddianness.) */
   trptr = trbuf;
-  *((short *) trptr) = 1;
-  trptr += sizeof (short);
+  short_x = 1;
+  memcpy (trptr, &short_x, 2);
+  trptr += 2;
   tfsizeptr = trptr;
-  trptr += sizeof (int);
+  trptr += 4;
   *((char *) trptr) = 'M';
   trptr += 1;
-  *((long long *) trptr) = (long) &testglob;
+  ll_x = (long) &testglob;
+  memcpy (trptr, &ll_x, sizeof (long long));
   trptr += sizeof (long long);
-  *((short *) trptr) = sizeof (testglob);
-  trptr += sizeof (short);
-  *((int *) trptr) = testglob;
+  short_x = sizeof (testglob);
+  memcpy (trptr, &short_x, 2);
+  trptr += 2;
+  memcpy (trptr, &testglob, sizeof (testglob));
   trptr += sizeof (testglob);
   /* Go back and patch in the frame size.  */
-  *((int *) tfsizeptr) = trptr - tfsizeptr - sizeof (int);
+  int_x = trptr - tfsizeptr - sizeof (int);
+  memcpy (tfsizeptr, &int_x, 4);
+
+  /* Write end of tracebuffer marker.  */
+  memset (trptr, 0, 6);
+  trptr += 6;
+
+  write (fd, trbuf, trptr - trbuf);
+
+  finish_trace_file (fd);
+}
+
+void
+write_error_trace_file (void)
+{
+  int fd;
+
+  fd = start_trace_file ("error.tf");
+
+  /* The next part of the file consists of newline-separated lines
+     defining status, tracepoints, etc.  The section is terminated by
+     an empty line.  */
+
+  /* Dump the size of the R (register) blocks in traceframes.  */
+  snprintf (spbuf, sizeof spbuf, "R %x\n", 500 /* FIXME get from arch */);
+  write (fd, spbuf, strlen (spbuf));
+
+  /* Dump trace status, in the general form of the qTstatus reply.  */
+  snprintf (spbuf, sizeof spbuf, "status 0;terror:made-up error:1;tframes:0;tcreated:0;tfree:100;tsize:1000\n");
+  write (fd, spbuf, strlen (spbuf));
+
+  /* Dump tracepoint definitions, in syntax similar to that used
+     for reconnection uploads.  */
+  /* FIXME need a portable way to print function address in hex */
+  snprintf (spbuf, sizeof spbuf, "tp T1:%lx:E:0:0\n",
+           (long) &write_basic_trace_file);
+  write (fd, spbuf, strlen (spbuf));
+  /* (Note that we would only need actions defined if we wanted to
+     test tdump.) */
+
+  /* Empty line marks the end of the definition section.  */
+  write (fd, "\n", 1);
+
+  trptr = trbuf;
 
   /* Write end of tracebuffer marker.  */
-  *((short *) trptr) = 0;
-  trptr += sizeof (short);
-  *((int *) trptr) = 0;
-  trptr += sizeof (int);
+  memset (trptr, 0, 6);
+  trptr += 6;
 
   write (fd, trbuf, trptr - trbuf);
 
@@ -109,6 +157,8 @@ main (int argc, char **argv, char **envp)
 {
   write_basic_trace_file ();
 
+  write_error_trace_file ();
+
   done_making_trace_files ();
 
   return 0;
index 20af854d1ce16a2833c4adeca9993492c885381b..a3adfcc0370bb42b864875549f52d8e52d3d3c3a 100644 (file)
@@ -47,7 +47,8 @@ if { [gdb_compile "$srcdir/$subdir/$srcfile" $binfile \
 gdb_reinitialize_dir $srcdir/$subdir
 
 # Make sure we are starting fresh.
-remote_exec build {sh -xc rm\ -f\ basic.tf}
+remote_file host delete basic.tf
+remote_file host delete error.tf
 
 gdb_load $binfile
 
@@ -83,7 +84,19 @@ Trace buffer has 256 bytes of 4096 bytes free \\(93% full\\).*
 Looking at trace frame 0, tracepoint .*" \
     "tstatus on trace file"
 
+# Now start afresh, using only a trace file.
 
+gdb_exit
+gdb_start
 
+gdb_load $binfile
 
+gdb_test "target tfile error.tf" "Created tracepoint.*" "target tfile"
 
+gdb_test "tstatus" \
+    "Using a trace file.*
+Trace stopped by an error \\(made-up error, tracepoint 1\\).*
+Collected 0 trace frame.*
+Trace buffer has 256 bytes of 4096 bytes free \\(93% full\\).*
+Not looking at any trace frame.*" \
+    "tstatus on error trace file"
index d3cccffe26870a8cbfc66898feccd84640b87729..447682a86868c1b376e9fa8903d917e0fa61960f 100644 (file)
@@ -195,12 +195,16 @@ char *stop_reason_names[] = {
   "tstop",
   "tfull",
   "tdisconnected",
-  "tpasscount"
+  "tpasscount",
+  "terror"
 };
 
 struct trace_status *
 current_trace_status ()
 {
+  /* Ensure this is never NULL.  */
+  if (!trace_status.error_desc)
+    trace_status.error_desc = "";
   return &trace_status;
 }
 
@@ -1570,6 +1574,14 @@ trace_status_command (char *args, int from_tty)
          printf_filtered (_("Trace stopped by tracepoint %d.\n"),
                           ts->stopping_tracepoint);
          break;
+       case tracepoint_error:
+         if (ts->stopping_tracepoint)
+           printf_filtered (_("Trace stopped by an error (%s, tracepoint %d).\n"),
+                            ts->error_desc, ts->stopping_tracepoint);
+         else
+           printf_filtered (_("Trace stopped by an error (%s).\n"),
+                            ts->error_desc);
+         break;
        case trace_stop_reason_unknown:
          printf_filtered (_("Trace stopped for an unknown reason.\n"));
          break;
@@ -1684,6 +1696,10 @@ trace_status_mi (int on_stop)
              stop_reason = "passcount";
              stopping_tracepoint = ts->stopping_tracepoint;
              break;
+           case tracepoint_error:
+             stop_reason = "error";
+             stopping_tracepoint = ts->stopping_tracepoint;
+             break;
            }
          
          if (stop_reason)
@@ -1692,6 +1708,9 @@ trace_status_mi (int on_stop)
              if (stopping_tracepoint != -1)
                ui_out_field_int (uiout, "stopping-tracepoint",
                                  stopping_tracepoint);
+             if (ts->stop_reason == tracepoint_error)
+               ui_out_field_string (uiout, "error-description",
+                                    ts->error_desc);
            }
        }
     }
@@ -2463,9 +2482,16 @@ trace_save (const char *filename, int target_does_save)
   fprintf (fp, "R %x\n", trace_regblock_size);
 
   /* Write out status of the tracing run (aka "tstatus" info).  */
-  fprintf (fp, "status %c;%s:%x",
-          (ts->running ? '1' : '0'),
-          stop_reason_names[ts->stop_reason], ts->stopping_tracepoint);
+  fprintf (fp, "status %c;%s",
+          (ts->running ? '1' : '0'), stop_reason_names[ts->stop_reason]);
+  /* Encode the error message in hex, might have weird chars.  */
+  if (ts->stop_reason == tracepoint_error)
+    {
+      char *buf = (char *) alloca (strlen (ts->error_desc) * 2 + 1);
+      bin2hex ((gdb_byte *) ts->error_desc, buf, 0);
+      fprintf (fp, ":X%s", buf);
+    }
+  fprintf (fp, ":%x", ts->stopping_tracepoint);
   if (ts->traceframe_count >= 0)
     fprintf (fp, ";tframes:%x", ts->traceframe_count);
   if (ts->traceframes_created >= 0)
@@ -3126,12 +3152,13 @@ extern char *unpack_varlen_hex (char *buff, ULONGEST *result);
 void
 parse_trace_status (char *line, struct trace_status *ts)
 {
-  char *p = line, *p1, *p_temp;
+  char *p = line, *p1, *p2, *p_temp;
   ULONGEST val;
 
   ts->running_known = 1;
   ts->running = (*p++ == '1');
   ts->stop_reason = trace_stop_reason_unknown;
+  ts->error_desc = "";
   ts->traceframe_count = -1;
   ts->traceframes_created = -1;
   ts->buffer_free = -1;
@@ -3164,6 +3191,30 @@ Status line: '%s'\n"), p, line);
          p = unpack_varlen_hex (++p1, &val);
          ts->stop_reason = tstop_command;
        }
+      else if (strncmp (p, stop_reason_names[tracepoint_error], p1 - p) == 0)
+       {
+         p2 = strchr (++p1, ':');
+         if (p2 != p1)
+           {
+             int end;
+             ts->error_desc = (char *) xmalloc (p2 - p1 + 1);
+             /* See if we're doing plain text or hex encoding.  */
+             if (*p1 == 'X')
+               {
+                 ++p1;
+                 end = hex2bin (p1, ts->error_desc, (p2 - p1) / 2);
+               }
+             else
+               {
+                 memcpy (ts->error_desc, p1, p2 - p1);
+                 end = p2 - p1;
+               }
+             ts->error_desc[end] = '\0';
+           }
+         p = unpack_varlen_hex (++p2, &val);
+         ts->stopping_tracepoint = val;
+         ts->stop_reason = tracepoint_error;
+       }
       else if (strncmp (p, "tframes", p1 - p) == 0)
        {
          p = unpack_varlen_hex (++p1, &val);
index 723baa2401ae24749707643195c7980ef9c1db3e..1da7d26e1cf8cab211b13828ec596da598c469eb 100644 (file)
@@ -73,7 +73,8 @@ enum trace_stop_reason
     tstop_command,
     trace_buffer_full,
     trace_disconnected,
-    tracepoint_passcount
+    tracepoint_passcount,
+    tracepoint_error
   };
 
 struct trace_status
@@ -89,10 +90,15 @@ struct trace_status
 
   enum trace_stop_reason stop_reason;
 
-  /* If stop_reason == tracepoint_passcount, the on-target number
-     of the tracepoint which caused the stop.  */
+  /* If stop_reason is tracepoint_passcount or tracepoint_error, this
+     is the (on-target) number of the tracepoint which caused the
+     stop.  */
   int stopping_tracepoint;
 
+  /* If stop_reason is tracepoint_error, this is a human-readable
+     string that describes the error that happened on the target.  */
+  char *error_desc;
+
   /* Number of traceframes currently in the buffer.  */
 
   int traceframe_count;