@@ -686,7 +686,7 @@ static void dump_option_section(int fd, unsigned int size,
do_print(OPTIONS, "%lld\n", sec->offset);
}
-static void dump_sections(int fd)
+static void dump_sections(int fd, int count)
{
struct file_section *sec = sections;
unsigned short flags;
@@ -724,6 +724,7 @@ static void dump_sections(int fd)
uncompress_reset();
sec = sec->next;
}
+ do_print(SUMMARY|SECTIONS, "\t[%d sections]\n", count);
}
static int dump_options_read(int fd);
@@ -936,17 +937,76 @@ static void dump_v6_file(int fd)
dump_therest(fd);
}
+static int walk_v7_sections(int fd)
+{
+ unsigned long long offset, soffset;
+ unsigned short fl;
+ char buf[DUMP_SIZE];
+ unsigned short id;
+ int size, csize, rsize;
+ int count = 0;
+
+ offset = lseek64(fd, 0, SEEK_CUR);
+ do {
+ soffset = lseek64(fd, 0, SEEK_CUR);
+ if (read_file_number(fd, &id, 2))
+ break;
+ if (id >= TRACECMD_OPTION_MAX)
+ die("Unknown section id %d", id);
+ if (read_file_string(fd, buf, DUMP_SIZE))
+ die("cannot read section description");
+ if (read_file_number(fd, &fl, 2))
+ die("cannot read section flags");
+ if (read_file_number(fd, &size, 4))
+ die("cannot read section size");
+ if (size <= 4)
+ die("Section %d (%s) is too small, %d bytes", id, buf, size);
+ count++;
+ if (fl & TRACECMD_SEC_FL_COMPRESS) {
+ if (id == TRACECMD_OPTION_BUFFER ||
+ id == TRACECMD_OPTION_BUFFER_LAT) {
+ do_print(SECTIONS,
+ "\t[Section %2d @ %-16lld\t\"%s\", flags 0x%X, "
+ "%d compressed bytes]\n",
+ id, soffset, buf, fl, size);
+ } else {
+ if (read_file_number(fd, &csize, 4))
+ die("cannot read section size");
+ if (read_file_number(fd, &rsize, 4))
+ die("cannot read section size");
+ do_print(SECTIONS, "\t[Section %2d @ %-16lld\t\"%s\", flags 0x%X, "
+ "%d compressed, %d uncompressed]\n",
+ id, soffset, buf, fl, csize, rsize);
+ size -= 8;
+ }
+ } else {
+ do_print(SECTIONS, "\t[Section %2d @ %-16lld\t\"%s\", flags 0x%X, %d bytes]\n",
+ id, soffset, buf, fl, size);
+ }
+
+ if (lseek64(fd, size, SEEK_CUR) == (off_t)-1)
+ break;
+ } while (1);
+
+ if (lseek64(fd, offset, SEEK_SET) == (off_t)-1)
+ die("cannot restore the original file location");
+ return count;
+}
+
static void dump_v7_file(int fd)
{
long long offset;
+ int sections;
if (read_file_number(fd, &offset, 8))
die("cannot read offset of the first option section");
- if (lseek64(fd, offset, SEEK_SET) == (off64_t)-1)
+ sections = walk_v7_sections(fd);
+
+ if (lseek64(fd, offset, SEEK_SET) == (off_t)-1)
die("cannot goto options offset %lld", offset);
dump_options(fd);
- dump_sections(fd);
+ dump_sections(fd, sections);
}
static void free_sections(void)
@@ -987,6 +1047,7 @@ static void dump_file(const char *file)
}
enum {
+ OPT_sections = 241,
OPT_verbose = 242,
OPT_clock = 243,
OPT_all = 244,
@@ -1030,6 +1091,7 @@ void trace_dump(int argc, char **argv)
{"options", no_argument, NULL, OPT_options},
{"flyrecord", no_argument, NULL, OPT_flyrecord},
{"clock", no_argument, NULL, OPT_clock},
+ {"sections", no_argument, NULL, OPT_sections},
{"validate", no_argument, NULL, 'v'},
{"help", no_argument, NULL, '?'},
{"verbose", optional_argument, NULL, OPT_verbose},
@@ -1092,6 +1154,8 @@ void trace_dump(int argc, char **argv)
case OPT_verbose:
if (trace_set_verbose(optarg) < 0)
die("invalid verbose level %s", optarg);
+ case OPT_sections:
+ verbosity |= SECTIONS;
break;
default:
usage(argv);
The new "trace-cmd dump --sections" argument walks through the sections from a trace file version 7 and prints their headers. The logic does not rely on the options, describing these sections. It could be useful to dump broken or incomplete trace files. Signed-off-by: Tzvetomir Stoyanov (VMware) <tz.stoyanov@gmail.com> --- tracecmd/trace-dump.c | 70 +++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 67 insertions(+), 3 deletions(-)