Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
From: Stan Shebs <stan@codesourcery.com>
To: gdb-patches@sourceware.org
Subject: [PATCH] Handle errors in tracepoint target agent
Date: Thu, 25 Mar 2010 00:48:00 -0000	[thread overview]
Message-ID: <4BAAB2E9.7020708@codesourcery.com> (raw)

[-- Attachment #1: Type: text/plain, Size: 1939 bytes --]

One of the downsides of the fancy-schmancy expression evaluation for 
tracepoints is that it could have plain old computational errors, such 
as a divide by zero, stack underflow, invalid memory reference, etc.  
Although it's conceivable that one might somehow want tracing to 
struggle on, more likely it's a sign of a mistake in the experimental 
setup, and the right thing is to simply give up.  This patch adds 
machinery for the target to report that it stopped due to an error and 
display any available info in tstatus.

But before committing, I want to get feedback on what to do about a 
protocol mistake I made with this one; the descriptive string is 
included verbatim in the status packet, which means that it can't have 
colons embedded, and probably other characters.  There are a couple ways 
to fix - encode the string in hex, or add a length prefix.  The problem 
is that this feature has been in Ericsson's hands for awhile, bolted 
into their application already I think, and so there is a compatibility 
issue.  We do have the list of strings that their agent returns, and we 
could say for instance that a leading numeric digit is assumed to 
indicate a length field, otherwise it's handled verbatim.  On the flip 
side, this all is getting rather arcane, so maybe I'm worrying too much 
about it.  What do people think?

Stan

2010-03-24  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.
    (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.
    * gdb.trace/tfile.exp: Test trace file with an error stop.


[-- Attachment #2: terror-patch-1 --]
[-- Type: text/plain, Size: 9267 bytes --]

Index: tracepoint.c
===================================================================
RCS file: /cvs/src/src/gdb/tracepoint.c,v
retrieving revision 1.155
diff -p -r1.155 tracepoint.c
*** tracepoint.c	24 Mar 2010 21:12:18 -0000	1.155
--- tracepoint.c	25 Mar 2010 00:28:27 -0000
*************** char *stop_reason_names[] = {
*** 195,201 ****
    "tstop",
    "tfull",
    "tdisconnected",
!   "tpasscount"
  };
  
  struct trace_status *
--- 195,202 ----
    "tstop",
    "tfull",
    "tdisconnected",
!   "tpasscount",
!   "terror"
  };
  
  struct trace_status *
*************** trace_status_command (char *args, int fr
*** 1570,1575 ****
--- 1571,1585 ----
  	  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->error_desc : ""),
+ 			     ts->stopping_tracepoint);
+ 	  else
+ 	    printf_filtered (_("Trace stopped by an error (%s).\n"),
+ 			     (ts->error_desc ? ts->error_desc : ""));
+ 	  break;
  	case trace_stop_reason_unknown:
  	  printf_filtered (_("Trace stopped for an unknown reason.\n"));
  	  break;
*************** trace_save (const char *filename, int ta
*** 2463,2471 ****
    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);
    if (ts->traceframe_count >= 0)
      fprintf (fp, ";tframes:%x", ts->traceframe_count);
    if (ts->traceframes_created >= 0)
--- 2473,2484 ----
    fprintf (fp, "R %x\n", trace_regblock_size);
  
    /* Write out status of the tracing run (aka "tstatus" info).  */
!   fprintf (fp, "status %c;%s%s%s:%x",
  	   (ts->running ? '1' : '0'),
!  	   stop_reason_names[ts->stop_reason],
!  	   (ts->stop_reason == tracepoint_error ? ":" : ""),
!  	   (ts->stop_reason == tracepoint_error ? ts->error_desc : ""),
!  	   ts->stopping_tracepoint);
    if (ts->traceframe_count >= 0)
      fprintf (fp, ";tframes:%x", ts->traceframe_count);
    if (ts->traceframes_created >= 0)
*************** extern char *unpack_varlen_hex (char *bu
*** 3126,3137 ****
  void
  parse_trace_status (char *line, struct trace_status *ts)
  {
!   char *p = line, *p1, *p_temp;
    ULONGEST val;
  
    ts->running_known = 1;
    ts->running = (*p++ == '1');
    ts->stop_reason = trace_stop_reason_unknown;
    ts->traceframe_count = -1;
    ts->traceframes_created = -1;
    ts->buffer_free = -1;
--- 3139,3151 ----
  void
  parse_trace_status (char *line, struct trace_status *ts)
  {
!   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 = NULL;
    ts->traceframe_count = -1;
    ts->traceframes_created = -1;
    ts->buffer_free = -1;
*************** Status line: '%s'\n"), p, line);
*** 3164,3169 ****
--- 3178,3196 ----
  	  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)
+ 	    {
+ 	      ts->error_desc = (char *) xmalloc (p2 - p1 + 1);
+ 	      memcpy (ts->error_desc, p1, p2 - p1);
+ 	      ts->error_desc[p2 - p1] = '\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: tracepoint.h
===================================================================
RCS file: /cvs/src/src/gdb/tracepoint.h,v
retrieving revision 1.29
diff -p -r1.29 tracepoint.h
*** tracepoint.h	23 Mar 2010 22:05:45 -0000	1.29
--- tracepoint.h	25 Mar 2010 00:28:27 -0000
*************** enum trace_stop_reason
*** 73,79 ****
      tstop_command,
      trace_buffer_full,
      trace_disconnected,
!     tracepoint_passcount
    };
  
  struct trace_status
--- 73,80 ----
      tstop_command,
      trace_buffer_full,
      trace_disconnected,
!     tracepoint_passcount,
!     tracepoint_error
    };
  
  struct trace_status
*************** struct trace_status
*** 89,98 ****
  
    enum trace_stop_reason stop_reason;
  
!   /* If stop_reason == tracepoint_passcount, the on-target number
!      of the tracepoint which caused the stop.  */
    int stopping_tracepoint;
  
    /* Number of traceframes currently in the buffer.  */
  
    int traceframe_count;
--- 90,104 ----
  
    enum trace_stop_reason stop_reason;
  
!   /* 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;
Index: doc/gdb.texinfo
===================================================================
RCS file: /cvs/src/src/gdb/doc/gdb.texinfo,v
retrieving revision 1.683
diff -p -r1.683 gdb.texinfo
*** doc/gdb.texinfo	24 Mar 2010 21:24:08 -0000	1.683
--- doc/gdb.texinfo	25 Mar 2010 00:28:28 -0000
*************** The trace stopped because @value{GDBN} d
*** 31362,31367 ****
--- 31362,31373 ----
  @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 not contain any colon characters.
+ 
  @item tunknown:0
  The trace stopped for some other reason.
  
Index: testsuite/gdb.trace/tfile.c
===================================================================
RCS file: /cvs/src/src/gdb/testsuite/gdb.trace/tfile.c,v
retrieving revision 1.1
diff -p -r1.1 tfile.c
*** testsuite/gdb.trace/tfile.c	15 Jan 2010 22:37:20 -0000	1.1
--- testsuite/gdb.trace/tfile.c	25 Mar 2010 00:28:28 -0000
*************** write_basic_trace_file ()
*** 100,105 ****
--- 100,146 ----
  }
  
  void
+ write_error_trace_file ()
+ {
+   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.  */
+   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);
+ 
+   /* Write end of tracebuffer marker.  */
+   *((short *) trptr) = 0;
+   trptr += sizeof (short);
+   *((int *) trptr) = 0;
+   trptr += sizeof (int);
+ 
+   write (fd, trbuf, trptr - trbuf);
+ 
+   finish_trace_file (fd);
+ }
+ 
+ void
  done_making_trace_files (void)
  {
  }
*************** main (int argc, char **argv, char **envp
*** 109,114 ****
--- 150,157 ----
  {
    write_basic_trace_file ();
  
+   write_error_trace_file ();
+ 
    done_making_trace_files ();
  
    return 0;
Index: testsuite/gdb.trace/tfile.exp
===================================================================
RCS file: /cvs/src/src/gdb/testsuite/gdb.trace/tfile.exp,v
retrieving revision 1.3
diff -p -r1.3 tfile.exp
*** testsuite/gdb.trace/tfile.exp	24 Mar 2010 21:11:06 -0000	1.3
--- testsuite/gdb.trace/tfile.exp	25 Mar 2010 00:28:28 -0000
*************** gdb_reinitialize_dir $srcdir/$subdir
*** 48,53 ****
--- 48,54 ----
  
  # Make sure we are starting fresh.
  remote_exec build {sh -xc rm\ -f\ basic.tf}
+ remote_exec build {sh -xc rm\ -f\ error.tf}
  
  gdb_load $binfile
  
*************** Trace buffer has 256 bytes of 4096 bytes
*** 83,89 ****
--- 84,102 ----
  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"

             reply	other threads:[~2010-03-25  0:48 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2010-03-25  0:48 Stan Shebs [this message]
2010-03-25  4:18 ` Eli Zaretskii
2010-03-25 10:27 ` Pedro Alves
2010-03-25 22:30   ` Stan Shebs
2010-03-25 22:42     ` Pedro Alves
2010-03-25 23:06       ` Stan Shebs

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=4BAAB2E9.7020708@codesourcery.com \
    --to=stan@codesourcery.com \
    --cc=gdb-patches@sourceware.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox