From: sashiko-bot@kernel.org
To: "Tanushree Shah" <tshah@linux.ibm.com>
Cc: linux-perf-users@vger.kernel.org
Subject: Re: [RFC PATCH v3 1/5] perf/trace-dat: Add trace.dat export infrastructure
Date: Mon, 03 Aug 2026 15:14:23 +0000 [thread overview]
Message-ID: <20260803151423.D69211F000E9@smtp.kernel.org> (raw)
In-Reply-To: <20260803145958.299956-2-tshah@linux.ibm.com>
Thank you for your contribution! Sashiko AI review found 5 potential issue(s) to consider:
- [High] The `TIME_EXTEND` upper bits are calculated using an incorrect bitwise right shift of 5 instead of 27, resulting in corrupted extended timestamps.
- [High] The ftrace ring buffer event length encoding for large events incorrectly writes the unaligned payload length, omitting necessary alignment padding.
- [High] Using 32-bit `long` variables and `ftell()`/`fseek()` for file offsets truncates trace files larger than 2GB on 32-bit systems.
- [High] Trace data export file headers and ftrace metadata are written in host endianness instead of the target trace's endianness, breaking cross-platform analysis.
- [Medium] Lack of validation for `trace_dat_page_size` can result in a fatal integer division by zero exception when calculating page padding.
--
--- Patch [1]: [RFC PATCH v3 1/5] perf/trace-dat: Add trace.dat export infrastructure ---
commit 34a2391aa9ca8393dfbdda4a477f39710a409324
Author: Tanushree Shah <tshah@linux.ibm.com>
perf/trace-dat: Add trace.dat export infrastructure
This commit adds new utility files to implement infrastructure for
exporting perf.data tracepoints to the trace.dat format. It provides
functions for managing per-cpu event buffers and constructing ftrace
ring buffer pages.
> diff --git a/tools/perf/util/trace-dat.c b/tools/perf/util/trace-dat.c
> new file mode 100644
> index 0000000000000..55a7bd982c6f8
> --- /dev/null
> +++ b/tools/perf/util/trace-dat.c
[ ... ]
> +static int trace_dat__write_page(FILE *fp, unsigned long long base_ts,
> + char **records, int *rec_sizes, int nr_recs)
> +{
> + unsigned long long commit = 0;
> + int offset = TRACE_DAT_RECORD_HEADER_SIZE;
> + int i;
> + char *page;
> +
> + page = calloc(1, trace_dat_page_size);
> + if (!page)
> + return -ENOMEM;
> +
> + for (i = 0; i < nr_recs; i++) {
> + memcpy(page + offset, records[i], rec_sizes[i]);
> + offset += rec_sizes[i];
> + commit += rec_sizes[i];
> + }
> +
> + memcpy(page, &base_ts, sizeof(base_ts));
> + memcpy(page + sizeof(base_ts), &commit, sizeof(commit));
[Severity: High]
Does this write the ftrace page header using native host endianness?
If a trace was recorded on a different architecture, copying the integers
directly to the output stream might mix host-endian metadata with
target-endian payloads.
Should this metadata be byte-swapped to match the target architecture
to ensure cross-platform trace analysis works correctly?
> +
> + if (!fwrite(page, 1, trace_dat_page_size, fp)) {
> + free(page);
> + return -EIO;
> + }
> + free(page);
> +
> + return 0;
> +}
[ ... ]
> +static int trace_dat__write_cpu_dat(FILE *fp, int cpu, unsigned long long *file_offset_out)
> +{
[ ... ]
> + /* Emit TIME_EXTEND when delta does not fit in 27 bits */
> + if (time_delta > TRACE_DAT_RECORD_TIME_MASK) {
> + unsigned int extend_hdr;
> + unsigned int delta_upper;
> +
> + extend_size = TRACE_DAT_RECORD_TIME_EXTEND_SIZE;
> + extend = calloc(1, extend_size);
> + 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;
[Severity: High]
Does this shift the upper bits of the time delta by the correct amount?
The code uses TRACE_DAT_RECORD_TIME_SHIFT, which is 5.
This calculates the upper bits as time_delta >> 5 rather than >> 27.
Would this copy the middle 22 bits instead of the upper bits, causing
timestamp corruption for any events that follow a time extend?
> +
> + memcpy(extend, &extend_hdr, TRACE_DAT_WORD_SIZE);
> + memcpy(extend + TRACE_DAT_WORD_SIZE, &delta_upper,
> + TRACE_DAT_WORD_SIZE);
> +
> + time_delta = 0;
> + }
[ ... ]
> + hdr_word = (time_delta << TRACE_DAT_RECORD_TIME_SHIFT) | type_len;
> +
> + data_rec = calloc(1, data_rec_size);
> + if (!data_rec) {
> + free(extend);
> + ret = -ENOMEM;
> + goto out_free;
> + }
> +
> + 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);
[Severity: High]
For large events, is this writing the raw, unaligned data_len into the
payload length field?
The internal offset data_rec_size advances by the padded size, but the
unaligned data_len is written here. If data_len is not a multiple of 4,
a parser reading this file might compute an incorrect total length and
fail to skip the alignment padding.
Could this cause the reader to misread the next event boundary?
> +
> + memcpy(data_rec + payload_offset, event->raw, data_len);
> +
[ ... ]
> +int trace_dat__write_flyrecord_section(void)
> +{
[ ... ]
> + section_size_pos = ftell(trace_dat_fp);
> + if (!fwrite(§ion_size, sizeof(unsigned long long), 1, trace_dat_fp)) {
> + ret = -EIO;
> + goto cleanup;
> + }
> +
> + /* Align to page boundary */
> + after_header = ftell(trace_dat_fp);
> + padding_needed = (trace_dat_page_size -
> + (after_header % trace_dat_page_size)) % trace_dat_page_size;
[Severity: Medium]
Is trace_dat_page_size guaranteed to be non-zero here?
If the caller fails to initialize this global variable or parses a
configuration that sets it to zero, this modulo operation will trigger a
fatal integer division by zero exception.
> +
> + if (padding_needed > 0) {
> + pad = calloc(1, padding_needed);
> + if (!pad) {
> + ret = -ENOMEM;
> + goto cleanup;
> + }
> +
> + if (!fwrite(pad, 1, padding_needed, trace_dat_fp)) {
> + free(pad);
> + ret = -EIO;
> + goto cleanup;
> + }
> + free(pad);
> + }
> +
> + /* write per-cpu trace data */
[ ... ]
> diff --git a/tools/perf/util/trace-dat.h b/tools/perf/util/trace-dat.h
> new file mode 100644
> index 0000000000000..9aec37b708d41
> --- /dev/null
> +++ b/tools/perf/util/trace-dat.h
> @@ -0,0 +1,83 @@
[ ... ]
> +extern FILE *trace_dat_fp;
> +extern int trace_dat_page_size;
> +extern int trace_dat_nr_cpus;
> +extern long trace_dat_options_offset;
> +extern long trace_dat_header_info_offset;
> +extern long trace_dat_events_format_offset;
> +extern long trace_dat_ftrace_format_offset;
> +extern long trace_dat_kallsyms_offset;
> +extern long trace_dat_cmdline_offset;
> +extern long trace_dat_next_options_offset;
[Severity: High]
Are these offsets safe for trace files larger than 2GB on 32-bit systems?
Using long for offsets and relying on ftell() limits the maximum supported
file size to 2GB on 32-bit architectures. Since perf.data files can easily
exceed this size, could this result in integer overflow and corrupted offsets?
Should this use standard 64-bit interfaces like u64 and ftello()/fseeko()
instead?
> +
> +/* collect and manage per-cpu tracepoint event buffers */
> +#define TRACE_DAT_RECORD_TYPE_TIME_EXTEND 30
> +#define TRACE_DAT_RECORD_TIME_EXTEND_SIZE 8
> +#define TRACE_DAT_RECORD_TYPE_LEN_MAX 28
[ ... ]
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260803145958.299956-1-tshah@linux.ibm.com?part=1
next prev parent reply other threads:[~2026-08-03 15:14 UTC|newest]
Thread overview: 14+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-03 14:59 [RFC PATCH v3 0/5] Add perf.data tracepoint events to trace.dat conversion Tanushree Shah
2026-08-03 14:59 ` [RFC PATCH v3 1/5] perf/trace-dat: Add trace.dat export infrastructure Tanushree Shah
2026-08-03 15:14 ` sashiko-bot [this message]
2026-08-03 14:59 ` [RFC PATCH v3 2/5] perf/trace-event: Write trace.dat metadata sections during parsing Tanushree Shah
2026-08-03 15:14 ` sashiko-bot
2026-08-03 14:59 ` [RFC PATCH v3 3/5] perf data-convert: Add perf.data to trace.dat conversion backend Tanushree Shah
2026-08-03 15:11 ` sashiko-bot
2026-08-03 14:59 ` [RFC PATCH v3 4/5] perf data: Add --to-trace-dat option for converting perf.data tracepoint events into trace.dat format Tanushree Shah
2026-08-03 15:13 ` sashiko-bot
2026-08-03 14:59 ` [RFC PATCH v3 5/5] perf test: Add test validating trace.dat generated by 'perf data convert --to-trace-dat' Tanushree Shah
2026-08-03 15:19 ` sashiko-bot
2026-08-06 0:15 ` Ian Rogers
2026-08-06 9:20 ` Tanushree Shah
2026-08-06 0:18 ` [RFC PATCH v3 0/5] Add perf.data tracepoint events to trace.dat conversion Ian Rogers
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260803151423.D69211F000E9@smtp.kernel.org \
--to=sashiko-bot@kernel.org \
--cc=linux-perf-users@vger.kernel.org \
--cc=sashiko-reviews@lists.linux.dev \
--cc=tshah@linux.ibm.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.