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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox