gdb/
2013-03-14 Hui Zhu <hui@codesourcery.com> Yao Qi <yao@codesourcery.com> * Makefile.in (REMOTE_OBS): Add ctf.o. (SFILES): Add ctf.c. (HFILES_NO_SRCDIR): Add ctf.h. * ctf.c, ctf.h: New files. * tracepoint.c: Include 'ctf.h'. (collect_pseudocommand): Remove static. (trace_save_command): Parse option "-ctf". Produce different trace file writers per option. Adjust output message. (trace_save_tfile, trace_save_ctf): New. * tracepoint.h (trace_save_tfile, trace_save_ctf): Declare. * mi/mi-main.c: Include 'ctf.h'. (mi_cmd_trace_save): Handle option '-ctf'. Call either trace_save_tfile or trace_save_ctf. * NEWS: Mention these changes. gdb/doc/ 2013-03-14 Hui Zhu <hui@codesourcery.com> Yao Qi <yao@codesourcery.com> * gdb.texinfo (Trace Files): Add "tsave -ctf".
This commit is contained in:
parent
6f2ef5f590
commit
d0353e7691
10 changed files with 777 additions and 19 deletions
|
@ -1,3 +1,22 @@
|
||||||
|
2013-03-14 Hui Zhu <hui@codesourcery.com>
|
||||||
|
Yao Qi <yao@codesourcery.com>
|
||||||
|
|
||||||
|
* Makefile.in (REMOTE_OBS): Add ctf.o.
|
||||||
|
(SFILES): Add ctf.c.
|
||||||
|
(HFILES_NO_SRCDIR): Add ctf.h.
|
||||||
|
* ctf.c, ctf.h: New files.
|
||||||
|
* tracepoint.c: Include 'ctf.h'.
|
||||||
|
(collect_pseudocommand): Remove static.
|
||||||
|
(trace_save_command): Parse option "-ctf".
|
||||||
|
Produce different trace file writers per option.
|
||||||
|
Adjust output message.
|
||||||
|
(trace_save_tfile, trace_save_ctf): New.
|
||||||
|
* tracepoint.h (trace_save_tfile, trace_save_ctf): Declare.
|
||||||
|
* mi/mi-main.c: Include 'ctf.h'.
|
||||||
|
(mi_cmd_trace_save): Handle option '-ctf'. Call either
|
||||||
|
trace_save_tfile or trace_save_ctf.
|
||||||
|
* NEWS: Mention these changes.
|
||||||
|
|
||||||
2013-03-14 Yao Qi <yao@codesourcery.com>
|
2013-03-14 Yao Qi <yao@codesourcery.com>
|
||||||
|
|
||||||
* tracepoint.c (trace_file_writer_xfree): New.
|
* tracepoint.c (trace_file_writer_xfree): New.
|
||||||
|
|
|
@ -511,7 +511,7 @@ SER_HARDWIRE = @SER_HARDWIRE@
|
||||||
# The `remote' debugging target is supported for most architectures,
|
# The `remote' debugging target is supported for most architectures,
|
||||||
# but not all (e.g. 960)
|
# but not all (e.g. 960)
|
||||||
REMOTE_OBS = remote.o dcache.o tracepoint.o ax-general.o ax-gdb.o remote-fileio.o \
|
REMOTE_OBS = remote.o dcache.o tracepoint.o ax-general.o ax-gdb.o remote-fileio.o \
|
||||||
remote-notif.o
|
remote-notif.o ctf.o
|
||||||
|
|
||||||
# This is remote-sim.o if a simulator is to be linked in.
|
# This is remote-sim.o if a simulator is to be linked in.
|
||||||
SIM_OBS = @SIM_OBS@
|
SIM_OBS = @SIM_OBS@
|
||||||
|
@ -760,7 +760,7 @@ SFILES = ada-exp.y ada-lang.c ada-typeprint.c ada-valprint.c ada-tasks.c \
|
||||||
regset.c sol-thread.c windows-termcap.c \
|
regset.c sol-thread.c windows-termcap.c \
|
||||||
common/gdb_vecs.c common/common-utils.c common/xml-utils.c \
|
common/gdb_vecs.c common/common-utils.c common/xml-utils.c \
|
||||||
common/ptid.c common/buffer.c gdb-dlfcn.c common/agent.c \
|
common/ptid.c common/buffer.c gdb-dlfcn.c common/agent.c \
|
||||||
common/format.c btrace.c record-btrace.c
|
common/format.c btrace.c record-btrace.c ctf.c
|
||||||
|
|
||||||
LINTFILES = $(SFILES) $(YYFILES) $(CONFIG_SRCS) init.c
|
LINTFILES = $(SFILES) $(YYFILES) $(CONFIG_SRCS) init.c
|
||||||
|
|
||||||
|
@ -837,7 +837,8 @@ gnulib/import/stddef.in.h gnulib/import/inttypes.in.h inline-frame.h skip.h \
|
||||||
common/common-utils.h common/xml-utils.h common/buffer.h common/ptid.h \
|
common/common-utils.h common/xml-utils.h common/buffer.h common/ptid.h \
|
||||||
common/format.h common/host-defs.h utils.h common/queue.h \
|
common/format.h common/host-defs.h utils.h common/queue.h \
|
||||||
common/linux-osdata.h gdb-dlfcn.h auto-load.h probe.h stap-probe.h \
|
common/linux-osdata.h gdb-dlfcn.h auto-load.h probe.h stap-probe.h \
|
||||||
gdb_bfd.h sparc-ravenscar-thread.h ppc-ravenscar-thread.h common/linux-btrace.h
|
gdb_bfd.h sparc-ravenscar-thread.h ppc-ravenscar-thread.h common/linux-btrace.h \
|
||||||
|
ctf.h
|
||||||
|
|
||||||
# Header files that already have srcdir in them, or which are in objdir.
|
# Header files that already have srcdir in them, or which are in objdir.
|
||||||
|
|
||||||
|
|
8
gdb/NEWS
8
gdb/NEWS
|
@ -3,6 +3,14 @@
|
||||||
|
|
||||||
*** Changes since GDB 7.6
|
*** Changes since GDB 7.6
|
||||||
|
|
||||||
|
* The command 'tsave' can now support new option '-ctf' to save trace
|
||||||
|
buffer in Common Trace Format.
|
||||||
|
|
||||||
|
* MI changes
|
||||||
|
|
||||||
|
** The -trace-save MI command can optionally save trace buffer in Common
|
||||||
|
Trace Format now.
|
||||||
|
|
||||||
*** Changes in GDB 7.6
|
*** Changes in GDB 7.6
|
||||||
|
|
||||||
* Target record has been renamed to record-full.
|
* Target record has been renamed to record-full.
|
||||||
|
|
647
gdb/ctf.c
Normal file
647
gdb/ctf.c
Normal file
|
@ -0,0 +1,647 @@
|
||||||
|
/* CTF format support.
|
||||||
|
|
||||||
|
Copyright (C) 2012-2013 Free Software Foundation, Inc.
|
||||||
|
Contributed by Hui Zhu <hui_zhu@mentor.com>
|
||||||
|
Contributed by Yao Qi <yao@codesourcery.com>
|
||||||
|
|
||||||
|
This file is part of GDB.
|
||||||
|
|
||||||
|
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/>. */
|
||||||
|
|
||||||
|
#include "defs.h"
|
||||||
|
#include "ctf.h"
|
||||||
|
#include "tracepoint.h"
|
||||||
|
#include "regcache.h"
|
||||||
|
|
||||||
|
#include <ctype.h>
|
||||||
|
|
||||||
|
/* GDB saves trace buffers and other information (such as trace
|
||||||
|
status) got from the remote target into Common Trace Format (CTF).
|
||||||
|
The following types of information are expected to save in CTF:
|
||||||
|
|
||||||
|
1. The length (in bytes) of register cache. Event "register" will
|
||||||
|
be defined in metadata, which includes the length.
|
||||||
|
|
||||||
|
2. Trace status. Not implemented yet in CTF writer.
|
||||||
|
|
||||||
|
3. Uploaded trace variables and tracepoints. Not implemented yet
|
||||||
|
in CTF writer.
|
||||||
|
|
||||||
|
4. Trace frames. Each trace frame is composed by several blocks
|
||||||
|
of different types ('R', 'M', 'V'). One trace frame is saved in
|
||||||
|
one CTF packet and the blocks of this frame are saved as events.
|
||||||
|
4.1: The trace frame related information (such as the number of
|
||||||
|
tracepoint associated with this frame) is saved in the packet
|
||||||
|
context.
|
||||||
|
4.2: The block 'M', 'R' and 'V' are saved in event "memory",
|
||||||
|
"register" and "tsv" respectively.
|
||||||
|
4.3: When iterating over events, babeltrace can't tell iterator
|
||||||
|
goes to a new packet, so we need a marker or anchor to tell GDB
|
||||||
|
that iterator goes into a new packet or frame. We define event
|
||||||
|
"frame". */
|
||||||
|
|
||||||
|
#define CTF_MAGIC 0xC1FC1FC1
|
||||||
|
#define CTF_SAVE_MAJOR 1
|
||||||
|
#define CTF_SAVE_MINOR 8
|
||||||
|
|
||||||
|
#define CTF_METADATA_NAME "metadata"
|
||||||
|
#define CTF_DATASTREAM_NAME "datastream"
|
||||||
|
|
||||||
|
/* Reserved event id. */
|
||||||
|
|
||||||
|
#define CTF_EVENT_ID_REGISTER 0
|
||||||
|
#define CTF_EVENT_ID_TSV 1
|
||||||
|
#define CTF_EVENT_ID_MEMORY 2
|
||||||
|
#define CTF_EVENT_ID_FRAME 3
|
||||||
|
|
||||||
|
/* The state kept while writing the CTF datastream file. */
|
||||||
|
|
||||||
|
struct trace_write_handler
|
||||||
|
{
|
||||||
|
/* File descriptor of metadata. */
|
||||||
|
FILE *metadata_fd;
|
||||||
|
/* File descriptor of traceframes. */
|
||||||
|
FILE *datastream_fd;
|
||||||
|
|
||||||
|
/* This is the content size of the current packet. */
|
||||||
|
size_t content_size;
|
||||||
|
|
||||||
|
/* This is the start offset of current packet. */
|
||||||
|
long packet_start;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Write metadata in FORMAT. */
|
||||||
|
|
||||||
|
static void
|
||||||
|
ctf_save_write_metadata (struct trace_write_handler *handler,
|
||||||
|
const char *format, ...)
|
||||||
|
{
|
||||||
|
va_list args;
|
||||||
|
|
||||||
|
va_start (args, format);
|
||||||
|
if (vfprintf (handler->metadata_fd, format, args) < 0)
|
||||||
|
error (_("Unable to write metadata file (%s)"),
|
||||||
|
safe_strerror (errno));
|
||||||
|
va_end (args);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Write BUF of length SIZE to datastream file represented by
|
||||||
|
HANDLER. */
|
||||||
|
|
||||||
|
static int
|
||||||
|
ctf_save_write (struct trace_write_handler *handler,
|
||||||
|
const gdb_byte *buf, size_t size)
|
||||||
|
{
|
||||||
|
if (fwrite (buf, size, 1, handler->datastream_fd) != 1)
|
||||||
|
error (_("Unable to write file for saving trace data (%s)"),
|
||||||
|
safe_strerror (errno));
|
||||||
|
|
||||||
|
handler->content_size += size;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Write a unsigned 32-bit integer to datastream file represented by
|
||||||
|
HANDLER. */
|
||||||
|
|
||||||
|
#define ctf_save_write_uint32(HANDLER, U32) \
|
||||||
|
ctf_save_write (HANDLER, (gdb_byte *) &U32, 4)
|
||||||
|
|
||||||
|
/* Set datastream file position. Update HANDLER->content_size
|
||||||
|
if WHENCE is SEEK_CUR. */
|
||||||
|
|
||||||
|
static int
|
||||||
|
ctf_save_fseek (struct trace_write_handler *handler, long offset,
|
||||||
|
int whence)
|
||||||
|
{
|
||||||
|
gdb_assert (whence != SEEK_END);
|
||||||
|
gdb_assert (whence != SEEK_SET
|
||||||
|
|| offset <= handler->content_size + handler->packet_start);
|
||||||
|
|
||||||
|
if (fseek (handler->datastream_fd, offset, whence))
|
||||||
|
error (_("Unable to seek file for saving trace data (%s)"),
|
||||||
|
safe_strerror (errno));
|
||||||
|
|
||||||
|
if (whence == SEEK_CUR)
|
||||||
|
handler->content_size += offset;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Change the datastream file position to align on ALIGN_SIZE,
|
||||||
|
and write BUF to datastream file. The size of BUF is SIZE. */
|
||||||
|
|
||||||
|
static int
|
||||||
|
ctf_save_align_write (struct trace_write_handler *handler,
|
||||||
|
const gdb_byte *buf,
|
||||||
|
size_t size, size_t align_size)
|
||||||
|
{
|
||||||
|
long offset
|
||||||
|
= (align_up (handler->content_size, align_size)
|
||||||
|
- handler->content_size);
|
||||||
|
|
||||||
|
if (ctf_save_fseek (handler, offset, SEEK_CUR))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (ctf_save_write (handler, buf, size))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Write events to next new packet. */
|
||||||
|
|
||||||
|
static void
|
||||||
|
ctf_save_next_packet (struct trace_write_handler *handler)
|
||||||
|
{
|
||||||
|
handler->packet_start += (handler->content_size + 4);
|
||||||
|
ctf_save_fseek (handler, handler->packet_start, SEEK_SET);
|
||||||
|
handler->content_size = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Write the CTF metadata header. */
|
||||||
|
|
||||||
|
static void
|
||||||
|
ctf_save_metadata_header (struct trace_write_handler *handler)
|
||||||
|
{
|
||||||
|
const char metadata_fmt[] =
|
||||||
|
"\ntrace {\n"
|
||||||
|
" major = %u;\n"
|
||||||
|
" minor = %u;\n"
|
||||||
|
" byte_order = %s;\n" /* be or le */
|
||||||
|
" packet.header := struct {\n"
|
||||||
|
" uint32_t magic;\n"
|
||||||
|
" };\n"
|
||||||
|
"};\n"
|
||||||
|
"\n"
|
||||||
|
"stream {\n"
|
||||||
|
" packet.context := struct {\n"
|
||||||
|
" uint32_t content_size;\n"
|
||||||
|
" uint32_t packet_size;\n"
|
||||||
|
" uint16_t tpnum;\n"
|
||||||
|
" };\n"
|
||||||
|
" event.header := struct {\n"
|
||||||
|
" uint32_t id;\n"
|
||||||
|
" };\n"
|
||||||
|
"};\n";
|
||||||
|
|
||||||
|
ctf_save_write_metadata (handler, "/* CTF %d.%d */\n",
|
||||||
|
CTF_SAVE_MAJOR, CTF_SAVE_MINOR);
|
||||||
|
ctf_save_write_metadata (handler,
|
||||||
|
"typealias integer { size = 8; align = 8; "
|
||||||
|
"signed = false; encoding = ascii;}"
|
||||||
|
" := ascii;\n");
|
||||||
|
ctf_save_write_metadata (handler,
|
||||||
|
"typealias integer { size = 8; align = 8; "
|
||||||
|
"signed = false; }"
|
||||||
|
" := uint8_t;\n");
|
||||||
|
ctf_save_write_metadata (handler,
|
||||||
|
"typealias integer { size = 16; align = 16;"
|
||||||
|
"signed = false; } := uint16_t;\n");
|
||||||
|
ctf_save_write_metadata (handler,
|
||||||
|
"typealias integer { size = 32; align = 32;"
|
||||||
|
"signed = false; } := uint32_t;\n");
|
||||||
|
ctf_save_write_metadata (handler,
|
||||||
|
"typealias integer { size = 64; align = 64;"
|
||||||
|
"signed = false; base = hex;}"
|
||||||
|
" := uint64_t;\n");
|
||||||
|
ctf_save_write_metadata (handler, "\n");
|
||||||
|
|
||||||
|
ctf_save_write_metadata (handler, metadata_fmt,
|
||||||
|
CTF_SAVE_MAJOR, CTF_SAVE_MINOR,
|
||||||
|
BYTE_ORDER == LITTLE_ENDIAN ? "le" : "be");
|
||||||
|
ctf_save_write_metadata (handler, "\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* CTF trace writer. */
|
||||||
|
|
||||||
|
struct ctf_trace_file_writer
|
||||||
|
{
|
||||||
|
struct trace_file_writer base;
|
||||||
|
|
||||||
|
/* States related to writing CTF trace file. */
|
||||||
|
struct trace_write_handler tcs;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* This is the implementation of trace_file_write_ops method
|
||||||
|
dtor. */
|
||||||
|
|
||||||
|
static void
|
||||||
|
ctf_dtor (struct trace_file_writer *self)
|
||||||
|
{
|
||||||
|
struct ctf_trace_file_writer *writer
|
||||||
|
= (struct ctf_trace_file_writer *) self;
|
||||||
|
|
||||||
|
if (writer->tcs.metadata_fd != NULL)
|
||||||
|
fclose (writer->tcs.metadata_fd);
|
||||||
|
|
||||||
|
if (writer->tcs.datastream_fd != NULL)
|
||||||
|
fclose (writer->tcs.datastream_fd);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/* This is the implementation of trace_file_write_ops method
|
||||||
|
target_save. */
|
||||||
|
|
||||||
|
static int
|
||||||
|
ctf_target_save (struct trace_file_writer *self,
|
||||||
|
const char *dirname)
|
||||||
|
{
|
||||||
|
/* Don't support save trace file to CTF format in the target. */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* This is the implementation of trace_file_write_ops method
|
||||||
|
start. It creates the directory DIRNAME, metadata and datastream
|
||||||
|
in the directory. */
|
||||||
|
|
||||||
|
static void
|
||||||
|
ctf_start (struct trace_file_writer *self, const char *dirname)
|
||||||
|
{
|
||||||
|
char *file_name;
|
||||||
|
struct cleanup *old_chain;
|
||||||
|
struct ctf_trace_file_writer *writer
|
||||||
|
= (struct ctf_trace_file_writer *) self;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
/* Create DIRNAME. */
|
||||||
|
if (mkdir (dirname, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH)
|
||||||
|
&& errno != EEXIST)
|
||||||
|
error (_("Unable to open directory '%s' for saving trace data (%s)"),
|
||||||
|
dirname, safe_strerror (errno));
|
||||||
|
|
||||||
|
memset (&writer->tcs, '\0', sizeof (writer->tcs));
|
||||||
|
|
||||||
|
file_name = xstrprintf ("%s/%s", dirname, CTF_METADATA_NAME);
|
||||||
|
old_chain = make_cleanup (xfree, file_name);
|
||||||
|
|
||||||
|
writer->tcs.metadata_fd = fopen (file_name, "w");
|
||||||
|
if (writer->tcs.metadata_fd == NULL)
|
||||||
|
error (_("Unable to open file '%s' for saving trace data (%s)"),
|
||||||
|
file_name, safe_strerror (errno));
|
||||||
|
do_cleanups (old_chain);
|
||||||
|
|
||||||
|
ctf_save_metadata_header (&writer->tcs);
|
||||||
|
|
||||||
|
file_name = xstrprintf ("%s/%s", dirname, CTF_DATASTREAM_NAME);
|
||||||
|
old_chain = make_cleanup (xfree, file_name);
|
||||||
|
writer->tcs.datastream_fd = fopen (file_name, "w");
|
||||||
|
if (writer->tcs.datastream_fd == NULL)
|
||||||
|
error (_("Unable to open file '%s' for saving trace data (%s)"),
|
||||||
|
file_name, safe_strerror (errno));
|
||||||
|
do_cleanups (old_chain);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* This is the implementation of trace_file_write_ops method
|
||||||
|
write_header. Write the types of events on trace variable and
|
||||||
|
frame. */
|
||||||
|
|
||||||
|
static void
|
||||||
|
ctf_write_header (struct trace_file_writer *self)
|
||||||
|
{
|
||||||
|
struct ctf_trace_file_writer *writer
|
||||||
|
= (struct ctf_trace_file_writer *) self;
|
||||||
|
|
||||||
|
|
||||||
|
ctf_save_write_metadata (&writer->tcs, "\n");
|
||||||
|
ctf_save_write_metadata (&writer->tcs,
|
||||||
|
"event {\n\tname = \"memory\";\n\tid = %u;\n"
|
||||||
|
"\tfields := struct { \n"
|
||||||
|
"\t\tuint64_t address;\n"
|
||||||
|
"\t\tuint16_t length;\n"
|
||||||
|
"\t\tuint8_t contents[length];\n"
|
||||||
|
"\t};\n"
|
||||||
|
"};\n", CTF_EVENT_ID_MEMORY);
|
||||||
|
|
||||||
|
ctf_save_write_metadata (&writer->tcs, "\n");
|
||||||
|
ctf_save_write_metadata (&writer->tcs,
|
||||||
|
"event {\n\tname = \"tsv\";\n\tid = %u;\n"
|
||||||
|
"\tfields := struct { \n"
|
||||||
|
"\t\tuint64_t val;\n"
|
||||||
|
"\t\tuint32_t num;\n"
|
||||||
|
"\t};\n"
|
||||||
|
"};\n", CTF_EVENT_ID_TSV);
|
||||||
|
|
||||||
|
ctf_save_write_metadata (&writer->tcs, "\n");
|
||||||
|
ctf_save_write_metadata (&writer->tcs,
|
||||||
|
"event {\n\tname = \"frame\";\n\tid = %u;\n"
|
||||||
|
"\tfields := struct { \n"
|
||||||
|
"\t};\n"
|
||||||
|
"};\n", CTF_EVENT_ID_FRAME);
|
||||||
|
|
||||||
|
gdb_assert (writer->tcs.content_size == 0);
|
||||||
|
gdb_assert (writer->tcs.packet_start == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* This is the implementation of trace_file_write_ops method
|
||||||
|
write_regblock_type. Write the type of register event in
|
||||||
|
metadata. */
|
||||||
|
|
||||||
|
static void
|
||||||
|
ctf_write_regblock_type (struct trace_file_writer *self, int size)
|
||||||
|
{
|
||||||
|
struct ctf_trace_file_writer *writer
|
||||||
|
= (struct ctf_trace_file_writer *) self;
|
||||||
|
|
||||||
|
ctf_save_write_metadata (&writer->tcs, "\n");
|
||||||
|
|
||||||
|
ctf_save_write_metadata (&writer->tcs,
|
||||||
|
"event {\n\tname = \"register\";\n\tid = %u;\n"
|
||||||
|
"\tfields := struct { \n"
|
||||||
|
"\t\tascii contents[%d];\n"
|
||||||
|
"\t};\n"
|
||||||
|
"};\n",
|
||||||
|
CTF_EVENT_ID_REGISTER, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* This is the implementation of trace_file_write_ops method
|
||||||
|
write_status. */
|
||||||
|
|
||||||
|
static void
|
||||||
|
ctf_write_status (struct trace_file_writer *self,
|
||||||
|
struct trace_status *ts)
|
||||||
|
{
|
||||||
|
/* It is not supported yet to write trace status into CTF trace
|
||||||
|
data. */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* This is the implementation of trace_file_write_ops method
|
||||||
|
write_uploaded_tsv. */
|
||||||
|
|
||||||
|
static void
|
||||||
|
ctf_write_uploaded_tsv (struct trace_file_writer *self,
|
||||||
|
struct uploaded_tsv *tsv)
|
||||||
|
{
|
||||||
|
/* It is not supported yet to write uploaded trace variables
|
||||||
|
into CTF trace data. */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* This is the implementation of trace_file_write_ops method
|
||||||
|
write_uploaded_tp. */
|
||||||
|
|
||||||
|
static void
|
||||||
|
ctf_write_uploaded_tp (struct trace_file_writer *self,
|
||||||
|
struct uploaded_tp *tp)
|
||||||
|
{
|
||||||
|
/* It is not supported yet to write uploaded tracepoints
|
||||||
|
into CTF trace data. */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* This is the implementation of trace_file_write_ops method
|
||||||
|
write_definition_end. */
|
||||||
|
|
||||||
|
static void
|
||||||
|
ctf_write_definition_end (struct trace_file_writer *self)
|
||||||
|
{
|
||||||
|
/* Nothing to do for CTF. */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The minimal file size of data stream. It is required by
|
||||||
|
babeltrace. */
|
||||||
|
|
||||||
|
#define CTF_FILE_MIN_SIZE 4096
|
||||||
|
|
||||||
|
/* This is the implementation of trace_file_write_ops method
|
||||||
|
end. */
|
||||||
|
|
||||||
|
static void
|
||||||
|
ctf_end (struct trace_file_writer *self)
|
||||||
|
{
|
||||||
|
struct ctf_trace_file_writer *writer = (struct ctf_trace_file_writer *) self;
|
||||||
|
|
||||||
|
gdb_assert (writer->tcs.content_size == 0);
|
||||||
|
/* The babeltrace requires or assumes that the size of datastream
|
||||||
|
file is greater than 4096 bytes. If we don't generate enough
|
||||||
|
packets and events, create a fake packet which has zero event,
|
||||||
|
to use up the space. */
|
||||||
|
if (writer->tcs.packet_start < CTF_FILE_MIN_SIZE)
|
||||||
|
{
|
||||||
|
uint32_t u32;
|
||||||
|
|
||||||
|
/* magic. */
|
||||||
|
u32 = CTF_MAGIC;
|
||||||
|
ctf_save_write_uint32 (&writer->tcs, u32);
|
||||||
|
|
||||||
|
/* content_size. */
|
||||||
|
u32 = 0;
|
||||||
|
ctf_save_write_uint32 (&writer->tcs, u32);
|
||||||
|
|
||||||
|
/* packet_size. */
|
||||||
|
u32 = 12;
|
||||||
|
if (writer->tcs.packet_start + u32 < CTF_FILE_MIN_SIZE)
|
||||||
|
u32 = CTF_FILE_MIN_SIZE - writer->tcs.packet_start;
|
||||||
|
|
||||||
|
u32 *= TARGET_CHAR_BIT;
|
||||||
|
ctf_save_write_uint32 (&writer->tcs, u32);
|
||||||
|
|
||||||
|
/* tpnum. */
|
||||||
|
u32 = 0;
|
||||||
|
ctf_save_write (&writer->tcs, (gdb_byte *) &u32, 2);
|
||||||
|
|
||||||
|
/* Enlarge the file to CTF_FILE_MIN_SIZE is it is still less
|
||||||
|
than that. */
|
||||||
|
if (CTF_FILE_MIN_SIZE
|
||||||
|
> (writer->tcs.packet_start + writer->tcs.content_size))
|
||||||
|
{
|
||||||
|
gdb_byte b = 0;
|
||||||
|
|
||||||
|
/* Fake the content size to avoid assertion failure in
|
||||||
|
ctf_save_fseek. */
|
||||||
|
writer->tcs.content_size = (CTF_FILE_MIN_SIZE
|
||||||
|
- 1 - writer->tcs.packet_start);
|
||||||
|
ctf_save_fseek (&writer->tcs, CTF_FILE_MIN_SIZE - 1,
|
||||||
|
SEEK_SET);
|
||||||
|
ctf_save_write (&writer->tcs, &b, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* This is the implementation of trace_frame_write_ops method
|
||||||
|
start. */
|
||||||
|
|
||||||
|
static void
|
||||||
|
ctf_write_frame_start (struct trace_file_writer *self, uint16_t tpnum)
|
||||||
|
{
|
||||||
|
struct ctf_trace_file_writer *writer
|
||||||
|
= (struct ctf_trace_file_writer *) self;
|
||||||
|
uint32_t id = CTF_EVENT_ID_FRAME;
|
||||||
|
uint32_t u32;
|
||||||
|
|
||||||
|
/* Step 1: Write packet context. */
|
||||||
|
/* magic. */
|
||||||
|
u32 = CTF_MAGIC;
|
||||||
|
ctf_save_write_uint32 (&writer->tcs, u32);
|
||||||
|
/* content_size and packet_size.. We still don't know the value,
|
||||||
|
write it later. */
|
||||||
|
ctf_save_fseek (&writer->tcs, 4, SEEK_CUR);
|
||||||
|
ctf_save_fseek (&writer->tcs, 4, SEEK_CUR);
|
||||||
|
/* Tracepoint number. */
|
||||||
|
ctf_save_write (&writer->tcs, (gdb_byte *) &tpnum, 2);
|
||||||
|
|
||||||
|
/* Step 2: Write event "frame". */
|
||||||
|
/* Event Id. */
|
||||||
|
ctf_save_align_write (&writer->tcs, (gdb_byte *) &id, 4, 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* This is the implementation of trace_frame_write_ops method
|
||||||
|
write_r_block. */
|
||||||
|
|
||||||
|
static void
|
||||||
|
ctf_write_frame_r_block (struct trace_file_writer *self,
|
||||||
|
gdb_byte *buf, int32_t size)
|
||||||
|
{
|
||||||
|
struct ctf_trace_file_writer *writer
|
||||||
|
= (struct ctf_trace_file_writer *) self;
|
||||||
|
uint32_t id = CTF_EVENT_ID_REGISTER;
|
||||||
|
|
||||||
|
/* Event Id. */
|
||||||
|
ctf_save_align_write (&writer->tcs, (gdb_byte *) &id, 4, 4);
|
||||||
|
|
||||||
|
/* array contents. */
|
||||||
|
ctf_save_align_write (&writer->tcs, buf, size, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* This is the implementation of trace_frame_write_ops method
|
||||||
|
write_m_block_header. */
|
||||||
|
|
||||||
|
static void
|
||||||
|
ctf_write_frame_m_block_header (struct trace_file_writer *self,
|
||||||
|
uint64_t addr, uint16_t length)
|
||||||
|
{
|
||||||
|
struct ctf_trace_file_writer *writer
|
||||||
|
= (struct ctf_trace_file_writer *) self;
|
||||||
|
uint32_t event_id = CTF_EVENT_ID_MEMORY;
|
||||||
|
|
||||||
|
/* Event Id. */
|
||||||
|
ctf_save_align_write (&writer->tcs, (gdb_byte *) &event_id, 4, 4);
|
||||||
|
|
||||||
|
/* Address. */
|
||||||
|
ctf_save_align_write (&writer->tcs, (gdb_byte *) &addr, 8, 8);
|
||||||
|
|
||||||
|
/* Length. */
|
||||||
|
ctf_save_align_write (&writer->tcs, (gdb_byte *) &length, 2, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* This is the implementation of trace_frame_write_ops method
|
||||||
|
write_m_block_memory. */
|
||||||
|
|
||||||
|
static void
|
||||||
|
ctf_write_frame_m_block_memory (struct trace_file_writer *self,
|
||||||
|
gdb_byte *buf, uint16_t length)
|
||||||
|
{
|
||||||
|
struct ctf_trace_file_writer *writer
|
||||||
|
= (struct ctf_trace_file_writer *) self;
|
||||||
|
|
||||||
|
/* Contents. */
|
||||||
|
ctf_save_align_write (&writer->tcs, (gdb_byte *) buf, length, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* This is the implementation of trace_frame_write_ops method
|
||||||
|
write_v_block. */
|
||||||
|
|
||||||
|
static void
|
||||||
|
ctf_write_frame_v_block (struct trace_file_writer *self,
|
||||||
|
int32_t num, uint64_t val)
|
||||||
|
{
|
||||||
|
struct ctf_trace_file_writer *writer
|
||||||
|
= (struct ctf_trace_file_writer *) self;
|
||||||
|
uint32_t id = CTF_EVENT_ID_TSV;
|
||||||
|
|
||||||
|
/* Event Id. */
|
||||||
|
ctf_save_align_write (&writer->tcs, (gdb_byte *) &id, 4, 4);
|
||||||
|
|
||||||
|
/* val. */
|
||||||
|
ctf_save_align_write (&writer->tcs, (gdb_byte *) &val, 8, 8);
|
||||||
|
/* num. */
|
||||||
|
ctf_save_align_write (&writer->tcs, (gdb_byte *) &num, 4, 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* This is the implementation of trace_frame_write_ops method
|
||||||
|
end. */
|
||||||
|
|
||||||
|
static void
|
||||||
|
ctf_write_frame_end (struct trace_file_writer *self)
|
||||||
|
{
|
||||||
|
struct ctf_trace_file_writer *writer
|
||||||
|
= (struct ctf_trace_file_writer *) self;
|
||||||
|
uint32_t u32;
|
||||||
|
uint32_t t;
|
||||||
|
|
||||||
|
/* Write the content size to packet header. */
|
||||||
|
ctf_save_fseek (&writer->tcs, writer->tcs.packet_start + 4,
|
||||||
|
SEEK_SET);
|
||||||
|
u32 = writer->tcs.content_size * TARGET_CHAR_BIT;
|
||||||
|
|
||||||
|
t = writer->tcs.content_size;
|
||||||
|
ctf_save_write_uint32 (&writer->tcs, u32);
|
||||||
|
|
||||||
|
/* Write the packet size. */
|
||||||
|
u32 += 4 * TARGET_CHAR_BIT;
|
||||||
|
ctf_save_write_uint32 (&writer->tcs, u32);
|
||||||
|
|
||||||
|
writer->tcs.content_size = t;
|
||||||
|
|
||||||
|
/* Write zero at the end of the packet. */
|
||||||
|
ctf_save_fseek (&writer->tcs, writer->tcs.packet_start + t,
|
||||||
|
SEEK_SET);
|
||||||
|
u32 = 0;
|
||||||
|
ctf_save_write_uint32 (&writer->tcs, u32);
|
||||||
|
writer->tcs.content_size = t;
|
||||||
|
|
||||||
|
ctf_save_next_packet (&writer->tcs);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Operations to write various types of trace frames into CTF
|
||||||
|
format. */
|
||||||
|
|
||||||
|
static const struct trace_frame_write_ops ctf_write_frame_ops =
|
||||||
|
{
|
||||||
|
ctf_write_frame_start,
|
||||||
|
ctf_write_frame_r_block,
|
||||||
|
ctf_write_frame_m_block_header,
|
||||||
|
ctf_write_frame_m_block_memory,
|
||||||
|
ctf_write_frame_v_block,
|
||||||
|
ctf_write_frame_end,
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Operations to write trace buffers into CTF format. */
|
||||||
|
|
||||||
|
static const struct trace_file_write_ops ctf_write_ops =
|
||||||
|
{
|
||||||
|
ctf_dtor,
|
||||||
|
ctf_target_save,
|
||||||
|
ctf_start,
|
||||||
|
ctf_write_header,
|
||||||
|
ctf_write_regblock_type,
|
||||||
|
ctf_write_status,
|
||||||
|
ctf_write_uploaded_tsv,
|
||||||
|
ctf_write_uploaded_tp,
|
||||||
|
ctf_write_definition_end,
|
||||||
|
NULL,
|
||||||
|
&ctf_write_frame_ops,
|
||||||
|
ctf_end,
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Return a trace writer for CTF format. */
|
||||||
|
|
||||||
|
struct trace_file_writer *
|
||||||
|
ctf_trace_file_writer_new (void)
|
||||||
|
{
|
||||||
|
struct ctf_trace_file_writer *writer
|
||||||
|
= xmalloc (sizeof (struct ctf_trace_file_writer));
|
||||||
|
|
||||||
|
writer->base.ops = &ctf_write_ops;
|
||||||
|
|
||||||
|
return (struct trace_file_writer *) writer;
|
||||||
|
}
|
25
gdb/ctf.h
Normal file
25
gdb/ctf.h
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
/* CTF format support.
|
||||||
|
|
||||||
|
Copyright (C) 2012-2013 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
This file is part of GDB.
|
||||||
|
|
||||||
|
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/>. */
|
||||||
|
|
||||||
|
#ifndef CTF_H
|
||||||
|
#define CTF_H
|
||||||
|
|
||||||
|
extern struct trace_file_writer *ctf_trace_file_writer_new (void);
|
||||||
|
|
||||||
|
#endif
|
|
@ -1,3 +1,8 @@
|
||||||
|
2013-03-14 Hui Zhu <hui@codesourcery.com>
|
||||||
|
Yao Qi <yao@codesourcery.com>
|
||||||
|
|
||||||
|
* gdb.texinfo (Trace Files): Add "tsave -ctf".
|
||||||
|
|
||||||
2013-03-13 Keith Seitz <keiths@redhat.com>
|
2013-03-13 Keith Seitz <keiths@redhat.com>
|
||||||
|
|
||||||
* gdb.texinfo (Maintenance Commands): Add missing ')' for
|
* gdb.texinfo (Maintenance Commands): Add missing ')' for
|
||||||
|
|
|
@ -12286,6 +12286,7 @@ of trace data, via the @code{target tfile} command.
|
||||||
|
|
||||||
@kindex tsave
|
@kindex tsave
|
||||||
@item tsave [ -r ] @var{filename}
|
@item tsave [ -r ] @var{filename}
|
||||||
|
@itemx tsave [-ctf] @var{dirname}
|
||||||
Save the trace data to @var{filename}. By default, this command
|
Save the trace data to @var{filename}. By default, this command
|
||||||
assumes that @var{filename} refers to the host filesystem, so if
|
assumes that @var{filename} refers to the host filesystem, so if
|
||||||
necessary @value{GDBN} will copy raw trace data up from the target and
|
necessary @value{GDBN} will copy raw trace data up from the target and
|
||||||
|
@ -12294,6 +12295,11 @@ optional argument @code{-r} (``remote'') to direct the target to save
|
||||||
the data directly into @var{filename} in its own filesystem, which may be
|
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
|
more efficient if the trace buffer is very large. (Note, however, that
|
||||||
@code{target tfile} can only read from files accessible to the host.)
|
@code{target tfile} can only read from files accessible to the host.)
|
||||||
|
By default, this command will save trace frame in tfile format.
|
||||||
|
You can supply the optional argument @code{-ctf} to save date in CTF
|
||||||
|
format. The @dfn{Common Trace Format} (CTF) is proposed as a trace format
|
||||||
|
that can be shared by multiple debugging and tracing tools. Please go to
|
||||||
|
@indicateurl{http://www.efficios.com/ctf} to get more information.
|
||||||
|
|
||||||
@kindex target tfile
|
@kindex target tfile
|
||||||
@kindex tfile
|
@kindex tfile
|
||||||
|
|
|
@ -49,6 +49,7 @@
|
||||||
#include "osdata.h"
|
#include "osdata.h"
|
||||||
#include "splay-tree.h"
|
#include "splay-tree.h"
|
||||||
#include "tracepoint.h"
|
#include "tracepoint.h"
|
||||||
|
#include "ctf.h"
|
||||||
#include "ada-lang.h"
|
#include "ada-lang.h"
|
||||||
#include "linespec.h"
|
#include "linespec.h"
|
||||||
|
|
||||||
|
@ -2477,24 +2478,44 @@ void
|
||||||
mi_cmd_trace_save (char *command, char **argv, int argc)
|
mi_cmd_trace_save (char *command, char **argv, int argc)
|
||||||
{
|
{
|
||||||
int target_saves = 0;
|
int target_saves = 0;
|
||||||
|
int generate_ctf = 0;
|
||||||
char *filename;
|
char *filename;
|
||||||
|
int oind = 0;
|
||||||
|
char *oarg;
|
||||||
|
|
||||||
if (argc != 1 && argc != 2)
|
enum opt
|
||||||
error (_("Usage: -trace-save [-r] filename"));
|
|
||||||
|
|
||||||
if (argc == 2)
|
|
||||||
{
|
{
|
||||||
filename = argv[1];
|
TARGET_SAVE_OPT, CTF_OPT
|
||||||
if (strcmp (argv[0], "-r") == 0)
|
};
|
||||||
|
static const struct mi_opt opts[] =
|
||||||
|
{
|
||||||
|
{"r", TARGET_SAVE_OPT, 0},
|
||||||
|
{"ctf", CTF_OPT, 0},
|
||||||
|
{ 0, 0, 0 }
|
||||||
|
};
|
||||||
|
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
int opt = mi_getopt ("-trace-save", argc, argv, opts,
|
||||||
|
&oind, &oarg);
|
||||||
|
|
||||||
|
if (opt < 0)
|
||||||
|
break;
|
||||||
|
switch ((enum opt) opt)
|
||||||
|
{
|
||||||
|
case TARGET_SAVE_OPT:
|
||||||
target_saves = 1;
|
target_saves = 1;
|
||||||
else
|
break;
|
||||||
error (_("Invalid option: %s"), argv[0]);
|
case CTF_OPT:
|
||||||
|
generate_ctf = 1;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
filename = argv[0];
|
|
||||||
}
|
}
|
||||||
|
filename = argv[oind];
|
||||||
|
|
||||||
|
if (generate_ctf)
|
||||||
|
trace_save_ctf (filename, target_saves);
|
||||||
|
else
|
||||||
trace_save_tfile (filename, target_saves);
|
trace_save_tfile (filename, target_saves);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -53,6 +53,7 @@
|
||||||
#include "exceptions.h"
|
#include "exceptions.h"
|
||||||
#include "cli/cli-utils.h"
|
#include "cli/cli-utils.h"
|
||||||
#include "probe.h"
|
#include "probe.h"
|
||||||
|
#include "ctf.h"
|
||||||
|
|
||||||
/* readline include files */
|
/* readline include files */
|
||||||
#include "readline/readline.h"
|
#include "readline/readline.h"
|
||||||
|
@ -3544,6 +3545,7 @@ trace_save_command (char *args, int from_tty)
|
||||||
char **argv;
|
char **argv;
|
||||||
char *filename = NULL;
|
char *filename = NULL;
|
||||||
struct cleanup *back_to;
|
struct cleanup *back_to;
|
||||||
|
int generate_ctf = 0;
|
||||||
struct trace_file_writer *writer = NULL;
|
struct trace_file_writer *writer = NULL;
|
||||||
|
|
||||||
if (args == NULL)
|
if (args == NULL)
|
||||||
|
@ -3556,6 +3558,8 @@ trace_save_command (char *args, int from_tty)
|
||||||
{
|
{
|
||||||
if (strcmp (*argv, "-r") == 0)
|
if (strcmp (*argv, "-r") == 0)
|
||||||
target_does_save = 1;
|
target_does_save = 1;
|
||||||
|
if (strcmp (*argv, "-ctf") == 0)
|
||||||
|
generate_ctf = 1;
|
||||||
else if (**argv == '-')
|
else if (**argv == '-')
|
||||||
error (_("unknown option `%s'"), *argv);
|
error (_("unknown option `%s'"), *argv);
|
||||||
else
|
else
|
||||||
|
@ -3565,6 +3569,9 @@ trace_save_command (char *args, int from_tty)
|
||||||
if (!filename)
|
if (!filename)
|
||||||
error_no_arg (_("file in which to save trace data"));
|
error_no_arg (_("file in which to save trace data"));
|
||||||
|
|
||||||
|
if (generate_ctf)
|
||||||
|
writer = ctf_trace_file_writer_new ();
|
||||||
|
else
|
||||||
writer = tfile_trace_file_writer_new ();
|
writer = tfile_trace_file_writer_new ();
|
||||||
|
|
||||||
make_cleanup (trace_file_writer_xfree, writer);
|
make_cleanup (trace_file_writer_xfree, writer);
|
||||||
|
@ -3572,7 +3579,8 @@ trace_save_command (char *args, int from_tty)
|
||||||
trace_save (filename, writer, target_does_save);
|
trace_save (filename, writer, target_does_save);
|
||||||
|
|
||||||
if (from_tty)
|
if (from_tty)
|
||||||
printf_filtered (_("Trace data saved to file '%s'.\n"), filename);
|
printf_filtered (_("Trace data saved to %s '%s'.\n"),
|
||||||
|
generate_ctf ? "directory" : "file", filename);
|
||||||
|
|
||||||
do_cleanups (back_to);
|
do_cleanups (back_to);
|
||||||
}
|
}
|
||||||
|
@ -3591,6 +3599,21 @@ trace_save_tfile (const char *filename, int target_does_save)
|
||||||
do_cleanups (back_to);
|
do_cleanups (back_to);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Save the trace data to dir DIRNAME of ctf format. */
|
||||||
|
|
||||||
|
void
|
||||||
|
trace_save_ctf (const char *dirname, int target_does_save)
|
||||||
|
{
|
||||||
|
struct trace_file_writer *writer;
|
||||||
|
struct cleanup *back_to;
|
||||||
|
|
||||||
|
writer = ctf_trace_file_writer_new ();
|
||||||
|
back_to = make_cleanup (trace_file_writer_xfree, writer);
|
||||||
|
|
||||||
|
trace_save (dirname, writer, target_does_save);
|
||||||
|
do_cleanups (back_to);
|
||||||
|
}
|
||||||
|
|
||||||
/* Tell the target what to do with an ongoing tracing run if GDB
|
/* Tell the target what to do with an ongoing tracing run if GDB
|
||||||
disconnects for some reason. */
|
disconnects for some reason. */
|
||||||
|
|
||||||
|
@ -5657,6 +5680,7 @@ _initialize_tracepoint (void)
|
||||||
|
|
||||||
add_com ("tsave", class_trace, trace_save_command, _("\
|
add_com ("tsave", class_trace, trace_save_command, _("\
|
||||||
Save the trace data to a file.\n\
|
Save the trace data to a file.\n\
|
||||||
|
Use the '-ctf' option to save the data to CTF format.\n\
|
||||||
Use the '-r' option to direct the target to save directly to the file,\n\
|
Use the '-r' option to direct the target to save directly to the file,\n\
|
||||||
using its own filesystem."));
|
using its own filesystem."));
|
||||||
|
|
||||||
|
|
|
@ -388,6 +388,8 @@ extern void tfind_1 (enum trace_find_type type, int num,
|
||||||
|
|
||||||
extern void trace_save_tfile (const char *filename,
|
extern void trace_save_tfile (const char *filename,
|
||||||
int target_does_save);
|
int target_does_save);
|
||||||
|
extern void trace_save_ctf (const char *dirname,
|
||||||
|
int target_does_save);
|
||||||
|
|
||||||
extern struct traceframe_info *parse_traceframe_info (const char *tframe_info);
|
extern struct traceframe_info *parse_traceframe_info (const char *tframe_info);
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue