Add trace file support.
* tracepoint.h (enum trace_stop_reason): New enum. (struct trace_status): New struct. (parse_trace_status): Declare. (struct uploaded_tp): Move here from remote.c, add fields for actions. (struct uploaded_tsv): New struct. * tracepoint.c (tfile_ops): New target vector. (trace_fd): New global. (tfile_open): New function. (tfile_close): New function. (tfile_files_info): New function. (tfile_get_trace_status): New function. (tfile_get_traceframe_address): New function. (tfile_trace_find): New function. (tfile_fetch_registers): New function. (tfile_xfer_partial): New function. (tfile_get_trace_state_variable_value): New function. (init_tfile_ops): New function. (_initialize_tracepoint): Call it, add tfile target. (trace_status): New global. (current_trace_status): New function. (trace_running_p): Remove, change all users to get from current_trace_status()->running. (get_trace_status): Remove. (trace_status_command): Call target_get_trace_status directly, report more detail including tracing stop reasons. (trace_find_command): Always allow tfind on a file. (trace_find_pc_command): Ditto. (trace_find_tracepoint_command): Ditto. (trace_find_line_command): Ditto. (trace_find_range_command): Ditto. (trace_find_outside_command): Ditto. (trace_frames_offset, cur_offset): Declare as off_t. (trace_regblock_size): Rename from reg_size, update users. (parse_trace_status): New function. (tfile_interp_line): New function. (disconnect_or_stop_tracing): Ensure current trace status before asking what to do. (stop_reason_names): New global. (trace_save_command): New command. (get_uploaded_tp): Move here from remote.c. (find_matching_tracepoint): Ditto. (merge_uploaded_tracepoints): New function. (parse_trace_status): Use stop_reason_names. (_initialize_tracepoint): Define tsave command. * target.h (target_ops): New fields to_save_trace_data, to_upload_tracepoints, to_upload_trace_state_variables, to_get_raw_trace_data, change to_get_trace_status to take a pointer to a status struct. (target_save_trace_data): New macro. (target_upload_tracepoints): New macro. (target_upload_trace_state_variables): New macro. (target_get_raw_trace_data): New macro. * target.c (update_current_target): Add new methods, change signature of to_get_trace_status. * remote.c (hex2bin): Make globally visible. (bin2hex): Ditto. (remote_download_trace_state_variable): Download name also. (remote_get_trace_status): Update parameter, use parse_trace_status. (remote_save_trace_data): New function. (remote_upload_tracepoints): New function. (remote_upload_trace_state_variables): New function. (remote_get_raw_trace_data): New function. (remote_start_remote): Use them. (_initialize_remote_ops): Add operations. * ax-gdb.c: Include breakpoint.h. * breakpoint.c (create_tracepoint_from_upload): Use break_command_really, return tracepoint, warn about unimplemented parts. * NEWS: Mention trace file addition. * gdb.texinfo (Trace Files): New section. (Tracepoint Packets): Document QTSave and qTBuffer. (Trace File Format): New appendix. * generic/gdbtk-bp.c (gdb_trace_status): Use current_trace_status. * gdb.trace/tfile.c: New file. * gdb.trace/tfile.exp: New file.
This commit is contained in:
parent
6ec12636a7
commit
00bf0b8586
14 changed files with 1969 additions and 235 deletions
|
@ -1,3 +1,78 @@
|
|||
2010-01-15 Stan Shebs <stan@codesourcery.com>
|
||||
|
||||
Add trace file support.
|
||||
* tracepoint.h (enum trace_stop_reason): New enum.
|
||||
(struct trace_status): New struct.
|
||||
(parse_trace_status): Declare.
|
||||
(struct uploaded_tp): Move here from remote.c,
|
||||
add fields for actions.
|
||||
(struct uploaded_tsv): New struct.
|
||||
* tracepoint.c (tfile_ops): New target vector.
|
||||
(trace_fd): New global.
|
||||
(tfile_open): New function.
|
||||
(tfile_close): New function.
|
||||
(tfile_files_info): New function.
|
||||
(tfile_get_trace_status): New function.
|
||||
(tfile_get_traceframe_address): New function.
|
||||
(tfile_trace_find): New function.
|
||||
(tfile_fetch_registers): New function.
|
||||
(tfile_xfer_partial): New function.
|
||||
(tfile_get_trace_state_variable_value): New function.
|
||||
(init_tfile_ops): New function.
|
||||
(_initialize_tracepoint): Call it, add tfile target.
|
||||
(trace_status): New global.
|
||||
(current_trace_status): New function.
|
||||
(trace_running_p): Remove, change all users to get from
|
||||
current_trace_status()->running.
|
||||
(get_trace_status): Remove.
|
||||
(trace_status_command): Call target_get_trace_status directly,
|
||||
report more detail including tracing stop reasons.
|
||||
(trace_find_command): Always allow tfind on a file.
|
||||
(trace_find_pc_command): Ditto.
|
||||
(trace_find_tracepoint_command): Ditto.
|
||||
(trace_find_line_command): Ditto.
|
||||
(trace_find_range_command): Ditto.
|
||||
(trace_find_outside_command): Ditto.
|
||||
(trace_frames_offset, cur_offset): Declare as off_t.
|
||||
(trace_regblock_size): Rename from reg_size, update users.
|
||||
(parse_trace_status): New function.
|
||||
(tfile_interp_line): New function.
|
||||
(disconnect_or_stop_tracing): Ensure current trace
|
||||
status before asking what to do.
|
||||
(stop_reason_names): New global.
|
||||
(trace_save_command): New command.
|
||||
(get_uploaded_tp): Move here from remote.c.
|
||||
(find_matching_tracepoint): Ditto.
|
||||
(merge_uploaded_tracepoints): New function.
|
||||
(parse_trace_status): Use stop_reason_names.
|
||||
(_initialize_tracepoint): Define tsave command.
|
||||
* target.h (target_ops): New fields to_save_trace_data,
|
||||
to_upload_tracepoints, to_upload_trace_state_variables,
|
||||
to_get_raw_trace_data, change to_get_trace_status
|
||||
to take a pointer to a status struct.
|
||||
(target_save_trace_data): New macro.
|
||||
(target_upload_tracepoints): New macro.
|
||||
(target_upload_trace_state_variables): New macro.
|
||||
(target_get_raw_trace_data): New macro.
|
||||
* target.c (update_current_target): Add new methods, change
|
||||
signature of to_get_trace_status.
|
||||
* remote.c (hex2bin): Make globally visible.
|
||||
(bin2hex): Ditto.
|
||||
(remote_download_trace_state_variable): Download name also.
|
||||
(remote_get_trace_status): Update parameter, use
|
||||
parse_trace_status.
|
||||
(remote_save_trace_data): New function.
|
||||
(remote_upload_tracepoints): New function.
|
||||
(remote_upload_trace_state_variables): New function.
|
||||
(remote_get_raw_trace_data): New function.
|
||||
(remote_start_remote): Use them.
|
||||
(_initialize_remote_ops): Add operations.
|
||||
* ax-gdb.c: Include breakpoint.h.
|
||||
* breakpoint.c (create_tracepoint_from_upload): Use
|
||||
break_command_really, return tracepoint, warn about unimplemented
|
||||
parts.
|
||||
* NEWS: Mention trace file addition.
|
||||
|
||||
2010-01-15 Jan Kratochvil <jan.kratochvil@redhat.com>
|
||||
|
||||
Fix compilation warning on gcc-3.4.
|
||||
|
@ -164,7 +239,6 @@
|
|||
(SUBDIR_PYTHON_SRCS): Likewise.
|
||||
(py-lazy-string.o): New rule.
|
||||
|
||||
|
||||
2010-01-13 Doug Evans <dje@google.com>
|
||||
|
||||
* mi/mi-main.c (list_available_thread_groups): Avoid "may be used
|
||||
|
|
10
gdb/NEWS
10
gdb/NEWS
|
@ -61,6 +61,16 @@ Renesas RX rx
|
|||
tell the target agent whether to continue running a trace if the
|
||||
connection is lost unexpectedly.
|
||||
|
||||
** Trace files
|
||||
|
||||
GDB now has the ability to save the trace buffer into a file, and
|
||||
then use that file as a target, similarly to you can do with
|
||||
corefiles. You can select trace frames, print data that was
|
||||
collected in them, and use tstatus to display the state of the
|
||||
tracing run at the moment that it was saved. To create a trace
|
||||
file, use "tsave <filename>", and to use it, do "target tfile
|
||||
<name>".
|
||||
|
||||
* Changed commands
|
||||
|
||||
disassemble
|
||||
|
|
|
@ -37,6 +37,7 @@
|
|||
#include "user-regs.h"
|
||||
#include "language.h"
|
||||
#include "dictionary.h"
|
||||
#include "breakpoint.h"
|
||||
#include "tracepoint.h"
|
||||
|
||||
/* To make sense of this file, you should read doc/agentexpr.texi.
|
||||
|
|
|
@ -9847,26 +9847,60 @@ ftrace_command (char *arg, int from_tty)
|
|||
set_tracepoint_count (breakpoint_count);
|
||||
}
|
||||
|
||||
extern void create_tracepoint_from_upload (int num, enum bptype type,
|
||||
ULONGEST addr);
|
||||
/* Given information about a tracepoint as recorded on a target (which
|
||||
can be either a live system or a trace file), attempt to create an
|
||||
equivalent GDB tracepoint. This is not a reliable process, since
|
||||
the target does not necessarily have all the information used when
|
||||
the tracepoint was originally defined. */
|
||||
|
||||
void
|
||||
create_tracepoint_from_upload (int num, enum bptype type, ULONGEST addr)
|
||||
struct breakpoint *
|
||||
create_tracepoint_from_upload (struct uploaded_tp *utp)
|
||||
{
|
||||
char buf[100];
|
||||
struct breakpoint *tp;
|
||||
|
||||
sprintf (buf, "*0x%s", paddress (get_current_arch (), addr));
|
||||
if (type == bp_fast_tracepoint)
|
||||
ftrace_command (buf, 0);
|
||||
else
|
||||
trace_command (buf, 0);
|
||||
/* In the absence of a source location, fall back to raw address. */
|
||||
sprintf (buf, "*%s", paddress (get_current_arch(), utp->addr));
|
||||
|
||||
/* Record that this tracepoint is numbered differently on host and
|
||||
target. */
|
||||
tp = get_tracepoint (tracepoint_count);
|
||||
tp->number_on_target = num;
|
||||
}
|
||||
break_command_really (get_current_arch (),
|
||||
buf,
|
||||
NULL, 0, 1 /* parse arg */,
|
||||
0 /* tempflag */,
|
||||
(utp->type == bp_fast_tracepoint) /* hardwareflag */,
|
||||
1 /* traceflag */,
|
||||
0 /* Ignore count */,
|
||||
pending_break_support,
|
||||
NULL,
|
||||
0 /* from_tty */,
|
||||
utp->enabled /* enabled */);
|
||||
set_tracepoint_count (breakpoint_count);
|
||||
|
||||
tp = get_tracepoint (tracepoint_count);
|
||||
|
||||
if (utp->pass > 0)
|
||||
{
|
||||
sprintf (buf, "%d %d", utp->pass, tp->number);
|
||||
|
||||
trace_pass_command (buf, 0);
|
||||
}
|
||||
|
||||
if (utp->cond)
|
||||
{
|
||||
printf_filtered ("Want to restore a condition\n");
|
||||
}
|
||||
|
||||
if (utp->numactions > 0)
|
||||
{
|
||||
printf_filtered ("Want to restore action list\n");
|
||||
}
|
||||
|
||||
if (utp->num_step_actions > 0)
|
||||
{
|
||||
printf_filtered ("Want to restore action list\n");
|
||||
}
|
||||
|
||||
return tp;
|
||||
}
|
||||
|
||||
/* Print information on tracepoint number TPNUM_EXP, or all if
|
||||
omitted. */
|
||||
|
|
|
@ -1,3 +1,9 @@
|
|||
2010-01-15 Stan Shebs <stan@codesourcery.com>
|
||||
|
||||
* gdb.texinfo (Trace Files): New section.
|
||||
(Tracepoint Packets): Document QTSave and qTBuffer.
|
||||
(Trace File Format): New appendix.
|
||||
|
||||
2010-01-13 Phil Muldoon <pmuldoon@redhat.com>
|
||||
|
||||
* gdb.texinfo (Values From Inferior): Document lazy_string value
|
||||
|
|
|
@ -174,6 +174,7 @@ software in general. We will miss him.
|
|||
@value{GDBN}
|
||||
* Operating System Information:: Getting additional information from
|
||||
the operating system
|
||||
* Trace File Format:: GDB trace file format
|
||||
* Copying:: GNU General Public License says
|
||||
how you can copy and share GDB
|
||||
* GNU Free Documentation License:: The license for this documentation
|
||||
|
@ -9292,12 +9293,17 @@ support tracepoints as of this writing. The format of the remote
|
|||
packets used to implement tracepoints are described in @ref{Tracepoint
|
||||
Packets}.
|
||||
|
||||
It is also possible to get trace data from a file, in a manner reminiscent
|
||||
of corefiles; you specify the filename, and use @code{tfind} to search
|
||||
through the file. @xref{Trace Files}, for more details.
|
||||
|
||||
This chapter describes the tracepoint commands and features.
|
||||
|
||||
@menu
|
||||
* Set Tracepoints::
|
||||
* Analyze Collected Data::
|
||||
* Tracepoint Variables::
|
||||
* Trace Files::
|
||||
@end menu
|
||||
|
||||
@node Set Tracepoints
|
||||
|
@ -10081,6 +10087,41 @@ which are managed by the target.
|
|||
> end
|
||||
@end smallexample
|
||||
|
||||
@node Trace Files
|
||||
@section Using Trace Files
|
||||
@cindex trace files
|
||||
|
||||
In some situations, the target running a trace experiment may no
|
||||
longer be available; perhaps it crashed, or the hardware was needed
|
||||
for a different activity. To handle these cases, you can arrange to
|
||||
dump the trace data into a file, and later use that file as a source
|
||||
of trace data, via the @code{target tfile} command.
|
||||
|
||||
@table @code
|
||||
|
||||
@kindex tsave
|
||||
@item tsave [ -r ] @var{filename}
|
||||
Save the trace data to @var{filename}. By default, this command
|
||||
assumes that @var{filename} refers to the host filesystem, so if
|
||||
necessary @value{GDBN} will copy raw trace data up from the target and
|
||||
then save it. If the target supports it, you can also supply the
|
||||
optional argument @code{-r} (``remote'') to direct the target to save
|
||||
the data directly into @var{filename} in its own filesystem, which may be
|
||||
more efficient if the trace buffer is very large. (Note, however, that
|
||||
@code{target tfile} can only read from files accessible to the host.)
|
||||
|
||||
@kindex target tfile
|
||||
@kindex tfile
|
||||
@item target tfile @var{filename}
|
||||
Use the file named @var{filename} as a source of trace data. Commands
|
||||
that examine data work as they do with a live target, but it is not
|
||||
possible to run any new trace experiments. @code{tstatus} will report
|
||||
the state of the trace run at the moment the data was saved, as well
|
||||
as the current trace frame you are examining. @var{filename} must be
|
||||
on a filesystem accessible to the host.
|
||||
|
||||
@end table
|
||||
|
||||
@node Overlays
|
||||
@chapter Debugging Programs That Use Overlays
|
||||
@cindex overlays
|
||||
|
@ -29964,10 +30005,12 @@ encoded). @value{GDBN} will continue to supply the values of symbols
|
|||
(if available), until the target ceases to request them.
|
||||
@end table
|
||||
|
||||
@item qTBuffer
|
||||
@item QTDisconnected
|
||||
@itemx QTDP
|
||||
@itemx QTDV
|
||||
@itemx QTfP
|
||||
@itemx qTfP
|
||||
@itemx qTfV
|
||||
@itemx QTFrame
|
||||
@xref{Tracepoint Packets}.
|
||||
|
||||
|
@ -29996,7 +30039,9 @@ the command by a @samp{,}, not a @samp{:}, contrary to the naming
|
|||
conventions above. Please don't use this packet as a model for new
|
||||
packets.)
|
||||
|
||||
@item QTsP
|
||||
@item QTSave
|
||||
@item qTsP
|
||||
@item qTsV
|
||||
@itemx QTStart
|
||||
@itemx QTStop
|
||||
@itemx QTinit
|
||||
|
@ -30455,6 +30500,29 @@ of data, and multiple @code{qTsP} to get additional pieces. Replies
|
|||
to these packets generally take the form of the @code{QTDP} packets
|
||||
that define tracepoints. (FIXME add detailed syntax)
|
||||
|
||||
@item qTfV
|
||||
@itemx qTsV
|
||||
These packets request data about trace state variables that are on the
|
||||
target. @value{GDBN} sends @code{qTfV} to get the first vari of data,
|
||||
and multiple @code{qTsV} to get additional variables. Replies to
|
||||
these packets follow the syntax of the @code{QTDV} packets that define
|
||||
trace state variables.
|
||||
|
||||
@item QTSave:@var{filename}
|
||||
This packet directs the target to save trace data to the file name
|
||||
@var{filename} in the target's filesystem. @var{filename} is encoded
|
||||
as a hex string; the interpretation of the file name (relative vs
|
||||
absolute, wild cards, etc) is up to the target.
|
||||
|
||||
@item qTBuffer:@var{offset},@var{len}
|
||||
Return up to @var{len} bytes of the current contents of trace buffer,
|
||||
starting at @var{offset}. The trace buffer is treated as if it were
|
||||
a contiguous collection of traceframes, as per the trace file format.
|
||||
The reply consists as many hex-encoded bytes as the target can deliver
|
||||
in a packet; it is not an error to return fewer than were asked for.
|
||||
A reply consisting of just @code{l} indicates that no bytes are
|
||||
available.
|
||||
|
||||
@end table
|
||||
|
||||
@node Host I/O Packets
|
||||
|
@ -32146,6 +32214,59 @@ element is interpreted as human-readable auxilliary information.
|
|||
|
||||
@include agentexpr.texi
|
||||
|
||||
@node Trace File Format
|
||||
@appendix Trace File Format
|
||||
@cindex trace file format
|
||||
|
||||
The trace file comes in three parts: a header, a textual description
|
||||
section, and a trace frame section with binary data.
|
||||
|
||||
The header has the form @code{\x7fTRACE0\n}. The first byte is
|
||||
@code{0x7f} so as to indicate that the file contains binary data,
|
||||
while the @code{0} is a version number that may have different values
|
||||
in the future.
|
||||
|
||||
The description section consists of multiple lines of @sc{ascii} text
|
||||
separated by newline characters (@code{0xa}). The lines may include a
|
||||
variety of optional descriptive or context-setting information, such
|
||||
as tracepoint definitions or register set size. @value{GDBN} will
|
||||
ignore any line that it does not recognize. An empty line marks the end
|
||||
of this section.
|
||||
|
||||
@c FIXME add some specific types of data
|
||||
|
||||
The trace frame section consists of a number of consecutive frames.
|
||||
Each frame begins with a two-byte tracepoint number, followed by a
|
||||
four-byte size giving the amount of data in the frame. The data in
|
||||
the frame consists of a number of blocks, each introduced by a
|
||||
character indicating its type (at least register, memory, and trace
|
||||
state variable). The data in this section is raw binary, not a
|
||||
hexadecimal or other encoding; its endianness matches the target's
|
||||
endianness.
|
||||
|
||||
@c FIXME bi-arch may require endianness/arch info in description section
|
||||
|
||||
@table @code
|
||||
@item R @var{bytes}
|
||||
Register block. The number and ordering of bytes matches that of a
|
||||
@code{g} packet in the remote protocol. Note that these are the
|
||||
actual bytes, in target order and @value{GDBN} register order, not a
|
||||
hexadecimal encoding.
|
||||
|
||||
@item M @var{address} @var{length} @var{bytes}...
|
||||
Memory block. This is a contiguous block of memory, at the 8-byte
|
||||
address @var{address}, with a 2-byte length @var{length}, followed by
|
||||
@var{length} bytes.
|
||||
|
||||
@item V @var{number} @var{value}
|
||||
Trace state variable block. This records the 8-byte signed value
|
||||
@var{value} of trace state variable numbered @var{number}.
|
||||
|
||||
@end table
|
||||
|
||||
Future enhancements of the trace file format may include additional types
|
||||
of blocks.
|
||||
|
||||
@node Target Descriptions
|
||||
@appendix Target Descriptions
|
||||
@cindex target descriptions
|
||||
|
|
342
gdb/remote.c
342
gdb/remote.c
|
@ -189,9 +189,9 @@ static void record_currthread (ptid_t currthread);
|
|||
|
||||
static int fromhex (int a);
|
||||
|
||||
static int hex2bin (const char *hex, gdb_byte *bin, int count);
|
||||
extern int hex2bin (const char *hex, gdb_byte *bin, int count);
|
||||
|
||||
static int bin2hex (const gdb_byte *bin, char *hex, int count);
|
||||
extern int bin2hex (const gdb_byte *bin, char *hex, int count);
|
||||
|
||||
static int putpkt_binary (char *buf, int cnt);
|
||||
|
||||
|
@ -215,7 +215,11 @@ static char *write_ptid (char *buf, const char *endbuf, ptid_t ptid);
|
|||
static ptid_t read_ptid (char *buf, char **obuf);
|
||||
|
||||
struct remote_state;
|
||||
static void remote_get_tracing_state (struct remote_state *);
|
||||
static int remote_get_trace_status (struct trace_status *ts);
|
||||
|
||||
static int remote_upload_tracepoints (struct uploaded_tp **utpp);
|
||||
|
||||
static int remote_upload_trace_state_variables (struct uploaded_tsv **utsvp);
|
||||
|
||||
static void remote_query_supported (void);
|
||||
|
||||
|
@ -3158,7 +3162,23 @@ remote_start_remote (struct ui_out *uiout, void *opaque)
|
|||
previously; find out where things are at. */
|
||||
if (rs->disconnected_tracing)
|
||||
{
|
||||
remote_get_tracing_state (rs);
|
||||
struct uploaded_tp *uploaded_tps = NULL;
|
||||
struct uploaded_tsv *uploaded_tsvs = NULL;
|
||||
|
||||
remote_get_trace_status (current_trace_status ());
|
||||
if (current_trace_status ()->running)
|
||||
printf_filtered (_("Trace is already running on the target.\n"));
|
||||
|
||||
/* Get trace state variables first, they may be checked when
|
||||
parsing uploaded commands. */
|
||||
|
||||
remote_upload_trace_state_variables (&uploaded_tsvs);
|
||||
|
||||
merge_uploaded_trace_state_variables (&uploaded_tsvs);
|
||||
|
||||
remote_upload_tracepoints (&uploaded_tps);
|
||||
|
||||
merge_uploaded_tracepoints (&uploaded_tps);
|
||||
}
|
||||
|
||||
/* If breakpoints are global, insert them now. */
|
||||
|
@ -3948,7 +3968,7 @@ fromhex (int a)
|
|||
error (_("Reply contains invalid hex digit %d"), a);
|
||||
}
|
||||
|
||||
static int
|
||||
int
|
||||
hex2bin (const char *hex, gdb_byte *bin, int count)
|
||||
{
|
||||
int i;
|
||||
|
@ -3978,7 +3998,7 @@ tohex (int nib)
|
|||
return 'a' + nib - 10;
|
||||
}
|
||||
|
||||
static int
|
||||
int
|
||||
bin2hex (const gdb_byte *bin, char *hex, int count)
|
||||
{
|
||||
int i;
|
||||
|
@ -8034,7 +8054,7 @@ remote_rcmd (char *command,
|
|||
{
|
||||
char *buf;
|
||||
|
||||
/* XXX - see also tracepoint.c:remote_get_noisy_reply(). */
|
||||
/* XXX - see also remote_get_noisy_reply(). */
|
||||
rs->buf[0] = '\0';
|
||||
getpkt (&rs->buf, &rs->buf_size, 0);
|
||||
buf = rs->buf;
|
||||
|
@ -9342,9 +9362,15 @@ static void
|
|||
remote_download_trace_state_variable (struct trace_state_variable *tsv)
|
||||
{
|
||||
struct remote_state *rs = get_remote_state ();
|
||||
char *p;
|
||||
|
||||
sprintf (rs->buf, "QTDV:%x:%s",
|
||||
tsv->number, phex ((ULONGEST) tsv->initial_value, 8));
|
||||
sprintf (rs->buf, "QTDV:%x:%s:%x:",
|
||||
tsv->number, phex ((ULONGEST) tsv->initial_value, 8), tsv->builtin);
|
||||
p = rs->buf + strlen (rs->buf);
|
||||
if ((p - rs->buf) + strlen (tsv->name) * 2 >= get_remote_packet_size ())
|
||||
error (_("Trace state variable name too long for tsv definition packet"));
|
||||
p += 2 * bin2hex ((gdb_byte *) (tsv->name), p, 0);
|
||||
*p++ = '\0';
|
||||
putpkt (rs->buf);
|
||||
remote_get_noisy_reply (&target_buf, &target_buf_size);
|
||||
}
|
||||
|
@ -9395,16 +9421,39 @@ remote_trace_start ()
|
|||
}
|
||||
|
||||
static int
|
||||
remote_get_trace_status (int *stop_reason)
|
||||
remote_get_trace_status (struct trace_status *ts)
|
||||
{
|
||||
putpkt ("qTStatus");
|
||||
remote_get_noisy_reply (&target_buf, &target_buf_size);
|
||||
char *p, *p1, *p_temp;
|
||||
ULONGEST val;
|
||||
/* FIXME we need to get register block size some other way */
|
||||
extern int trace_regblock_size;
|
||||
trace_regblock_size = get_remote_arch_state ()->sizeof_g_packet;
|
||||
|
||||
if (target_buf[0] != 'T' ||
|
||||
(target_buf[1] != '0' && target_buf[1] != '1'))
|
||||
putpkt ("qTStatus");
|
||||
getpkt (&target_buf, &target_buf_size, 0);
|
||||
/* FIXME should handle more variety of replies */
|
||||
|
||||
p = target_buf;
|
||||
|
||||
/* If the remote target doesn't do tracing, flag it. */
|
||||
if (*p == '\0')
|
||||
return -1;
|
||||
|
||||
/* We're working with a live target. */
|
||||
ts->from_file = 0;
|
||||
|
||||
/* Set some defaults. */
|
||||
ts->running_known = 0;
|
||||
ts->stop_reason = trace_stop_reason_unknown;
|
||||
ts->traceframe_count = -1;
|
||||
ts->buffer_free = 0;
|
||||
|
||||
if (*p++ != 'T')
|
||||
error (_("Bogus trace status reply from target: %s"), target_buf);
|
||||
|
||||
return (target_buf[1] == '1');
|
||||
parse_trace_status (p, ts);
|
||||
|
||||
return ts->running;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -9434,16 +9483,16 @@ remote_trace_find (enum trace_find_type type, int num,
|
|||
sprintf (p, "%x", num);
|
||||
break;
|
||||
case tfind_pc:
|
||||
sprintf (p, "pc:%s", paddress (target_gdbarch, addr1));
|
||||
sprintf (p, "pc:%s", phex_nz (addr1, 0));
|
||||
break;
|
||||
case tfind_tp:
|
||||
sprintf (p, "tdp:%x", num);
|
||||
break;
|
||||
case tfind_range:
|
||||
sprintf (p, "range:%s:%s", paddress (target_gdbarch, addr1), paddress (target_gdbarch, addr2));
|
||||
sprintf (p, "range:%s:%s", phex_nz (addr1, 0), phex_nz (addr2, 0));
|
||||
break;
|
||||
case tfind_outside:
|
||||
sprintf (p, "outside:%s:%s", paddress (target_gdbarch, addr1), paddress (target_gdbarch, addr2));
|
||||
sprintf (p, "outside:%s:%s", phex_nz (addr1, 0), phex_nz (addr2, 0));
|
||||
break;
|
||||
default:
|
||||
error ("Unknown trace find type %d", type);
|
||||
|
@ -9499,6 +9548,67 @@ remote_get_trace_state_variable_value (int tsvnum, LONGEST *val)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
remote_save_trace_data (char *filename)
|
||||
{
|
||||
struct remote_state *rs = get_remote_state ();
|
||||
char *p, *reply;
|
||||
|
||||
p = rs->buf;
|
||||
strcpy (p, "QTSave:");
|
||||
p += strlen (p);
|
||||
if ((p - rs->buf) + strlen (filename) * 2 >= get_remote_packet_size ())
|
||||
error (_("Remote file name too long for trace save packet"));
|
||||
p += 2 * bin2hex ((gdb_byte *) filename, p, 0);
|
||||
*p++ = '\0';
|
||||
putpkt (rs->buf);
|
||||
remote_get_noisy_reply (&target_buf, &target_buf_size);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* This is basically a memory transfer, but needs to be its own packet
|
||||
because we don't know how the target actually organizes its trace
|
||||
memory, plus we want to be able to ask for as much as possible, but
|
||||
not be unhappy if we don't get as much as we ask for. */
|
||||
|
||||
static LONGEST
|
||||
remote_get_raw_trace_data (gdb_byte *buf, ULONGEST offset, LONGEST len)
|
||||
{
|
||||
struct remote_state *rs = get_remote_state ();
|
||||
char *reply;
|
||||
char *p;
|
||||
int rslt;
|
||||
|
||||
p = rs->buf;
|
||||
strcpy (p, "qTBuffer:");
|
||||
p += strlen (p);
|
||||
p += hexnumstr (p, offset);
|
||||
*p++ = ',';
|
||||
p += hexnumstr (p, len);
|
||||
*p++ = '\0';
|
||||
|
||||
putpkt (rs->buf);
|
||||
reply = remote_get_noisy_reply (&target_buf, &target_buf_size);
|
||||
if (reply && *reply)
|
||||
{
|
||||
/* 'l' by itself means we're at the end of the buffer and
|
||||
there is nothing more to get. */
|
||||
if (*reply == 'l')
|
||||
return 0;
|
||||
|
||||
/* Convert the reply into binary. Limit the number of bytes to
|
||||
convert according to our passed-in buffer size, rather than
|
||||
what was returned in the packet; if the target is
|
||||
unexpectedly generous and gives us a bigger reply than we
|
||||
asked for, we don't want to crash. */
|
||||
rslt = hex2bin (target_buf, buf, len);
|
||||
return rslt;
|
||||
}
|
||||
|
||||
/* Something went wrong, flag as an error. */
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void
|
||||
remote_set_disconnected_tracing (int val)
|
||||
{
|
||||
|
@ -9592,6 +9702,10 @@ Specify the serial device it is connected to\n\
|
|||
remote_ops.to_trace_stop = remote_trace_stop;
|
||||
remote_ops.to_trace_find = remote_trace_find;
|
||||
remote_ops.to_get_trace_state_variable_value = remote_get_trace_state_variable_value;
|
||||
remote_ops.to_save_trace_data = remote_save_trace_data;
|
||||
remote_ops.to_upload_tracepoints = remote_upload_tracepoints;
|
||||
remote_ops.to_upload_trace_state_variables = remote_upload_trace_state_variables;
|
||||
remote_ops.to_get_raw_trace_data = remote_get_raw_trace_data;
|
||||
remote_ops.to_set_disconnected_tracing = remote_set_disconnected_tracing;
|
||||
remote_ops.to_core_of_thread = remote_core_of_thread;
|
||||
}
|
||||
|
@ -9744,181 +9858,51 @@ remote_new_objfile (struct objfile *objfile)
|
|||
remote_check_symbols (objfile);
|
||||
}
|
||||
|
||||
/* Struct to collect random info about tracepoints on the target. */
|
||||
/* Pull all the tracepoints defined on the target and create local
|
||||
data structures representing them. We don't want to create real
|
||||
tracepoints yet, we don't want to mess up the user's existing
|
||||
collection. */
|
||||
|
||||
struct uploaded_tp {
|
||||
int number;
|
||||
enum bptype type;
|
||||
ULONGEST addr;
|
||||
int enabled;
|
||||
int step;
|
||||
int pass;
|
||||
int orig_size;
|
||||
char *cond;
|
||||
int cond_len;
|
||||
struct uploaded_tp *next;
|
||||
};
|
||||
|
||||
struct uploaded_tp *uploaded_tps;
|
||||
|
||||
struct uploaded_tp *
|
||||
get_uploaded_tp (int num)
|
||||
{
|
||||
struct uploaded_tp *utp;
|
||||
|
||||
for (utp = uploaded_tps; utp; utp = utp->next)
|
||||
if (utp->number == num)
|
||||
return utp;
|
||||
utp = (struct uploaded_tp *) xmalloc (sizeof (struct uploaded_tp));
|
||||
utp->number = num;
|
||||
utp->next = uploaded_tps;
|
||||
uploaded_tps = utp;
|
||||
return utp;
|
||||
}
|
||||
|
||||
/* Look for an existing tracepoint that seems similar enough to the
|
||||
uploaded one. Enablement isn't checked, because the user can
|
||||
toggle that freely, and may have done so in anticipation of the
|
||||
next trace run. */
|
||||
|
||||
struct breakpoint *
|
||||
find_matching_tracepoint (struct uploaded_tp *utp)
|
||||
{
|
||||
VEC(breakpoint_p) *tp_vec = all_tracepoints ();
|
||||
int ix;
|
||||
struct breakpoint *t;
|
||||
|
||||
for (ix = 0; VEC_iterate (breakpoint_p, tp_vec, ix, t); ix++)
|
||||
{
|
||||
if (t->type == utp->type
|
||||
&& (t->loc && t->loc->address == utp->addr)
|
||||
&& t->step_count == utp->step
|
||||
&& t->pass_count == utp->pass
|
||||
/* FIXME also test conditionals and actions */
|
||||
)
|
||||
return t;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Find out everything we can about the trace run that was already
|
||||
happening on the target. This includes both running/stopped, and
|
||||
the tracepoints that were in use. */
|
||||
|
||||
static void
|
||||
remote_get_tracing_state (struct remote_state *rs)
|
||||
static int
|
||||
remote_upload_tracepoints (struct uploaded_tp **utpp)
|
||||
{
|
||||
struct remote_state *rs = get_remote_state ();
|
||||
char *p;
|
||||
ULONGEST num, addr, step, pass, orig_size, xlen;
|
||||
int enabled, i;
|
||||
enum bptype type;
|
||||
char *cond;
|
||||
struct uploaded_tp *utp;
|
||||
struct breakpoint *t;
|
||||
extern void get_trace_status ();
|
||||
|
||||
get_trace_status ();
|
||||
if (trace_running_p)
|
||||
printf_filtered (_("Trace is running on the target.\n"));
|
||||
|
||||
/* Ask for a first packet of tracepoint definition. */
|
||||
putpkt ("qTfP");
|
||||
getpkt (&rs->buf, &rs->buf_size, 0);
|
||||
p = rs->buf;
|
||||
while (*p != '\0')
|
||||
while (*p && *p != 'l')
|
||||
{
|
||||
if (*p == 'T')
|
||||
{
|
||||
p++;
|
||||
p = unpack_varlen_hex (p, &num);
|
||||
p++;
|
||||
p = unpack_varlen_hex (p, &addr);
|
||||
p++;
|
||||
enabled = (*p++ == 'E');
|
||||
p++;
|
||||
p = unpack_varlen_hex (p, &step);
|
||||
p++;
|
||||
p = unpack_varlen_hex (p, &pass);
|
||||
p++;
|
||||
type = bp_tracepoint;
|
||||
cond = NULL;
|
||||
while (*p)
|
||||
{
|
||||
if (*p == 'F')
|
||||
{
|
||||
type = bp_fast_tracepoint;
|
||||
p++;
|
||||
p = unpack_varlen_hex (p, &orig_size);
|
||||
}
|
||||
else if (*p == 'X')
|
||||
{
|
||||
p++;
|
||||
p = unpack_varlen_hex (p, &xlen);
|
||||
p++; /* skip the comma */
|
||||
cond = (char *) xmalloc (xlen);
|
||||
hex2bin (p, cond, xlen);
|
||||
p += 2 * xlen;
|
||||
}
|
||||
else
|
||||
/* Silently skip over anything else. */
|
||||
p++;
|
||||
}
|
||||
utp = get_uploaded_tp (num);
|
||||
utp->type = type;
|
||||
utp->addr = addr;
|
||||
utp->enabled = enabled;
|
||||
utp->step = step;
|
||||
utp->pass = pass;
|
||||
utp->cond = cond;
|
||||
utp->cond_len = xlen;
|
||||
}
|
||||
else if (*p == 'A')
|
||||
{
|
||||
p++;
|
||||
p = unpack_varlen_hex (p, &num);
|
||||
p++;
|
||||
p = unpack_varlen_hex (p, &addr);
|
||||
p++;
|
||||
utp = get_uploaded_tp (num);
|
||||
/* FIXME save the action */
|
||||
}
|
||||
else if (*p == 'S')
|
||||
{
|
||||
p++;
|
||||
p = unpack_varlen_hex (p, &num);
|
||||
p++;
|
||||
p = unpack_varlen_hex (p, &addr);
|
||||
p++;
|
||||
utp = get_uploaded_tp (num);
|
||||
/* FIXME save the action */
|
||||
}
|
||||
else if (*p == 'l')
|
||||
{
|
||||
/* No more tracepoint info, get out of the loop. */
|
||||
break;
|
||||
}
|
||||
parse_tracepoint_definition (p, utpp);
|
||||
/* Ask for another packet of tracepoint definition. */
|
||||
putpkt ("qTsP");
|
||||
getpkt (&rs->buf, &rs->buf_size, 0);
|
||||
p = rs->buf;
|
||||
}
|
||||
/* Got all the tracepoint info, now look for matches among what we
|
||||
already have in GDB. */
|
||||
for (utp = uploaded_tps; utp; utp = utp->next)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
remote_upload_trace_state_variables (struct uploaded_tsv **utsvp)
|
||||
{
|
||||
struct remote_state *rs = get_remote_state ();
|
||||
char *p;
|
||||
|
||||
/* Ask for a first packet of variable definition. */
|
||||
putpkt ("qTfV");
|
||||
getpkt (&rs->buf, &rs->buf_size, 0);
|
||||
p = rs->buf;
|
||||
while (*p && *p != 'l')
|
||||
{
|
||||
t = find_matching_tracepoint (utp);
|
||||
if (t)
|
||||
{
|
||||
printf_filtered (_("Assuming tracepoint %d is same as target's tracepoint %d.\n"),
|
||||
t->number, utp->number);
|
||||
t->number_on_target = utp->number;
|
||||
}
|
||||
else
|
||||
{
|
||||
extern void create_tracepoint_from_upload (int num, ULONGEST addr);
|
||||
create_tracepoint_from_upload (utp->number, utp->addr);
|
||||
}
|
||||
parse_tsv_definition (p, utsvp);
|
||||
/* Ask for another packet of variable definition. */
|
||||
putpkt ("qTsV");
|
||||
getpkt (&rs->buf, &rs->buf_size, 0);
|
||||
p = rs->buf;
|
||||
}
|
||||
/* FIXME free all the space */
|
||||
uploaded_tps = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
|
|
18
gdb/target.c
18
gdb/target.c
|
@ -694,6 +694,10 @@ update_current_target (void)
|
|||
INHERIT (to_trace_stop, t);
|
||||
INHERIT (to_trace_find, t);
|
||||
INHERIT (to_get_trace_state_variable_value, t);
|
||||
INHERIT (to_save_trace_data, t);
|
||||
INHERIT (to_upload_tracepoints, t);
|
||||
INHERIT (to_upload_trace_state_variables, t);
|
||||
INHERIT (to_get_raw_trace_data, t);
|
||||
INHERIT (to_set_disconnected_tracing, t);
|
||||
INHERIT (to_magic, t);
|
||||
/* Do not inherit to_memory_map. */
|
||||
|
@ -859,7 +863,7 @@ update_current_target (void)
|
|||
(void (*) (void))
|
||||
tcomplain);
|
||||
de_fault (to_get_trace_status,
|
||||
(int (*) (int *))
|
||||
(int (*) (struct trace_status *))
|
||||
return_minus_one);
|
||||
de_fault (to_trace_stop,
|
||||
(void (*) (void))
|
||||
|
@ -870,6 +874,18 @@ update_current_target (void)
|
|||
de_fault (to_get_trace_state_variable_value,
|
||||
(int (*) (int, LONGEST *))
|
||||
return_zero);
|
||||
de_fault (to_save_trace_data,
|
||||
(int (*) (char *))
|
||||
tcomplain);
|
||||
de_fault (to_upload_tracepoints,
|
||||
(int (*) (struct uploaded_tp **))
|
||||
return_zero);
|
||||
de_fault (to_upload_trace_state_variables,
|
||||
(int (*) (struct uploaded_tsv **))
|
||||
return_zero);
|
||||
de_fault (to_get_raw_trace_data,
|
||||
(LONGEST (*) (gdb_byte *, ULONGEST, LONGEST))
|
||||
tcomplain);
|
||||
de_fault (to_set_disconnected_tracing,
|
||||
(void (*) (int))
|
||||
tcomplain);
|
||||
|
|
30
gdb/target.h
30
gdb/target.h
|
@ -32,6 +32,9 @@ struct bp_target_info;
|
|||
struct regcache;
|
||||
struct target_section_table;
|
||||
struct trace_state_variable;
|
||||
struct trace_status;
|
||||
struct uploaded_tsv;
|
||||
struct uploaded_tp;
|
||||
|
||||
/* This include file defines the interface between the main part
|
||||
of the debugger, and the part which is target-specific, or
|
||||
|
@ -632,7 +635,7 @@ struct target_ops
|
|||
void (*to_trace_start) (void);
|
||||
|
||||
/* Get the current status of a tracing run. */
|
||||
int (*to_get_trace_status) (int *stop_reason);
|
||||
int (*to_get_trace_status) (struct trace_status *ts);
|
||||
|
||||
/* Stop a trace run. */
|
||||
void (*to_trace_stop) (void);
|
||||
|
@ -649,6 +652,15 @@ struct target_ops
|
|||
location pointed to by VAL, else returning 0. */
|
||||
int (*to_get_trace_state_variable_value) (int tsv, LONGEST *val);
|
||||
|
||||
int (*to_save_trace_data) (char *filename);
|
||||
|
||||
int (*to_upload_tracepoints) (struct uploaded_tp **utpp);
|
||||
|
||||
int (*to_upload_trace_state_variables) (struct uploaded_tsv **utsvp);
|
||||
|
||||
LONGEST (*to_get_raw_trace_data) (gdb_byte *buf,
|
||||
ULONGEST offset, LONGEST len);
|
||||
|
||||
/* Set the target's tracing behavior in response to unexpected
|
||||
disconnection - set VAL to 1 to keep tracing, 0 to stop. */
|
||||
void (*to_set_disconnected_tracing) (int val);
|
||||
|
@ -1319,8 +1331,8 @@ extern int target_search_memory (CORE_ADDR start_addr,
|
|||
#define target_trace_set_readonly_regions() \
|
||||
(*current_target.to_trace_set_readonly_regions) ()
|
||||
|
||||
#define target_get_trace_status(stop_reason) \
|
||||
(*current_target.to_get_trace_status) (stop_reason)
|
||||
#define target_get_trace_status(ts) \
|
||||
(*current_target.to_get_trace_status) (ts)
|
||||
|
||||
#define target_trace_stop() \
|
||||
(*current_target.to_trace_stop) ()
|
||||
|
@ -1331,6 +1343,18 @@ extern int target_search_memory (CORE_ADDR start_addr,
|
|||
#define target_get_trace_state_variable_value(tsv,val) \
|
||||
(*current_target.to_get_trace_state_variable_value) ((tsv), (val))
|
||||
|
||||
#define target_save_trace_data(filename) \
|
||||
(*current_target.to_save_trace_data) (filename)
|
||||
|
||||
#define target_upload_tracepoints(utpp) \
|
||||
(*current_target.to_upload_tracepoints) (utpp)
|
||||
|
||||
#define target_upload_trace_state_variables(utsvp) \
|
||||
(*current_target.to_upload_trace_state_variables) (utsvp)
|
||||
|
||||
#define target_get_raw_trace_data(buf,offset,len) \
|
||||
(*current_target.to_get_raw_trace_data) ((buf), (offset), (len))
|
||||
|
||||
#define target_set_disconnected_tracing(val) \
|
||||
(*current_target.to_set_disconnected_tracing) (val)
|
||||
|
||||
|
|
|
@ -1,3 +1,8 @@
|
|||
2010-01-15 Stan Shebs <stan@codesourcery.com>
|
||||
|
||||
* gdb.trace/tfile.c: New file.
|
||||
* gdb.trace/tfile.exp: New file.
|
||||
|
||||
2010-01-14 Jan Kratochvil <jan.kratochvil@redhat.com>
|
||||
|
||||
* gdb.base/pie-support.exp, gdb.base/pie-support.c: Remove.
|
||||
|
|
116
gdb/testsuite/gdb.trace/tfile.c
Normal file
116
gdb/testsuite/gdb.trace/tfile.c
Normal file
|
@ -0,0 +1,116 @@
|
|||
/* This program does two things; it generates valid trace files, and
|
||||
it can also be traced so as to test trace file creation from
|
||||
GDB. */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
char spbuf[200];
|
||||
|
||||
char trbuf[1000];
|
||||
char *trptr;
|
||||
char *tfsizeptr;
|
||||
|
||||
int testglob = 31415;
|
||||
|
||||
int
|
||||
start_trace_file (char *filename)
|
||||
{
|
||||
int fd;
|
||||
|
||||
fd = open (filename, O_WRONLY|O_CREAT|O_APPEND,
|
||||
S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
|
||||
|
||||
if (fd < 0)
|
||||
return fd;
|
||||
|
||||
/* Write a file header, with a high-bit-set char to indicate a
|
||||
binary file, plus a hint as what this file is, and a version
|
||||
number in case of future needs. */
|
||||
write (fd, "\x7fTRACE0\n", 8);
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
||||
void
|
||||
finish_trace_file (int fd)
|
||||
{
|
||||
close (fd);
|
||||
}
|
||||
|
||||
void
|
||||
write_basic_trace_file ()
|
||||
{
|
||||
int fd;
|
||||
|
||||
fd = start_trace_file ("basic.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;tstop:0;tframes:1;tcreated:1;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);
|
||||
|
||||
/* Make up a simulated trace buffer. */
|
||||
/* (Encapsulate better if we're going to do lots of this.) */
|
||||
trptr = trbuf;
|
||||
*((short *) trptr) = 1;
|
||||
trptr += sizeof (short);
|
||||
tfsizeptr = trptr;
|
||||
trptr += sizeof (int);
|
||||
*((char *) trptr) = 'M';
|
||||
trptr += 1;
|
||||
*((long long *) trptr) = (long) &testglob;
|
||||
trptr += sizeof (long long);
|
||||
*((short *) trptr) = sizeof (testglob);
|
||||
trptr += sizeof (short);
|
||||
*((int *) trptr) = testglob;
|
||||
trptr += sizeof (testglob);
|
||||
/* Go back and patch in the frame size. */
|
||||
*((int *) tfsizeptr) = trptr - tfsizeptr - sizeof (int);
|
||||
|
||||
/* 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)
|
||||
{
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char **argv, char **envp)
|
||||
{
|
||||
write_basic_trace_file ();
|
||||
|
||||
done_making_trace_files ();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
89
gdb/testsuite/gdb.trace/tfile.exp
Normal file
89
gdb/testsuite/gdb.trace/tfile.exp
Normal file
|
@ -0,0 +1,89 @@
|
|||
# Copyright 2010 Free Software Foundation, Inc.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
# Test of trace file support.
|
||||
|
||||
# Note that unlike most of the tracing tests, this can be run on
|
||||
# targets lacking tracepoint support; the program tfile.c has the
|
||||
# ability to generate synthetic trace files directly, and the tfile
|
||||
# target is available to all GDB configs.
|
||||
|
||||
load_lib "trace-support.exp";
|
||||
|
||||
if [target_info exists gdb,nofileio] {
|
||||
verbose "Skipping tfile.exp because of no fileio capabilities."
|
||||
continue
|
||||
}
|
||||
|
||||
if $tracelevel then {
|
||||
strace $tracelevel
|
||||
}
|
||||
|
||||
set prms_id 0
|
||||
set bug_id 0
|
||||
|
||||
gdb_exit
|
||||
gdb_start
|
||||
set testfile "tfile"
|
||||
set srcfile ${testfile}.c
|
||||
set binfile $objdir/$subdir/$testfile
|
||||
if { [gdb_compile "$srcdir/$subdir/$srcfile" $binfile \
|
||||
executable {debug nowarnings}] != "" } {
|
||||
untested file.exp
|
||||
return -1
|
||||
}
|
||||
gdb_reinitialize_dir $srcdir/$subdir
|
||||
|
||||
# Make sure we are starting fresh.
|
||||
remote_exec build {sh -xc rm\ -f\ basic.tf}
|
||||
|
||||
gdb_load $binfile
|
||||
|
||||
runto_main
|
||||
|
||||
gdb_test "break done_making_trace_files" "" ""
|
||||
|
||||
gdb_test "continue" "" ""
|
||||
|
||||
# tsave command would be tested here...
|
||||
|
||||
gdb_test "continue" "" ""
|
||||
|
||||
# Program has presumably exited, now target a trace file it created.
|
||||
|
||||
gdb_test "target tfile basic.tf" "Created tracepoint.*" "target tfile"
|
||||
|
||||
gdb_test "info trace" ".*tracepoint.*in write_basic_trace_file.*" \
|
||||
"info tracepoints on trace file"
|
||||
|
||||
gdb_test "tfind 0" "Found traceframe 0.*" "tfind 0 on trace file"
|
||||
|
||||
gdb_test "print testglob" " = 31415" "print testglob on trace file"
|
||||
|
||||
gdb_test "tfind" "Target failed to find requested trace frame." \
|
||||
"tfind does not find a second frame in trace file"
|
||||
|
||||
gdb_test "tstatus" \
|
||||
"Using a trace file.*
|
||||
Trace stopped by a tstop command.*
|
||||
Collected 1 trace frames.*
|
||||
Trace buffer has 256 bytes free.*
|
||||
Looking at trace frame 0, tracepoint .*" \
|
||||
"tstatus on trace file"
|
||||
|
||||
|
||||
|
||||
|
||||
|
1240
gdb/tracepoint.c
1240
gdb/tracepoint.c
File diff suppressed because it is too large
Load diff
|
@ -61,12 +61,79 @@ struct trace_state_variable
|
|||
|
||||
/* The value of a variable is a 64-bit signed integer. */
|
||||
LONGEST value;
|
||||
|
||||
/* This is true for variables that are predefined and built into
|
||||
the target. */
|
||||
int builtin;
|
||||
};
|
||||
|
||||
/* The trace status encompasses various info about the general state
|
||||
of the tracing run. */
|
||||
|
||||
enum trace_stop_reason
|
||||
{
|
||||
trace_stop_reason_unknown,
|
||||
trace_never_run,
|
||||
tstop_command,
|
||||
trace_buffer_full,
|
||||
trace_disconnected,
|
||||
tracepoint_passcount
|
||||
};
|
||||
|
||||
extern unsigned long trace_running_p;
|
||||
struct trace_status
|
||||
{
|
||||
/* This is true if the status is coming from a file rather
|
||||
than a live target. */
|
||||
int from_file;
|
||||
|
||||
/* This is true if the value of the running field is known. */
|
||||
int running_known;
|
||||
|
||||
int running;
|
||||
|
||||
enum trace_stop_reason stop_reason;
|
||||
|
||||
int stopping_tracepoint;
|
||||
|
||||
int traceframe_count;
|
||||
|
||||
size_t buffer_size;
|
||||
|
||||
size_t buffer_free;
|
||||
};
|
||||
|
||||
struct trace_status *current_trace_status (void);
|
||||
|
||||
extern char *default_collect;
|
||||
|
||||
/* Struct to collect random info about tracepoints on the target. */
|
||||
|
||||
struct uploaded_tp {
|
||||
int number;
|
||||
enum bptype type;
|
||||
ULONGEST addr;
|
||||
int enabled;
|
||||
int step;
|
||||
int pass;
|
||||
int orig_size;
|
||||
char *cond;
|
||||
int numactions;
|
||||
char *actions[100];
|
||||
int num_step_actions;
|
||||
char *step_actions[100];
|
||||
struct uploaded_tp *next;
|
||||
};
|
||||
|
||||
/* Struct recording info about trace state variables on the target. */
|
||||
|
||||
struct uploaded_tsv {
|
||||
const char *name;
|
||||
int number;
|
||||
LONGEST initial_value;
|
||||
int builtin;
|
||||
struct uploaded_tsv *next;
|
||||
};
|
||||
|
||||
/* A hook used to notify the UI of tracepoint operations. */
|
||||
|
||||
extern void (*deprecated_trace_find_hook) (char *arg, int from_tty);
|
||||
|
@ -81,4 +148,15 @@ extern void while_stepping_pseudocommand (char *args, int from_tty);
|
|||
|
||||
extern struct trace_state_variable *find_trace_state_variable (const char *name);
|
||||
|
||||
extern void parse_trace_status (char *line, struct trace_status *ts);
|
||||
|
||||
extern void parse_tracepoint_definition (char *line, struct uploaded_tp **utpp);
|
||||
extern void parse_tsv_definition (char *line, struct uploaded_tsv **utsvp);
|
||||
|
||||
extern struct uploaded_tp *get_uploaded_tp (int num, ULONGEST addr,
|
||||
struct uploaded_tp **utpp);
|
||||
extern struct breakpoint *create_tracepoint_from_upload (struct uploaded_tp *utp);
|
||||
extern void merge_uploaded_tracepoints (struct uploaded_tp **utpp);
|
||||
extern void merge_uploaded_trace_state_variables (struct uploaded_tsv **utsvp);
|
||||
|
||||
#endif /* TRACEPOINT_H */
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue