From 6c28cbf2b6beb56c99ec084b9bc5adc8d4813894 Mon Sep 17 00:00:00 2001 From: Stan Shebs Date: Fri, 26 Mar 2010 01:46:29 +0000 Subject: [PATCH] 2010-03-25 Stan Shebs * 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 | 11 +++++ gdb/doc/ChangeLog | 4 ++ gdb/doc/gdb.texinfo | 9 ++++ gdb/testsuite/ChangeLog | 7 +++ gdb/testsuite/gdb.trace/tfile.c | 80 +++++++++++++++++++++++++------ gdb/testsuite/gdb.trace/tfile.exp | 15 +++++- gdb/tracepoint.c | 61 +++++++++++++++++++++-- gdb/tracepoint.h | 12 +++-- 8 files changed, 175 insertions(+), 24 deletions(-) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 3bf68362309..6dff8952be6 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,14 @@ +2010-03-25 Stan Shebs + + * 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 * dwarf2read.c (read_subroutine_type): If the compilation unit diff --git a/gdb/doc/ChangeLog b/gdb/doc/ChangeLog index d99937aefb7..dfb8a8d5d43 100644 --- a/gdb/doc/ChangeLog +++ b/gdb/doc/ChangeLog @@ -1,3 +1,7 @@ +2010-03-24 Stan Shebs + + * gdb.texinfo (Tracepoint Packets): Document trace error status. + 2010-03-24 Tom Tromey PR breakpoints/9352: diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo index 369556d6569..3c7d669b319 100644 --- a/gdb/doc/gdb.texinfo +++ b/gdb/doc/gdb.texinfo @@ -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. diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog index 3ee9fb5fbe5..3800958806f 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -1,3 +1,10 @@ +2010-03-25 Stan Shebs + + * 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 * gdb.java/jprint.exp: XFAIL printing of static class members diff --git a/gdb/testsuite/gdb.trace/tfile.c b/gdb/testsuite/gdb.trace/tfile.c index 9ffc37164aa..5d4c797e94a 100644 --- a/gdb/testsuite/gdb.trace/tfile.c +++ b/gdb/testsuite/gdb.trace/tfile.c @@ -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; diff --git a/gdb/testsuite/gdb.trace/tfile.exp b/gdb/testsuite/gdb.trace/tfile.exp index 20af854d1ce..a3adfcc0370 100644 --- a/gdb/testsuite/gdb.trace/tfile.exp +++ b/gdb/testsuite/gdb.trace/tfile.exp @@ -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" diff --git a/gdb/tracepoint.c b/gdb/tracepoint.c index d3cccffe268..447682a8686 100644 --- a/gdb/tracepoint.c +++ b/gdb/tracepoint.c @@ -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); diff --git a/gdb/tracepoint.h b/gdb/tracepoint.h index 723baa2401a..1da7d26e1cf 100644 --- a/gdb/tracepoint.h +++ b/gdb/tracepoint.h @@ -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; -- 2.30.2