[RFC PATCH v1 7/8] perf record: Add --buildid-offset option

From: Ian Rogers

Date: Fri Aug 07 2026 - 03:34:38 EST


Add the --buildid-offset flag to perf record to natively request
PERF_SAMPLE_BUILD_ID_OFFSET and PERF_SAMPLE_CALLCHAIN_BUILD_ID_OFFSET
from the kernel. This configures the evsel attributes by replacing
the standard IP and CALLCHAIN bits with the build ID offset equivalents.

Signed-off-by: Ian Rogers <irogers@xxxxxxxxxx>
---
tools/perf/builtin-record.c | 7 +++++++
tools/perf/util/evsel.c | 11 +++++++++++
tools/perf/util/record.h | 1 +
3 files changed, 19 insertions(+)

diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index f58d7e3c7879..9ff9cfc06278 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -3608,6 +3608,8 @@ static struct option __record_options[] = {
"file", "vmlinux pathname"),
OPT_BOOLEAN(0, "buildid-all", &record.buildid_all,
"Record build-id of all DSOs regardless of hits"),
+ OPT_BOOLEAN(0, "buildid-offset", &record.opts.buildid_offset,
+ "Record build id offset instead of IP"),
OPT_BOOLEAN_SET(0, "buildid-mmap", &record.buildid_mmap, &record.buildid_mmap_set,
"Record build-id in mmap events and skip build-id processing."),
OPT_BOOLEAN(0, "timestamp-filename", &record.timestamp_filename,
@@ -4166,6 +4168,11 @@ int cmd_record(int argc, const char **argv)
rec->no_buildid_cache = true;
}

+ if (rec->opts.buildid_offset) {
+ /* Do not drop mmap events here so we can generate build ids later */
+ /* rec->opts.synth &= ~PERF_SYNTH_MMAP; */
+ }
+
if (rec->opts.record_cgroup && !perf_can_record_cgroup()) {
pr_err("Kernel has no cgroup sampling support.\n");
err = -EINVAL;
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index d9a07f5825e8..587f0fa41cce 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -1744,6 +1744,17 @@ void evsel__config(struct evsel *evsel, const struct record_opts *opts,
if (opts->sample_transaction)
evsel__set_sample_bit(evsel, TRANSACTION);

+ if (opts->buildid_offset) {
+ if (evsel->core.attr.sample_type & PERF_SAMPLE_IP) {
+ evsel__reset_sample_bit(evsel, IP);
+ evsel__set_sample_bit(evsel, BUILD_ID_OFFSET);
+ }
+ if (evsel->core.attr.sample_type & PERF_SAMPLE_CALLCHAIN) {
+ evsel__reset_sample_bit(evsel, CALLCHAIN);
+ evsel__set_sample_bit(evsel, CALLCHAIN_BUILD_ID_OFFSET);
+ }
+ }
+
if (opts->running_time) {
evsel->core.attr.read_format |=
PERF_FORMAT_TOTAL_TIME_ENABLED |
diff --git a/tools/perf/util/record.h b/tools/perf/util/record.h
index 93627c9a7338..a8cec7db150e 100644
--- a/tools/perf/util/record.h
+++ b/tools/perf/util/record.h
@@ -55,6 +55,7 @@ struct record_opts {
bool kcore;
bool text_poke;
bool build_id;
+ bool buildid_offset;
unsigned int freq;
unsigned int mmap_pages;
unsigned int auxtrace_mmap_pages;
--
2.55.0.679.g6767b8d81c-goog