Perf already captures the tracing metadata as a part of
data section in perf.data

When trace_dat_fp is set, write trace.dat compatible metadata
sections using the perf provided raw buffers.

Sections written:
- Initial format header (magic, version, endian, long_size,
  page_size, compression, options_offset placeholder)
- Section 16: HEADER INFO (header_page + header_event)
- Section 17: FTRACE EVENT FORMATS
- Section 18: EVENT FORMATS (per system/event format files)
- Section 19: KALLSYMS
- Section 21: CMDLINES
- Section 15: STRINGS (written last after all sections)

Introduce to_file_u16/u32/u64 helpers wrapping tep_read_number() to
write all trace.dat metadata in the recorded machine's byte
order, ensuring correct cross-platform compatibility.

Signed-off-by: Tanushree Shah <[email protected]>
---
 tools/perf/util/trace-dat.c        | 212 ++++++++++++--------
 tools/perf/util/trace-dat.h        |  40 +++-
 tools/perf/util/trace-event-read.c | 307 ++++++++++++++++++++++++++++-
 3 files changed, 465 insertions(+), 94 deletions(-)

diff --git a/tools/perf/util/trace-dat.c b/tools/perf/util/trace-dat.c
index 55a7bd982c6f..f71e03716e27 100644
--- a/tools/perf/util/trace-dat.c
+++ b/tools/perf/util/trace-dat.c
@@ -43,6 +43,7 @@
 /* Buffer size for reading trace_clock string from debugfs/tracefs */
 #define CLOCK_BUFFER_SIZE 256
 
+bool trace_dat_write_failed;
 FILE *trace_dat_fp;
 int trace_dat_page_size;
 int trace_dat_nr_cpus;
@@ -143,10 +144,12 @@ int trace_dat__collect_cpu_event(int cpu, unsigned long 
long ts,
 }
 
 /* Write a single page of trace records */
-static int trace_dat__write_page(FILE *fp, unsigned long long base_ts,
+static int trace_dat__write_page(FILE *fp, struct tep_handle *pevent, unsigned 
long long base_ts,
                        char **records, int *rec_sizes, int nr_recs)
 {
        unsigned long long commit = 0;
+       unsigned long long ts_out;
+       unsigned long long commit_out;
        int offset = TRACE_DAT_RECORD_HEADER_SIZE;
        int i;
        char *page;
@@ -161,8 +164,12 @@ static int trace_dat__write_page(FILE *fp, unsigned long 
long base_ts,
                commit += rec_sizes[i];
        }
 
-       memcpy(page, &base_ts, sizeof(base_ts));
-       memcpy(page + sizeof(base_ts), &commit, sizeof(commit));
+       /* Byte-swap page header for cross-arch compatibility */
+       ts_out = to_file_u64(pevent, base_ts);
+       commit_out = to_file_u64(pevent, commit);
+
+       memcpy(page, &ts_out, sizeof(ts_out));
+       memcpy(page + sizeof(ts_out), &commit_out, sizeof(commit_out));
 
        if (!fwrite(page, 1, trace_dat_page_size, fp)) {
                free(page);
@@ -174,7 +181,8 @@ static int trace_dat__write_page(FILE *fp, unsigned long 
long base_ts,
 }
 
 /* Write all trace data for a single CPU as trace.dat flyrecord pages */
-static int trace_dat__write_cpu_dat(FILE *fp, int cpu, unsigned long long 
*file_offset_out)
+static int trace_dat__write_cpu_dat(FILE *fp, struct tep_handle *pevent,
+               int cpu, unsigned long long *file_offset_out)
 {
        struct cpu_events *cpu_events = &trace_cpu_data[cpu];
        unsigned long long base_ts;
@@ -229,11 +237,18 @@ static int trace_dat__write_cpu_dat(FILE *fp, int cpu, 
unsigned long long *file_
                        if (!extend)
                                return -ENOMEM;
 
-                       extend_hdr =
-                               ((time_delta & TRACE_DAT_RECORD_TIME_MASK) <<
-                                TRACE_DAT_RECORD_TIME_SHIFT) |
-                               TRACE_DAT_RECORD_TYPE_TIME_EXTEND;
-                       delta_upper = time_delta >> TRACE_DAT_RECORD_TIME_SHIFT;
+                       if (tep_is_file_bigendian(pevent)) {
+                               extend_hdr = (time_delta & 
TRACE_DAT_RECORD_TIME_MASK) |
+                                    (TRACE_DAT_RECORD_TYPE_TIME_EXTEND << 27);
+                               delta_upper = time_delta >> 27;
+                       } else {
+                               extend_hdr = ((time_delta & 
TRACE_DAT_RECORD_TIME_MASK) <<
+                                       TRACE_DAT_RECORD_TIME_SHIFT) |
+                                       TRACE_DAT_RECORD_TYPE_TIME_EXTEND;
+                               delta_upper = time_delta >> 
TRACE_DAT_RECORD_TIME_SHIFT;
+                       }
+                       extend_hdr  = to_file_u32(pevent, extend_hdr);   /* 
still needed */
+                       delta_upper = to_file_u32(pevent, delta_upper);   /* 
still needed */
 
                        memcpy(extend, &extend_hdr, TRACE_DAT_WORD_SIZE);
                        memcpy(extend + TRACE_DAT_WORD_SIZE, &delta_upper,
@@ -273,7 +288,7 @@ static int trace_dat__write_cpu_dat(FILE *fp, int cpu, 
unsigned long long *file_
                /* Check page fit BEFORE allocating data record */
                if (page_size_used + needed_size >
                        trace_dat_page_size - TRACE_DAT_RECORD_HEADER_SIZE) {
-                       ret = trace_dat__write_page(fp, base_ts,
+                       ret = trace_dat__write_page(fp, pevent, base_ts,
                                        page_records, page_rec_sizes,
                                        nr_page_recs);
 
@@ -299,7 +314,13 @@ static int trace_dat__write_cpu_dat(FILE *fp, int cpu, 
unsigned long long *file_
                        time_delta = 0;
                }
 
-               hdr_word = (time_delta << TRACE_DAT_RECORD_TIME_SHIFT) | 
type_len;
+               if (tep_is_file_bigendian(pevent))
+                       hdr_word = ((unsigned int)time_delta & 
TRACE_DAT_RECORD_TIME_MASK) |
+                               (type_len << 27);
+               else
+                       hdr_word = ((unsigned int)time_delta << 
TRACE_DAT_RECORD_TIME_SHIFT) |
+                               type_len;
+               hdr_word = to_file_u32(pevent, hdr_word);
 
                data_rec = calloc(1, data_rec_size);
                if (!data_rec) {
@@ -311,8 +332,11 @@ static int trace_dat__write_cpu_dat(FILE *fp, int cpu, 
unsigned long long *file_
                memcpy(data_rec, &hdr_word, TRACE_DAT_WORD_SIZE);
 
                /* Large events: write actual byte length after header */
-               if (type_len == 0)
-                       memcpy(data_rec + TRACE_DAT_WORD_SIZE, &data_len, 
TRACE_DAT_WORD_SIZE);
+               if (type_len == 0) {
+                       unsigned int data_len_out = to_file_u32(pevent, 
data_len);
+
+                       memcpy(data_rec + TRACE_DAT_WORD_SIZE, &data_len_out, 
TRACE_DAT_WORD_SIZE);
+               }
 
                memcpy(data_rec + payload_offset, event->raw, data_len);
 
@@ -366,7 +390,7 @@ static int trace_dat__write_cpu_dat(FILE *fp, int cpu, 
unsigned long long *file_
        }
 
        if (nr_page_recs > 0) {
-               ret = trace_dat__write_page(fp, base_ts,
+               ret = trace_dat__write_page(fp, pevent, base_ts,
                                page_records, page_rec_sizes, nr_page_recs);
        }
 out_free:
@@ -378,11 +402,11 @@ static int trace_dat__write_cpu_dat(FILE *fp, int cpu, 
unsigned long long *file_
 }
 
 /* Write the strings section containing section name lookup table */
-int trace_dat__write_strings_section(void)
+int trace_dat__write_strings_section(struct tep_handle *pevent)
 {
-       unsigned short section_id = TRACE_DAT_SECTION_STRINGS;
-       unsigned short flags = 0;
        unsigned long long section_size = 0;
+       unsigned short section_id = to_file_u16(pevent, 
TRACE_DAT_SECTION_STRINGS);
+       unsigned short flags = to_file_u16(pevent, 0);
        static const char * const section_names[] = {
                "headers",              /* offset 0 - strid for section 16  */
                "ftrace event formats", /* offset 8 - strid for section 17  */
@@ -397,7 +421,7 @@ int trace_dat__write_strings_section(void)
        };
 
        /* string_id points to "strings" string itself */
-       unsigned int string_id = STRID_STRINGS;
+       unsigned int string_id = to_file_u32(pevent, STRID_STRINGS);
        int i;
 
        if (!trace_dat_fp)
@@ -405,47 +429,59 @@ int trace_dat__write_strings_section(void)
 
        for (i = 0; section_names[i] != NULL; i++)
                section_size += strlen(section_names[i]) + 1;
+       section_size = to_file_u64(pevent, section_size);
 
        /* write section header */
        if (!fwrite(&section_id, sizeof(unsigned short), 1, trace_dat_fp) ||
                       !fwrite(&flags, sizeof(unsigned short), 1, trace_dat_fp) 
||
                       !fwrite(&string_id, sizeof(unsigned int), 1, 
trace_dat_fp) ||
-                      !fwrite(&section_size, sizeof(unsigned long long), 1, 
trace_dat_fp))
-               return -EIO;
+                      !fwrite(&section_size, sizeof(unsigned long long), 1, 
trace_dat_fp)) {
+               pr_warning("Failed to write strings section\n");
+               trace_dat_write_failed = true;
+       }
 
        /* write strings */
        for (i = 0; section_names[i] != NULL; i++)
-               if (!fwrite(section_names[i], 1, strlen(section_names[i]) + 1, 
trace_dat_fp))
-                       return -EIO;
+               if (!fwrite(section_names[i], 1, strlen(section_names[i]) + 1, 
trace_dat_fp)) {
+                       pr_warning("Failed to write strings section\n");
+                       trace_dat_write_failed = true;
+               }
        return 0;
 }
 
 /* Writes options section containing CPUCOUNT, TRACECLOCK, EVENT_FORMAT, 
HEADER_INFO,
  * FTRACE_EVENTS, KALLSYMS, CMDLINES options, ending with DONE option pointing 
to next section.
  */
-int trace_dat__write_options_section1(void)
+int trace_dat__write_options_section1(struct tep_handle *pevent)
 {
-       unsigned short section_id = TRACE_DAT_SECTION_OPTIONS;
-       unsigned short flags = 0;
-       unsigned int string_id = STRID_OPTIONS_1;
+       unsigned short section_id = to_file_u16(pevent, 
TRACE_DAT_SECTION_OPTIONS);
+       unsigned short flags = to_file_u16(pevent, 0);
+       unsigned int string_id = to_file_u32(pevent, STRID_OPTIONS_1);
        unsigned long long section_size = 0;
        long section_size_pos;
        long payload_start;
        unsigned long long section_start;
        unsigned short opt_id;
        unsigned int opt_size;
+       unsigned int raw_opt_size;
+       unsigned int nr_cpus;
        char clock_buf[CLOCK_BUFFER_SIZE];
        FILE *clock_file;
        size_t bytes_read;
        char *path;
        unsigned long long next_offset;
+       unsigned long long events_off;
+       unsigned long long header_off;
+       unsigned long long ftrace_off;
+       unsigned long long kallsyms_off;
+       unsigned long long cmdline_off;
        long end_pos;
 
        if (!trace_dat_fp)
                return -EBADF;
 
        /* fill options_offset in initial format */
-       section_start = ftell(trace_dat_fp);
+       section_start = to_file_u64(pevent, ftell(trace_dat_fp));
 
        if (fseek(trace_dat_fp, trace_dat_options_offset, SEEK_SET) < 0 ||
           !fwrite(&section_start, sizeof(unsigned long long), 1, trace_dat_fp) 
||
@@ -464,16 +500,17 @@ int trace_dat__write_options_section1(void)
        payload_start = ftell(trace_dat_fp);
 
        /* CPUCOUNT option */
-       opt_id = TRACE_DAT_OPTION_CPUCOUNT;
-       opt_size = sizeof(unsigned int);
+       opt_id = to_file_u16(pevent, TRACE_DAT_OPTION_CPUCOUNT);
+       opt_size = to_file_u32(pevent, sizeof(unsigned int));
+       nr_cpus = to_file_u32(pevent, trace_dat_nr_cpus);
 
        if (!fwrite(&opt_id, sizeof(unsigned short), 1, trace_dat_fp) ||
            !fwrite(&opt_size, sizeof(unsigned int), 1, trace_dat_fp) ||
-           !fwrite(&trace_dat_nr_cpus, sizeof(unsigned int), 1, trace_dat_fp))
+           !fwrite(&nr_cpus, sizeof(unsigned int), 1, trace_dat_fp))
                return -EIO;
 
        /* TRACECLOCK option */
-       opt_id = TRACE_DAT_OPTION_TRACECLOCK;
+       opt_id = to_file_u16(pevent, TRACE_DAT_OPTION_TRACECLOCK);
 
        path = get_tracing_file("trace_clock");
        if (path) {
@@ -490,66 +527,72 @@ int trace_dat__write_options_section1(void)
                strcpy(clock_buf, "local\n");
                bytes_read = strlen(clock_buf);
        }
-       opt_size = bytes_read + 1;
+       raw_opt_size = bytes_read + 1;
+       opt_size = to_file_u32(pevent, bytes_read + 1);
        if (!fwrite(&opt_id, sizeof(unsigned short), 1, trace_dat_fp) ||
            !fwrite(&opt_size, sizeof(unsigned int), 1, trace_dat_fp) ||
-           !fwrite(clock_buf, 1, opt_size, trace_dat_fp))
+           !fwrite(clock_buf, 1, raw_opt_size, trace_dat_fp))
                return -EIO;
 
        /* EVENT option */
-       opt_id = TRACE_DAT_OPTION_EVENT;
-       opt_size = sizeof(unsigned long long);
+       opt_id = to_file_u16(pevent, TRACE_DAT_OPTION_EVENT);
+       opt_size = to_file_u32(pevent, sizeof(unsigned long long));
+       events_off = to_file_u64(pevent, trace_dat_events_format_offset);
 
        if (!fwrite(&opt_id, sizeof(unsigned short), 1, trace_dat_fp) ||
           !fwrite(&opt_size, sizeof(unsigned int), 1, trace_dat_fp) ||
-          !fwrite(&trace_dat_events_format_offset, sizeof(unsigned long long),
+          !fwrite(&events_off, sizeof(unsigned long long),
                   1, trace_dat_fp))
                return -EIO;
 
        /* HEADER option */
-       opt_id = TRACE_DAT_OPTION_HEADER;
-       opt_size = sizeof(unsigned long long);
+       opt_id = to_file_u16(pevent, TRACE_DAT_OPTION_HEADER);
+       opt_size = to_file_u32(pevent, sizeof(unsigned long long));
+       header_off = to_file_u64(pevent, trace_dat_header_info_offset);
 
        if (!fwrite(&opt_id, sizeof(unsigned short), 1, trace_dat_fp) ||
            !fwrite(&opt_size, sizeof(unsigned int), 1, trace_dat_fp) ||
-           !fwrite(&trace_dat_header_info_offset, sizeof(unsigned long long),
+           !fwrite(&header_off, sizeof(unsigned long long),
                    1, trace_dat_fp))
                return -EIO;
 
        /* FTRACE option */
-       opt_id = TRACE_DAT_OPTION_FTRACE;
-       opt_size = sizeof(unsigned long long);
+       opt_id = to_file_u16(pevent, TRACE_DAT_OPTION_FTRACE);
+       opt_size = to_file_u32(pevent, sizeof(unsigned long long));
+       ftrace_off = to_file_u64(pevent, trace_dat_ftrace_format_offset);
 
        if (!fwrite(&opt_id, sizeof(unsigned short), 1, trace_dat_fp) ||
            !fwrite(&opt_size, sizeof(unsigned int), 1, trace_dat_fp) ||
-           !fwrite(&trace_dat_ftrace_format_offset, sizeof(unsigned long long),
+           !fwrite(&ftrace_off, sizeof(unsigned long long),
                   1, trace_dat_fp))
                return -EIO;
 
        /* KALLSYMS option */
-       opt_id = TRACE_DAT_OPTION_KALLSYMS;
-       opt_size = sizeof(unsigned long long);
+       opt_id = to_file_u16(pevent, TRACE_DAT_OPTION_KALLSYMS);
+       opt_size = to_file_u32(pevent, sizeof(unsigned long long));
+       kallsyms_off = to_file_u64(pevent, trace_dat_kallsyms_offset);
 
        if (!fwrite(&opt_id, sizeof(unsigned short), 1, trace_dat_fp) ||
            !fwrite(&opt_size, sizeof(unsigned int), 1, trace_dat_fp) ||
-           !fwrite(&trace_dat_kallsyms_offset, sizeof(unsigned long long),
+           !fwrite(&kallsyms_off, sizeof(unsigned long long),
                    1, trace_dat_fp))
                return -EIO;
 
        /* CMDLINE option */
-       opt_id = TRACE_DAT_OPTION_CMDLINE;
-       opt_size = sizeof(unsigned long long);
+       opt_id = to_file_u16(pevent, TRACE_DAT_OPTION_CMDLINE);
+       opt_size = to_file_u32(pevent, sizeof(unsigned long long));
+       cmdline_off = to_file_u64(pevent, trace_dat_cmdline_offset);
 
        if (!fwrite(&opt_id, sizeof(unsigned short), 1, trace_dat_fp) ||
            !fwrite(&opt_size, sizeof(unsigned int), 1, trace_dat_fp) ||
-           !fwrite(&trace_dat_cmdline_offset, sizeof(unsigned long long),
+           !fwrite(&cmdline_off, sizeof(unsigned long long),
                    1, trace_dat_fp))
                return -EIO;
 
        /* DONE option id - next_options_offset filled later */
-       opt_id = TRACE_DAT_OPTION_DONE;
-       opt_size = sizeof(unsigned long long);
-       next_offset = 0;  /* placeholder */
+       opt_id = to_file_u16(pevent, TRACE_DAT_OPTION_DONE);
+       opt_size = to_file_u32(pevent, sizeof(unsigned long long));
+       next_offset = to_file_u64(pevent, 0);
 
        trace_dat_next_options_offset = ftell(trace_dat_fp);
        if (!fwrite(&opt_id, sizeof(unsigned short), 1, trace_dat_fp) ||
@@ -560,7 +603,7 @@ int trace_dat__write_options_section1(void)
        /* fill section size */
        end_pos = ftell(trace_dat_fp);
 
-       section_size = end_pos - payload_start;
+       section_size = to_file_u64(pevent, end_pos - payload_start);
        if (fseek(trace_dat_fp, section_size_pos, SEEK_SET) < 0 ||
            !fwrite(&section_size, sizeof(unsigned long long), 1, trace_dat_fp) 
||
            fseek(trace_dat_fp, end_pos, SEEK_SET) < 0)
@@ -574,20 +617,21 @@ int trace_dat__write_options_section1(void)
  * (flyrecord section offset, clock type, page size, CPU count,
  * per-CPU offsets/sizes) and DONE option.
  */
-int trace_dat__write_options_section2(void)
+int trace_dat__write_options_section2(struct tep_handle *pevent)
 {
-       unsigned short section_id  = TRACE_DAT_SECTION_OPTIONS;
-       unsigned short flags = 0;
-       unsigned int string_id = STRID_OPTIONS_2;
+       unsigned short section_id = to_file_u16(pevent, 
TRACE_DAT_SECTION_OPTIONS);
+       unsigned short flags = to_file_u16(pevent, 0);
+       unsigned int string_id = to_file_u32(pevent, STRID_OPTIONS_2);
        unsigned long long section_size = 0;
        long section_size_pos;
        long payload_start;
        int cpu;
-       unsigned short opt_id = TRACE_DAT_OPTION_BUFFER;
-       unsigned int opt_size = 0;
+       unsigned short opt_id = to_file_u16(pevent, TRACE_DAT_OPTION_BUFFER);
+       unsigned int opt_size = 0;  /* filled after payload written */
        long opt_size_pos;
        unsigned long long data_offset = 0;
-       unsigned int page_size = (unsigned int)trace_dat_page_size;
+       unsigned int page_size = to_file_u32(pevent, (unsigned 
int)trace_dat_page_size);
+       unsigned int nr_cpus   = to_file_u32(pevent, trace_dat_nr_cpus);
        const char *clock = "local";
        unsigned long long next;
        long end_pos;
@@ -600,7 +644,7 @@ int trace_dat__write_options_section2(void)
                return -EINVAL;
 
        /* fill done1 next offset - points to this section */
-       next = ftell(trace_dat_fp);
+       next = to_file_u64(pevent, ftell(trace_dat_fp));
 
        if (fseek(trace_dat_fp, trace_dat_next_options_offset + 2 + 4, 
SEEK_SET) < 0 ||
            !fwrite(&next, sizeof(unsigned long long), 1, trace_dat_fp) ||
@@ -631,15 +675,16 @@ int trace_dat__write_options_section2(void)
            !fwrite("\0", 1, 1, trace_dat_fp) ||
            !fwrite(clock, 1, strlen(clock) + 1, trace_dat_fp) ||
            !fwrite(&page_size, sizeof(unsigned int), 1, trace_dat_fp) ||
-           !fwrite(&trace_dat_nr_cpus, sizeof(unsigned int), 1, trace_dat_fp))
+           !fwrite(&nr_cpus, sizeof(unsigned int), 1, trace_dat_fp))
                return -EIO;
 
        /* per cpu: cpu_id + offset placeholder + size */
        for (cpu = 0; cpu < trace_dat_nr_cpus; cpu++) {
+               unsigned int cpu_out          = to_file_u32(pevent, cpu);
                cpu_offset = 0;  /* filled in write_flyrecord */
-               cpu_size   = 0;  /* filled in write_flyrecord */
+               cpu_size = 0;  /* filled in write_flyrecord */
 
-               if (!fwrite(&cpu, sizeof(unsigned int), 1, trace_dat_fp))
+               if (!fwrite(&cpu_out, sizeof(unsigned int), 1, trace_dat_fp))
                        return -EIO;
                buffer_opt_cpu_offsets_pos[cpu] = ftell(trace_dat_fp);
                if (!fwrite(&cpu_offset, sizeof(unsigned long long), 1, 
trace_dat_fp) ||
@@ -650,17 +695,17 @@ int trace_dat__write_options_section2(void)
        /* fill opt_size */
        end_pos = ftell(trace_dat_fp);
 
-       opt_size = end_pos - opt_payload_start;
-       fseek(trace_dat_fp, opt_size_pos, SEEK_SET);
-       if (!fwrite(&opt_size, sizeof(unsigned int), 1, trace_dat_fp))
+       opt_size = to_file_u32(pevent, end_pos - opt_payload_start);
+       if (fseek(trace_dat_fp, opt_size_pos, SEEK_SET) < 0 ||
+           !fwrite(&opt_size, sizeof(unsigned int), 1, trace_dat_fp) ||
+           fseek(trace_dat_fp, end_pos, SEEK_SET) < 0)
                return -EIO;
-       fseek(trace_dat_fp, end_pos, SEEK_SET);
 
        /* DONE id=0 */
-       done_id = TRACE_DAT_OPTION_DONE;
-       done_size = sizeof(unsigned long long);
+       done_id = to_file_u16(pevent, TRACE_DAT_OPTION_DONE);
+       done_size = to_file_u32(pevent, sizeof(unsigned long long));
        /* No additional options sections follow this one */
-       next = 0;
+       next = to_file_u64(pevent, 0);
 
        if (!fwrite(&done_id, sizeof(unsigned short), 1, trace_dat_fp) ||
            !fwrite(&done_size, sizeof(unsigned int), 1, trace_dat_fp) ||
@@ -670,24 +715,25 @@ int trace_dat__write_options_section2(void)
        /* fill section size */
        end_pos = ftell(trace_dat_fp);
 
-       section_size = end_pos - payload_start;
-       fseek(trace_dat_fp, section_size_pos, SEEK_SET);
-       if (!fwrite(&section_size, sizeof(unsigned long long), 1, trace_dat_fp))
+       section_size = to_file_u64(pevent, end_pos - payload_start);
+       if (fseek(trace_dat_fp, section_size_pos, SEEK_SET) < 0 ||
+           !fwrite(&section_size, sizeof(unsigned long long), 1, trace_dat_fp) 
||
+           fseek(trace_dat_fp, end_pos, SEEK_SET) < 0)
                return -EIO;
-       fseek(trace_dat_fp, end_pos, SEEK_SET);
 
        return 0;
 
 }
 
-int trace_dat__write_flyrecord_section(void)
+int trace_dat__write_flyrecord_section(struct tep_handle *pevent)
 {
-       unsigned short section_id = TRACE_DAT_SECTION_FLYRECORD;
-       unsigned short flags = 0;
-       unsigned int string_id = STRID_BUFFER_FLYRECORD;
+       unsigned short section_id = to_file_u16(pevent, 
TRACE_DAT_SECTION_FLYRECORD);
+       unsigned short flags = to_file_u16(pevent, 0);
+       unsigned int string_id = to_file_u32(pevent, STRID_BUFFER_FLYRECORD);
        unsigned long long section_size = 0;
        long section_size_pos;
        long flyrecord_start;
+       unsigned long long flyrecord_out;
        long after_header;
        long padding_needed;
        unsigned long long *cpu_offsets;
@@ -750,7 +796,7 @@ int trace_dat__write_flyrecord_section(void)
        for (cpu = 0; cpu < trace_dat_nr_cpus; cpu++) {
                start = ftell(trace_dat_fp);
 
-               ret = trace_dat__write_cpu_dat(trace_dat_fp, cpu, 
&cpu_offsets[cpu]);
+               ret = trace_dat__write_cpu_dat(trace_dat_fp, pevent, cpu, 
&cpu_offsets[cpu]);
 
                if (ret < 0) {
                        pr_err("Failed to write CPU %d data\n", cpu);
@@ -762,7 +808,7 @@ int trace_dat__write_flyrecord_section(void)
        /* fill section size */
        end_pos = ftell(trace_dat_fp);
 
-       section_size = end_pos - after_header;
+       section_size = to_file_u64(pevent, end_pos - after_header);
        if (fseek(trace_dat_fp, section_size_pos, SEEK_SET) < 0 ||
            !fwrite(&section_size, sizeof(unsigned long long), 1, 
trace_dat_fp)) {
                ret = -EIO;
@@ -775,6 +821,8 @@ int trace_dat__write_flyrecord_section(void)
 
        /* fill cpu offsets and sizes in BUFFER option */
        for (cpu = 0; cpu < trace_dat_nr_cpus; cpu++) {
+               cpu_offsets[cpu] = to_file_u64(pevent, cpu_offsets[cpu]);
+               cpu_sizes[cpu]   = to_file_u64(pevent, cpu_sizes[cpu]);
                if (fseek(trace_dat_fp, buffer_opt_cpu_offsets_pos[cpu], 
SEEK_SET) < 0 ||
                    !fwrite(&cpu_offsets[cpu], sizeof(unsigned long long), 1, 
trace_dat_fp) ||
                    !fwrite(&cpu_sizes[cpu], sizeof(unsigned long long), 1, 
trace_dat_fp)) {
@@ -784,8 +832,9 @@ int trace_dat__write_flyrecord_section(void)
        }
 
        /* fill data offset in buffer option */
+       flyrecord_out = to_file_u64(pevent, flyrecord_start);
        if (fseek(trace_dat_fp, opt_payload_start, SEEK_SET) < 0 ||
-           !fwrite(&flyrecord_start, sizeof(unsigned long long), 1, 
trace_dat_fp)) {
+           !fwrite(&flyrecord_out, sizeof(unsigned long long), 1, 
trace_dat_fp)) {
                ret = -EIO;
                goto cleanup;
        }
@@ -795,7 +844,6 @@ int trace_dat__write_flyrecord_section(void)
                goto cleanup;
        }
 
-
 cleanup:
        free(cpu_offsets);
        free(cpu_sizes);
diff --git a/tools/perf/util/trace-dat.h b/tools/perf/util/trace-dat.h
index 9aec37b708d4..5985083b275a 100644
--- a/tools/perf/util/trace-dat.h
+++ b/tools/perf/util/trace-dat.h
@@ -8,9 +8,13 @@
 #define __PERF_TRACE_DAT_H
 
 #include <stdio.h>
+#include <stdbool.h>
+#include <event-parse.h>
+#include <byteswap.h>
+#include "util.h"
 
 /* trace.dat file format version */
-#define TRACE_DAT_VERSION '7'
+#define TRACE_DAT_VERSION "7"
 
 /*
  * Section IDs for trace.dat format
@@ -51,6 +55,32 @@
 #define STRID_OPTIONS_2        77
 #define STRID_BUFFER_FLYRECORD 85
 
+/*
+ * Set by trace.dat section writers (kallsyms, ftrace, events etc.) on
+ * fwrite() failure; checked by trace_convert__perf2dat() to clean up.
+ */
+extern bool trace_dat_write_failed;
+
+/*
+ * tep handle from the recording machine; set by trace_convert__perf2dat()
+ * before options/flyrecord sections are written.
+ */
+
+static inline uint16_t to_file_u16(struct tep_handle *pevent, uint16_t val)
+{
+       return tep_read_number(pevent, &val, 2);
+}
+
+static inline uint32_t to_file_u32(struct tep_handle *pevent, uint32_t val)
+{
+       return tep_read_number(pevent, &val, 4);
+}
+
+static inline uint64_t to_file_u64(struct tep_handle *pevent, uint64_t val)
+{
+       return tep_read_number(pevent, &val, 8);
+}
+
 struct perf_session;
 
 extern FILE *trace_dat_fp;
@@ -75,9 +105,9 @@ int trace_dat__collect_cpu_event(int cpu, unsigned long long 
ts,
 void trace_dat__free_cpu_buffers(void);
 
 /* write trace.dat file sections */
-int trace_dat__write_options_section1(void);
-int trace_dat__write_options_section2(void);
-int trace_dat__write_flyrecord_section(void);
-int trace_dat__write_strings_section(void);
+int trace_dat__write_options_section1(struct tep_handle *pevent);
+int trace_dat__write_options_section2(struct tep_handle *pevent);
+int trace_dat__write_flyrecord_section(struct tep_handle *pevent);
+int trace_dat__write_strings_section(struct tep_handle *pevent);
 
 #endif /* __PERF_TRACE_DAT_H */
diff --git a/tools/perf/util/trace-event-read.c 
b/tools/perf/util/trace-event-read.c
index ecbbb93f0185..7e38e9c8f507 100644
--- a/tools/perf/util/trace-event-read.c
+++ b/tools/perf/util/trace-event-read.c
@@ -19,6 +19,7 @@
 #include "trace-event.h"
 #include "debug.h"
 #include "util.h"
+#include "trace-dat.h"
 
 static int input_fd;
 
@@ -145,10 +146,9 @@ static char *read_string(void)
 static int read_proc_kallsyms(struct tep_handle *pevent)
 {
        unsigned int size;
+       char *buf;
 
        size = read4(pevent);
-       if (!size)
-               return 0;
        /*
         * Just skip it, now that we configure libtraceevent to use the
         * tools/perf/ symbol resolver.
@@ -160,11 +160,59 @@ static int read_proc_kallsyms(struct tep_handle *pevent)
         * payload", so that older tools can continue reading it and interpret
         * it as "no kallsyms payload is present".
         */
-       lseek(input_fd, size, SEEK_CUR);
+       /* Write kallsyms section with empty payload if no data */
+       if (!size) {
+               if (trace_dat_fp && !trace_dat_write_failed) {
+                       unsigned short section_id = to_file_u16(pevent, 
TRACE_DAT_SECTION_KALLSYMS);
+                       unsigned short flags = to_file_u16(pevent, 0);
+                       unsigned int string_id = to_file_u32(pevent, 
STRID_KALLSYMS);
+                       unsigned long long section_size = to_file_u64(pevent, 
sizeof(unsigned int));
+                       unsigned int kallsyms_data = to_file_u32(pevent, 0);
+
+                       trace_dat_kallsyms_offset = ftell(trace_dat_fp);
+                       if (!fwrite(&section_id, sizeof(unsigned short), 1, 
trace_dat_fp) ||
+                           !fwrite(&flags, sizeof(unsigned short), 1, 
trace_dat_fp) ||
+                           !fwrite(&string_id, sizeof(unsigned int), 1, 
trace_dat_fp) ||
+                           !fwrite(&section_size, sizeof(unsigned long long), 
1, trace_dat_fp) ||
+                           !fwrite(&kallsyms_data, sizeof(unsigned int), 1, 
trace_dat_fp)) {
+                               pr_warning("Failed to write trace.dat kallsyms 
section\n");
+                               trace_dat_write_failed = true;
+                       }
+               }
+               return 0;
+       }
+       buf = malloc(size);
+       if (buf == NULL)
+               return -1;
+       if (do_read(buf, size) < 0) {
+               free(buf);
+               return -1;
+       }
        trace_data_size += size;
+       /* Write kallsyms section with data */
+       if (trace_dat_fp && !trace_dat_write_failed) {
+               unsigned short section_id = to_file_u16(pevent, 
TRACE_DAT_SECTION_KALLSYMS);
+               unsigned int string_id = to_file_u32(pevent, STRID_KALLSYMS);
+               unsigned long long section_size = to_file_u64(pevent, 
sizeof(unsigned int) + size);
+               unsigned short flags = to_file_u16(pevent, 0);
+               unsigned int size_out = to_file_u32(pevent, size);
+
+               trace_dat_kallsyms_offset = ftell(trace_dat_fp);
+               if (!fwrite(&section_id, sizeof(unsigned short), 1, 
trace_dat_fp) ||
+                   !fwrite(&flags, sizeof(unsigned short), 1, trace_dat_fp) ||
+                   !fwrite(&string_id, sizeof(unsigned int), 1, trace_dat_fp) 
||
+                   !fwrite(&section_size, sizeof(unsigned long long), 1, 
trace_dat_fp) ||
+                   !fwrite(&size_out, sizeof(unsigned int), 1, trace_dat_fp) ||
+                   !fwrite(buf, 1, size, trace_dat_fp)) {
+                       pr_warning("Failed to write trace.dat kallsyms 
section\n");
+                       trace_dat_write_failed = true;
+               }
+       }
+       free(buf);
        return 0;
 }
 
+
 static int read_ftrace_printk(struct tep_handle *pevent)
 {
        unsigned int size;
@@ -195,6 +243,13 @@ static int read_ftrace_printk(struct tep_handle *pevent)
 static int read_header_files(struct tep_handle *pevent)
 {
        unsigned long long size;
+       unsigned long long header_page_size;
+       unsigned long long header_event_size;
+       char *header_event;
+       unsigned short section_id;
+       unsigned short flags;
+       unsigned int string_id;
+       unsigned long long section_size;
        char *header_page;
        char buf[BUFSIZ];
        int ret = 0;
@@ -209,6 +264,7 @@ static int read_header_files(struct tep_handle *pevent)
 
        size = read8(pevent);
 
+       header_page_size = size;
        header_page = malloc(size);
        if (header_page == NULL)
                return -1;
@@ -227,19 +283,63 @@ static int read_header_files(struct tep_handle *pevent)
                 */
                tep_set_long_size(pevent, tep_get_header_page_size(pevent));
        }
-       free(header_page);
 
-       if (do_read(buf, 13) < 0)
+       if (do_read(buf, 13) < 0) {
+               free(header_page);
                return -1;
+       }
 
        if (memcmp(buf, "header_event", 13) != 0) {
                pr_debug("did not read header event");
+               free(header_page);
                return -1;
        }
 
        size = read8(pevent);
-       skip(size);
+       if (trace_dat_fp && !trace_dat_write_failed) {
+               unsigned long long header_page_size_out;
+               unsigned long long header_event_size_out;
+
+               header_event_size = size;
+               header_event = malloc(size);
+               if (header_event == NULL) {
+                       free(header_page);
+                       return -1;
+               }
+               if (do_read(header_event, size) < 0) {
+                       free(header_page);
+                       free(header_event);
+                       return -1;
+               }
+               /* Write header_page and header_event to trace.dat */
+               section_id = to_file_u16(pevent, TRACE_DAT_SECTION_HEADER);
+               flags = to_file_u16(pevent, 0);
+               string_id = to_file_u32(pevent, STRID_HEADERS);
+               section_size = to_file_u64(pevent, 12 + 8 + header_page_size +
+                               13 + 8 + header_event_size);
+               header_page_size_out = to_file_u64(pevent, header_page_size);
+               header_event_size_out = to_file_u64(pevent, header_event_size);
+
+               trace_dat_header_info_offset = ftell(trace_dat_fp);
+               if (!fwrite(&section_id, sizeof(unsigned short), 1, 
trace_dat_fp) ||
+                   !fwrite(&flags, sizeof(unsigned short), 1, trace_dat_fp) ||
+                   !fwrite(&string_id, sizeof(unsigned int), 1, trace_dat_fp) 
||
+                   !fwrite(&section_size, sizeof(unsigned long long), 1, 
trace_dat_fp) ||
+                   !fwrite("header_page\0", 1, 12, trace_dat_fp) ||
+                   !fwrite(&header_page_size_out, sizeof(unsigned long long), 
1, trace_dat_fp) ||
+                   !fwrite(header_page, 1, header_page_size, trace_dat_fp) ||
+                   !fwrite("header_event\0", 1, 13, trace_dat_fp) ||
+                   !fwrite(&header_event_size_out, sizeof(unsigned long long), 
1, trace_dat_fp) ||
+                   !fwrite(header_event, 1, header_event_size, trace_dat_fp)) {
+                       pr_warning("Failed to write trace.dat header 
section\n");
+                       trace_dat_write_failed = true;
+               }
+               free(header_event);
+       } else {
+               skip(size);
+       }
 
+       free(header_page);
        return ret;
 }
 
@@ -259,6 +359,15 @@ static int read_ftrace_file(struct tep_handle *pevent, 
unsigned long long size)
                pr_debug("error reading ftrace file.\n");
                goto out;
        }
+       if (trace_dat_fp && !trace_dat_write_failed) {
+               unsigned long long size_out = to_file_u64(pevent, size);
+
+               if (!fwrite(&size_out, sizeof(unsigned long long), 1, 
trace_dat_fp) ||
+                   !fwrite(buf, 1, size, trace_dat_fp)) {
+                       pr_warning("Failed to write trace.dat ftrace event 
formats section\n");
+                       trace_dat_write_failed = true;
+               }
+       }
 
        ret = parse_ftrace_file(pevent, buf, size);
        if (ret < 0)
@@ -283,6 +392,15 @@ static int read_event_file(struct tep_handle *pevent, char 
*sys,
        ret = do_read(buf, size);
        if (ret < 0)
                goto out;
+       if (trace_dat_fp && !trace_dat_write_failed) {
+               unsigned long long size_out = to_file_u64(pevent, size);
+
+               if (!fwrite(&size_out, sizeof(unsigned long long), 1, 
trace_dat_fp) ||
+                   !fwrite(buf, 1, size, trace_dat_fp)) {
+                       pr_warning("Failed to write trace.dat event formats 
section\n");
+                       trace_dat_write_failed = true;
+               }
+       }
 
        ret = parse_event_file(pevent, buf, size, sys);
        if (ret < 0)
@@ -298,8 +416,39 @@ static int read_ftrace_files(struct tep_handle *pevent)
        int count;
        int i;
        int ret;
+       long section_size_pos = 0;
+       long count_pos = 0;
+       unsigned long long section_size = 0;
+       long end_pos;
 
        count = read4(pevent);
+       /* Write ftrace formats section to trace.dat output file */
+       if (trace_dat_fp && !trace_dat_write_failed) {
+               unsigned short section_id = to_file_u16(pevent, 
TRACE_DAT_SECTION_FTRACE);
+               unsigned short flags = to_file_u16(pevent, 0);
+               unsigned int string_id = to_file_u32(pevent, 
STRID_FTRACE_FORMATS);
+               unsigned int count_out = to_file_u32(pevent, count);
+
+               section_size = to_file_u64(pevent, 0);
+               trace_dat_ftrace_format_offset = ftell(trace_dat_fp);
+
+               if (!fwrite(&section_id, sizeof(unsigned short), 1, 
trace_dat_fp) ||
+                       !fwrite(&flags, sizeof(unsigned short), 1, 
trace_dat_fp) ||
+                       !fwrite(&string_id, sizeof(unsigned int), 1, 
trace_dat_fp)) {
+                       pr_warning("Failed to write trace.dat ftrace event 
formats section\n");
+                       trace_dat_write_failed = true;
+               }
+               section_size_pos = ftell(trace_dat_fp);
+               if (!fwrite(&section_size, sizeof(unsigned long long), 1, 
trace_dat_fp)) {
+                       pr_warning("Failed to write trace.dat ftrace event 
formats section\n");
+                       trace_dat_write_failed = true;
+               }
+               count_pos = ftell(trace_dat_fp);
+               if (!fwrite(&count_out, sizeof(unsigned int), 1, trace_dat_fp)) 
{
+                       pr_warning("Failed to write trace.dat ftrace event 
formats section\n");
+                       trace_dat_write_failed = true;
+               }
+       }
 
        for (i = 0; i < count; i++) {
                size = read8(pevent);
@@ -307,6 +456,18 @@ static int read_ftrace_files(struct tep_handle *pevent)
                if (ret)
                        return ret;
        }
+       /* Fill in section size after writing all ftrace files */
+       if (trace_dat_fp && !trace_dat_write_failed) {
+               end_pos = ftell(trace_dat_fp);
+               section_size = to_file_u64(pevent, end_pos - count_pos);
+               if (fseek(trace_dat_fp, section_size_pos, SEEK_SET) < 0 ||
+                       !fwrite(&section_size, sizeof(unsigned long long), 1, 
trace_dat_fp) ||
+                       fseek(trace_dat_fp, end_pos, SEEK_SET) < 0) {
+                       pr_warning("Failed to write trace.dat ftrace event 
formats section\n");
+                       trace_dat_write_failed = true;
+               }
+       }
+
        return 0;
 }
 
@@ -318,8 +479,38 @@ static int read_event_files(struct tep_handle *pevent)
        int count;
        int i,x;
        int ret;
+       long section_size_pos = 0;
+       long sys_count_pos = 0;
+       unsigned long long section_size = 0;
+       long end_pos;
 
        systems = read4(pevent);
+       /* Write event formats section to trace.dat output file */
+       if (trace_dat_fp && !trace_dat_write_failed) {
+               unsigned short section_id = to_file_u16(pevent, 
TRACE_DAT_SECTION_EVENTS);
+               unsigned short flags = to_file_u16(pevent, 0);
+               unsigned int string_id = to_file_u32(pevent, 
STRID_EVENT_FORMATS);
+               unsigned int systems_out = to_file_u32(pevent, systems);
+
+               section_size = to_file_u64(pevent, 0);
+               trace_dat_events_format_offset = ftell(trace_dat_fp);
+               if (!fwrite(&section_id, sizeof(unsigned short), 1, 
trace_dat_fp) ||
+                   !fwrite(&flags, sizeof(unsigned short), 1, trace_dat_fp) ||
+                   !fwrite(&string_id, sizeof(unsigned int), 1, trace_dat_fp)) 
{
+                       pr_warning("Failed to write trace.dat event formats 
section\n");
+                       trace_dat_write_failed = true;
+               }
+               section_size_pos = ftell(trace_dat_fp);
+               if (!fwrite(&section_size, sizeof(unsigned long long), 1, 
trace_dat_fp)) {
+                       pr_warning("Failed to write trace.dat event formats 
section\n");
+                       trace_dat_write_failed = true;
+               }
+               sys_count_pos = ftell(trace_dat_fp);
+               if (!fwrite(&systems_out, sizeof(unsigned int), 1, 
trace_dat_fp)) {
+                       pr_warning("Failed to write trace.dat event formats 
section\n");
+                       trace_dat_write_failed = true;
+               }
+       }
 
        for (i = 0; i < systems; i++) {
                sys = read_string();
@@ -327,6 +518,15 @@ static int read_event_files(struct tep_handle *pevent)
                        return -1;
 
                count = read4(pevent);
+               if (trace_dat_fp && !trace_dat_write_failed) {
+                       unsigned int count_out = to_file_u32(pevent, count);
+
+                       if (!fwrite(sys, 1, strlen(sys) + 1, trace_dat_fp) ||
+                           !fwrite(&count_out, sizeof(unsigned int), 1, 
trace_dat_fp)) {
+                               pr_warning("Failed to write trace.dat event 
formats section\n");
+                               trace_dat_write_failed = true;
+                       }
+               }
 
                for (x=0; x < count; x++) {
                        size = read8(pevent);
@@ -338,6 +538,18 @@ static int read_event_files(struct tep_handle *pevent)
                }
                free(sys);
        }
+       /* Fill in section size after writing all event files */
+       if (trace_dat_fp && !trace_dat_write_failed) {
+               end_pos = ftell(trace_dat_fp);
+               section_size = to_file_u64(pevent, end_pos - sys_count_pos);
+               fseek(trace_dat_fp, section_size_pos, SEEK_SET);
+               if (!fwrite(&section_size, sizeof(unsigned long long), 1, 
trace_dat_fp)) {
+                       pr_warning("Failed to write trace.dat event formats 
section\n");
+                       trace_dat_write_failed = true;
+               }
+               fseek(trace_dat_fp, end_pos, SEEK_SET);
+       }
+
        return 0;
 }
 
@@ -349,8 +561,28 @@ static int read_saved_cmdline(struct tep_handle *pevent)
 
        /* it can have 0 size */
        size = read8(pevent);
-       if (!size)
+       /* Write cmdlines section with empty payload if no data */
+       if (!size) {
+               if (trace_dat_fp && !trace_dat_write_failed) {
+                       unsigned short section_id = to_file_u16(pevent, 
TRACE_DAT_SECTION_CMDLINE);
+                       unsigned short flags = to_file_u16(pevent, 0);
+                       unsigned int string_id = to_file_u32(pevent, 
STRID_CMDLINES);
+                       unsigned long long section_size =
+                               to_file_u64(pevent, sizeof(unsigned long long));
+                       unsigned long long section_data = to_file_u64(pevent, 
0);
+
+                       trace_dat_cmdline_offset = ftell(trace_dat_fp);
+                       if (!fwrite(&section_id, sizeof(unsigned short), 1, 
trace_dat_fp) ||
+                           !fwrite(&flags, sizeof(unsigned short), 1, 
trace_dat_fp) ||
+                           !fwrite(&string_id, sizeof(unsigned int), 1, 
trace_dat_fp) ||
+                           !fwrite(&section_size, sizeof(unsigned long long), 
1, trace_dat_fp) ||
+                           !fwrite(&section_data, sizeof(unsigned long long), 
1, trace_dat_fp)) {
+                               pr_warning("Failed to write trace.dat cmdlines 
section\n");
+                               trace_dat_write_failed = true;
+                       }
+               }
                return 0;
+       }
 
        buf = malloc(size + 1);
        if (buf == NULL) {
@@ -363,6 +595,27 @@ static int read_saved_cmdline(struct tep_handle *pevent)
                pr_debug("error reading saved cmdlines\n");
                goto out;
        }
+       /* Write cmdlines section with data */
+       if (trace_dat_fp && !trace_dat_write_failed) {
+               unsigned short section_id = to_file_u16(pevent, 
TRACE_DAT_SECTION_CMDLINE);
+               unsigned short flags = to_file_u16(pevent, 0);
+               unsigned int string_id = to_file_u32(pevent, STRID_CMDLINES);
+               unsigned long long section_size =
+                       to_file_u64(pevent, sizeof(unsigned long long) + size);
+               unsigned long long size_out = to_file_u64(pevent, size);
+
+               trace_dat_cmdline_offset = ftell(trace_dat_fp);
+               if (!fwrite(&section_id, sizeof(unsigned short), 1, 
trace_dat_fp) ||
+                       !fwrite(&flags, sizeof(unsigned short), 1, 
trace_dat_fp) ||
+                       !fwrite(&string_id, sizeof(unsigned int), 1, 
trace_dat_fp) ||
+                       !fwrite(&section_size, sizeof(unsigned long long), 1, 
trace_dat_fp) ||
+                       !fwrite(&size_out, sizeof(unsigned long long), 1, 
trace_dat_fp) ||
+                       !fwrite(buf, 1, size, trace_dat_fp)) {
+                       pr_warning("Failed to write trace.dat cmdlines 
section\n");
+                       trace_dat_write_failed = true;
+               }
+       }
+
        buf[ret] = '\0';
 
        parse_saved_cmdline(pevent, buf, size);
@@ -387,6 +640,7 @@ ssize_t trace_report(int fd, struct trace_event *tevent, 
bool __repipe)
        int file_page_size;
        struct tep_handle *pevent = NULL;
        int err;
+       char magic_buf[10];
 
        repipe = __repipe;
        input_fd = fd;
@@ -398,12 +652,17 @@ ssize_t trace_report(int fd, struct trace_event *tevent, 
bool __repipe)
                return -1;
        }
 
+       if (trace_dat_fp)
+               memcpy(magic_buf, buf, 3);
+
        if (do_read(buf, 7) < 0)
                return -1;
        if (memcmp(buf, "tracing", 7) != 0) {
                pr_debug("not a trace file (missing 'tracing' tag)");
                return -1;
        }
+       if (trace_dat_fp)
+               memcpy(magic_buf + 3, buf, 7);
 
        version = read_string();
        if (version == NULL)
@@ -440,6 +699,34 @@ ssize_t trace_report(int fd, struct trace_event *tevent, 
bool __repipe)
        tep_set_long_size(pevent, file_long_size);
        tep_set_page_size(pevent, file_page_size);
 
+       /* Write initial file header to trace.dat */
+       if (trace_dat_fp && !trace_dat_write_failed) {
+               unsigned char endian = file_bigendian;
+               unsigned char long_size = file_long_size;
+               unsigned int page_size = to_file_u32(pevent, file_page_size);
+               unsigned long long placeholder = to_file_u64(pevent, 0);
+
+               if (!fwrite(magic_buf, 1, 10, trace_dat_fp) ||    /* magic + 
"tracing" */
+                   !fwrite(TRACE_DAT_VERSION, 1, 2, trace_dat_fp) ||
+                   !fwrite(&endian, 1, 1, trace_dat_fp) ||
+                   !fwrite(&long_size, 1, 1, trace_dat_fp) ||
+                   !fwrite(&page_size, sizeof(unsigned int), 1, trace_dat_fp) 
||
+                   !fwrite("none", 1, 4, trace_dat_fp) ||
+                   !fwrite("\0", 1, 1, trace_dat_fp) ||
+                   !fwrite("\0", 1, 1, trace_dat_fp)) {
+                       pr_warning("Failed to write trace.dat initalfile 
header\n");
+                       trace_dat_write_failed = true;
+               }
+
+               if (!trace_dat_write_failed) {
+                       trace_dat_options_offset = ftell(trace_dat_fp);
+                       if (!fwrite(&placeholder, sizeof(unsigned long long), 
1, trace_dat_fp)) {
+                               pr_warning("Failed to write trace.dat initial 
file header\n");
+                               trace_dat_write_failed = true;
+                       }
+               }
+       }
+
        err = read_header_files(pevent);
        if (err)
                goto out;
@@ -460,6 +747,12 @@ ssize_t trace_report(int fd, struct trace_event *tevent, 
bool __repipe)
                if (err)
                        goto out;
        }
+       /* Write strings section to trace.dat output file */
+       if (trace_dat_fp && !trace_dat_write_failed) {
+               err = trace_dat__write_strings_section(pevent);
+               if (err)
+                       goto out;
+       }
 
        size = trace_data_size;
        repipe = false;
-- 
2.47.3


Reply via email to