* 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.
+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
+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:
@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.
+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
}
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");
/* 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));
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);
{
write_basic_trace_file ();
+ write_error_trace_file ();
+
done_making_trace_files ();
return 0;
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
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"
"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;
}
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;
stop_reason = "passcount";
stopping_tracepoint = ts->stopping_tracepoint;
break;
+ case tracepoint_error:
+ stop_reason = "error";
+ stopping_tracepoint = ts->stopping_tracepoint;
+ break;
}
if (stop_reason)
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);
}
}
}
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)
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;
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);
tstop_command,
trace_buffer_full,
trace_disconnected,
- tracepoint_passcount
+ tracepoint_passcount,
+ tracepoint_error
};
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;