From: Ian Rogers <irogers@google.com>
To: Steven Rostedt <rostedt@goodmis.org>,
Masami Hiramatsu <mhiramat@kernel.org>,
Alexei Starovoitov <ast@kernel.org>,
Daniel Borkmann <daniel@iogearbox.net>,
John Fastabend <john.fastabend@gmail.com>,
Andrii Nakryiko <andrii@kernel.org>,
Eduard Zingerman <eddyz87@gmail.com>,
Kumar Kartikeya Dwivedi <memxor@gmail.com>,
Martin KaFai Lau <martin.lau@linux.dev>,
Song Liu <song@kernel.org>,
Yonghong Song <yonghong.song@linux.dev>,
Jiri Olsa <jolsa@kernel.org>,
Emil Tsalapatis <emil@etsalapatis.com>,
Peter Zijlstra <peterz@infradead.org>,
Ingo Molnar <mingo@redhat.com>,
Arnaldo Carvalho de Melo <acme@kernel.org>,
Namhyung Kim <namhyung@kernel.org>,
Mark Rutland <mark.rutland@arm.com>,
Alexander Shishkin <alexander.shishkin@linux.intel.com>,
Ian Rogers <irogers@google.com>,
Adrian Hunter <adrian.hunter@intel.com>,
James Clark <james.clark@linaro.org>,
Suzuki K Poulose <suzuki.poulose@arm.com>,
Mike Leach <mike.leach@arm.com>, Leo Yan <leo.yan@arm.com>,
John Garry <john.g.garry@oracle.com>,
Will Deacon <will@kernel.org>, Thomas Gleixner <tglx@kernel.org>,
Dapeng Mi <dapeng1.mi@linux.intel.com>,
Ravi Bangoria <ravi.bangoria@amd.com>,
Swapnil Sapkal <swapnil.sapkal@amd.com>,
Thomas Falcon <thomas.falcon@intel.com>,
Thomas Richter <tmricht@linux.ibm.com>,
Dmitrii Dolgov <9erthalion6@gmail.com>,
Eric Biggers <ebiggers@kernel.org>, Zecheng Li <zli94@ncsu.edu>,
Gabriel Marin <gmx@google.com>,
Tengda Wu <wutengda@huaweicloud.com>,
Derek Foreman <derek.foreman@collabora.com>,
Tanushree Shah <tshah@linux.ibm.com>,
Ankur Arora <ankur.a.arora@oracle.com>,
Aaron Tomlin <atomlin@atomlin.com>, tanze <tanze@kylinos.cn>,
Rui Qi <qirui.001@bytedance.com>,
Howard Chu <howardchu95@gmail.com>, Chuck Lever <cel@kernel.org>,
Shimin Guo <shimin.guo@skydio.com>,
Alessio Podda <aleph.pi.gh@gmail.com>,
linux-kernel@vger.kernel.org, bpf@vger.kernel.org,
linux-perf-users@vger.kernel.org, coresight@lists.linaro.org,
linux-arm-kernel@lists.infradead.org
Subject: [RFC PATCH v1 5/8] perf tools: Internal support for BUILD_ID_OFFSET
Date: Fri, 7 Aug 2026 00:18:15 -0700 [thread overview]
Message-ID: <20260807071818.718751-6-irogers@google.com> (raw)
In-Reply-To: <20260807071818.718751-1-irogers@google.com>
Implement user-space parsing for the new sample types in evsel,
update perf_event_attr_fprintf to display the new bits
in 'perf report -D', and update synthetic event parameter names.
Signed-off-by: Ian Rogers <irogers@google.com>
---
tools/perf/builtin-script.c | 16 +++--
tools/perf/util/event.c | 42 +++++++----
tools/perf/util/evsel.c | 24 +++++++
tools/perf/util/evsel.h | 3 +-
tools/perf/util/evsel_fprintf.c | 2 +-
tools/perf/util/machine.c | 87 ++++++++++++++++-------
tools/perf/util/maps.c | 29 ++++++++
tools/perf/util/maps.h | 2 +
tools/perf/util/perf_event_attr_fprintf.c | 3 +-
tools/perf/util/sample.h | 13 ++++
tools/perf/util/synthetic-events.c | 20 ++++++
11 files changed, 192 insertions(+), 49 deletions(-)
diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
index 93cffafb1af7..65229e9952a8 100644
--- a/tools/perf/builtin-script.c
+++ b/tools/perf/builtin-script.c
@@ -494,7 +494,8 @@ static int evsel__check_attr(struct evsel *evsel, struct perf_session *session)
return -EINVAL;
if (PRINT_FIELD(IP)) {
- if (evsel__check_stype(evsel, PERF_SAMPLE_IP, "IP", PERF_OUTPUT_IP))
+ if (evsel__check_stype(evsel, PERF_SAMPLE_IP | PERF_SAMPLE_BUILD_ID_OFFSET,
+ "IP", PERF_OUTPUT_IP))
return -EINVAL;
}
@@ -511,7 +512,8 @@ static int evsel__check_attr(struct evsel *evsel, struct perf_session *session)
return -EINVAL;
if (PRINT_FIELD(SYM) &&
- !(evsel->core.attr.sample_type & (PERF_SAMPLE_IP|PERF_SAMPLE_ADDR))) {
+ !(evsel->core.attr.sample_type & (PERF_SAMPLE_IP | PERF_SAMPLE_ADDR |
+ PERF_SAMPLE_BUILD_ID_OFFSET))) {
pr_err("Display of symbols requested but neither sample IP nor "
"sample address\navailable. Hence, no addresses to convert "
"to symbols.\n");
@@ -523,7 +525,8 @@ static int evsel__check_attr(struct evsel *evsel, struct perf_session *session)
return -EINVAL;
}
if (PRINT_FIELD(DSO) &&
- !(evsel->core.attr.sample_type & (PERF_SAMPLE_IP|PERF_SAMPLE_ADDR))) {
+ !(evsel->core.attr.sample_type & (PERF_SAMPLE_IP | PERF_SAMPLE_ADDR |
+ PERF_SAMPLE_BUILD_ID_OFFSET))) {
pr_err("Display of DSO requested but no address to convert.\n");
return -EINVAL;
}
@@ -1702,7 +1705,7 @@ static int perf_sample__fprintf_bts(struct perf_sample *sample,
unsigned int print_opts = output[type].print_ip_opts;
struct callchain_cursor *cursor = NULL;
- if (symbol_conf.use_callchain && sample->callchain) {
+ if (symbol_conf.use_callchain && (sample->callchain || sample->callchain_bids)) {
cursor = get_tls_callchain_cursor();
if (thread__resolve_callchain(al->thread, cursor,
sample, NULL, NULL,
@@ -2528,7 +2531,7 @@ static void process_event(struct perf_script *script,
if (script->stitch_lbr)
thread__set_lbr_stitch_enable(al->thread, true);
- if (symbol_conf.use_callchain && sample->callchain) {
+ if (symbol_conf.use_callchain && (sample->callchain || sample->callchain_bids)) {
cursor = get_tls_callchain_cursor();
if (thread__resolve_callchain(al->thread, cursor,
sample, NULL, NULL,
@@ -2815,7 +2818,7 @@ static int process_deferred_sample_event(const struct perf_tool *tool,
if (PRINT_FIELD(IP)) {
struct callchain_cursor *cursor = NULL;
- if (symbol_conf.use_callchain && sample->callchain) {
+ if (symbol_conf.use_callchain && (sample->callchain || sample->callchain_bids)) {
cursor = get_tls_callchain_cursor();
if (thread__resolve_callchain(al.thread, cursor,
sample, NULL, NULL,
@@ -2897,6 +2900,7 @@ static int process_attr(const struct perf_tool *tool, union perf_event *event,
/* Enable fields for callchain entries */
if (symbol_conf.use_callchain &&
(sample_type & PERF_SAMPLE_CALLCHAIN ||
+ sample_type & PERF_SAMPLE_CALLCHAIN_BUILD_ID_OFFSET ||
sample_type & PERF_SAMPLE_BRANCH_STACK ||
(sample_type & PERF_SAMPLE_REGS_USER &&
sample_type & PERF_SAMPLE_STACK_USER))) {
diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c
index 982fb9ed049f..86df3edd1bfa 100644
--- a/tools/perf/util/event.c
+++ b/tools/perf/util/event.c
@@ -702,12 +702,6 @@ struct map *thread__find_map(struct thread *thread, struct perf_sample *sample,
thread__zput(al->thread);
al->thread = thread__get(thread);
- if (sample->ip) {
- al->addr = sample->ip;
- } else {
- pr_debug("Sample missing IP data\n");
- return NULL;
- }
al->cpumode = sample->cpumode;
al->filtered = 0;
@@ -740,15 +734,33 @@ struct map *thread__find_map(struct thread *thread, struct perf_sample *sample,
return NULL;
}
- al->map = maps__find(maps, al->addr);
- if (al->map != NULL) {
- /*
- * Kernel maps might be changed when loading symbols so loading
- * must be done prior to using kernel maps.
- */
- if (load_map)
- map__load(al->map);
- al->addr = map__map_ip(al->map, al->addr);
+
+ if (sample->ip) {
+ al->addr = sample->ip;
+ al->map = maps__find(maps, al->addr);
+ if (al->map != NULL) {
+ /*
+ * Kernel maps might be changed when loading symbols so loading
+ * must be done prior to using kernel maps.
+ */
+ if (load_map)
+ map__load(al->map);
+ al->addr = map__map_ip(al->map, al->addr);
+ }
+ } else if (sample->bid.bid && sample->bid.bid->size > 0) {
+ struct build_id bid;
+
+ build_id__init(&bid, sample->bid.bid->data, sample->bid.bid->size);
+ al->addr = sample->bid.offset;
+ al->map = maps__find_by_build_id(maps, &bid);
+ if (al->map != NULL) {
+ if (load_map)
+ map__load(al->map);
+ /* al->addr is already a file offset */
+ }
+ } else {
+ pr_debug("Sample missing IP or build id + offset data\n");
+ return NULL;
}
return al->map;
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index d4cb455f4a7d..d9a07f5825e8 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -3778,6 +3778,30 @@ int __evsel__parse_sample(struct evsel *evsel, union perf_event *event,
array = (void *)array + sz;
}
+ if (type & PERF_SAMPLE_BUILD_ID_OFFSET) {
+ data->bid.bid = (struct perf_build_id *) array;
+ array += sizeof(struct perf_build_id) / sizeof(u64);
+ data->bid.offset = *array;
+ array++;
+ } else {
+ data->bid.bid = NULL;
+ data->bid.offset = 0;
+ }
+
+
+ if (type & PERF_SAMPLE_CALLCHAIN_BUILD_ID_OFFSET) {
+ OVERFLOW_CHECK_u64(array);
+ sz = *array++;
+
+ OVERFLOW_CHECK(array, sz * (sizeof(struct perf_build_id) + sizeof(u64)), max_size);
+ data->callchain_bids = (struct perf_build_id *) array;
+ data->callchain_bids_nr = sz;
+ array += sz * (sizeof(struct perf_build_id) + sizeof(u64)) / sizeof(u64);
+ } else {
+ data->callchain_bids = NULL;
+ data->callchain_bids_nr = 0;
+ }
+
if (evsel__is_offcpu_event(evsel)) {
if (__set_offcpu_sample(data))
goto out_efault;
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h
index d9ecc6628217..e082e6e6af66 100644
--- a/tools/perf/util/evsel.h
+++ b/tools/perf/util/evsel.h
@@ -567,7 +567,8 @@ static inline bool evsel__has_callchain(const struct evsel *evsel)
* For reporting purposes, an evsel sample can have a recorded callchain
* or a callchain synthesized from AUX area data.
*/
- return evsel->core.attr.sample_type & PERF_SAMPLE_CALLCHAIN ||
+ return evsel->core.attr.sample_type & (PERF_SAMPLE_CALLCHAIN |
+ PERF_SAMPLE_CALLCHAIN_BUILD_ID_OFFSET) ||
evsel->synth_sample_type & PERF_SAMPLE_CALLCHAIN;
}
diff --git a/tools/perf/util/evsel_fprintf.c b/tools/perf/util/evsel_fprintf.c
index 0f7a25500a44..9f7054410a2c 100644
--- a/tools/perf/util/evsel_fprintf.c
+++ b/tools/perf/util/evsel_fprintf.c
@@ -131,7 +131,7 @@ int sample__fprintf_callchain(struct perf_sample *sample, int left_alignment,
if (cursor == NULL)
return fprintf(fp, "<not enough memory for the callchain cursor>%s", print_oneline ? "" : "\n");
- if (sample->callchain) {
+ if (sample->callchain || sample->callchain_bids) {
callchain_cursor_commit(cursor);
while (1) {
diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c
index aeace492b4e7..82de7bc7eba1 100644
--- a/tools/perf/util/machine.c
+++ b/tools/perf/util/machine.c
@@ -2216,7 +2216,9 @@ static int add_callchain_ip(struct thread *thread,
struct branch_flags *flags,
struct iterations *iter,
u64 branch_from,
- bool symbols)
+ bool symbols,
+ struct perf_build_id *bid,
+ u64 offset)
{
struct map_symbol ms = {};
struct addr_location al;
@@ -2230,7 +2232,9 @@ static int add_callchain_ip(struct thread *thread,
al.srcline = NULL;
if (!cpumode) {
thread__find_cpumode_addr_location(thread,
- &(struct perf_sample){.ip = ip},
+ &(struct perf_sample){.ip = ip,
+ .bid = { .bid = bid,
+ .offset = offset }},
symbols, &al);
} else {
if (ip >= PERF_CONTEXT_MAX) {
@@ -2411,7 +2415,7 @@ static int lbr_callchain_add_kernel_ip(struct thread *thread,
err = add_callchain_ip(thread, cursor, parent,
root_al, &cpumode, chain->ips[i],
false, NULL, NULL, branch_from,
- symbols);
+ symbols, /*bid=*/NULL, /*offset=*/0);
if (err)
return err;
}
@@ -2422,7 +2426,7 @@ static int lbr_callchain_add_kernel_ip(struct thread *thread,
err = add_callchain_ip(thread, cursor, parent,
root_al, &cpumode, chain->ips[i],
false, NULL, NULL, branch_from,
- symbols);
+ symbols, /*bid=*/NULL, /*offset=*/0);
if (err)
return err;
}
@@ -2505,7 +2509,7 @@ static int lbr_callchain_add_lbr_ip(struct thread *thread,
err = add_callchain_ip(thread, cursor, parent,
root_al, &cpumode, ip,
true, flags, NULL,
- *branch_from, symbols);
+ *branch_from, symbols, /*bid=*/NULL, /*offset=*/0);
if (err)
return err;
@@ -2530,7 +2534,7 @@ static int lbr_callchain_add_lbr_ip(struct thread *thread,
err = add_callchain_ip(thread, cursor, parent,
root_al, &cpumode, ip,
true, flags, NULL,
- *branch_from, symbols);
+ *branch_from, symbols, /*bid=*/NULL, /*offset=*/0);
if (err)
return err;
save_lbr_cursor_node(thread, cursor, i);
@@ -2545,7 +2549,7 @@ static int lbr_callchain_add_lbr_ip(struct thread *thread,
err = add_callchain_ip(thread, cursor, parent,
root_al, &cpumode, ip,
true, flags, NULL,
- *branch_from, symbols);
+ *branch_from, symbols, /*bid=*/NULL, /*offset=*/0);
if (err)
return err;
save_lbr_cursor_node(thread, cursor, i);
@@ -2565,7 +2569,7 @@ static int lbr_callchain_add_lbr_ip(struct thread *thread,
err = add_callchain_ip(thread, cursor, parent,
root_al, &cpumode, ip,
true, flags, NULL,
- *branch_from, symbols);
+ *branch_from, symbols, /*bid=*/NULL, /*offset=*/0);
if (err)
return err;
}
@@ -2829,7 +2833,8 @@ static int find_prev_cpumode(struct ip_callchain *chain, struct thread *thread,
if (ip >= PERF_CONTEXT_MAX) {
err = add_callchain_ip(thread, cursor, parent,
root_al, cpumode, ip,
- false, NULL, NULL, 0, symbols);
+ false, NULL, NULL, 0, symbols,
+ /*bid=*/NULL, /*offset=*/0);
break;
}
}
@@ -2857,6 +2862,7 @@ static int thread__resolve_callchain_sample(struct thread *thread,
struct branch_stack *branch = sample->branch_stack;
struct branch_entry *entries = perf_sample__branch_entries(sample);
struct ip_callchain *chain = sample->callchain;
+ struct ip_callchain *alloc_chain = NULL;
int chain_nr = 0;
u8 cpumode = PERF_RECORD_MISC_USER;
int i, j, err, nr_entries, usr_idx;
@@ -2864,6 +2870,16 @@ static int thread__resolve_callchain_sample(struct thread *thread,
int first_call = 0;
u64 leaf_frame_caller;
+ if (!chain && sample->callchain_bids_nr > 0) {
+ alloc_chain = malloc(sizeof(*chain) + sample->callchain_bids_nr * sizeof(u64));
+ if (alloc_chain) {
+ alloc_chain->nr = sample->callchain_bids_nr;
+ for (i = 0; i < (int)sample->callchain_bids_nr; i++)
+ alloc_chain->ips[i] = ((u64 *)sample->callchain_bids)[i * 4 + 3];
+ chain = alloc_chain;
+ }
+ }
+
if (chain)
chain_nr = chain->nr;
@@ -2874,8 +2890,10 @@ static int thread__resolve_callchain_sample(struct thread *thread,
root_al, max_stack,
!env ? 0 : env->max_branches,
symbols);
- if (err)
- return (err < 0) ? err : 0;
+ if (err) {
+ err = (err < 0) ? err : 0;
+ goto out;
+ }
}
/*
@@ -2938,18 +2956,20 @@ static int thread__resolve_callchain_sample(struct thread *thread,
root_al,
NULL, be[i].to,
true, &be[i].flags,
- NULL, be[i].from, symbols);
+ NULL, be[i].from, symbols,
+ /*bid=*/NULL, /*offset=*/0);
if (!err) {
err = add_callchain_ip(thread, cursor, parent, root_al,
NULL, be[i].from,
true, &be[i].flags,
- &iter[i], 0, symbols);
+ &iter[i], 0, symbols,
+ /*bid=*/NULL, /*offset=*/0);
}
if (err == -EINVAL)
break;
if (err)
- return err;
+ goto out;
}
if (chain_nr == 0)
@@ -2962,12 +2982,16 @@ static int thread__resolve_callchain_sample(struct thread *thread,
if (chain && callchain_param.order != ORDER_CALLEE) {
err = find_prev_cpumode(chain, thread, cursor, parent, root_al,
&cpumode, chain->nr - first_call, symbols);
- if (err)
- return (err < 0) ? err : 0;
+ if (err) {
+ err = (err < 0) ? err : 0;
+ goto out;
+ }
}
for (i = first_call, nr_entries = 0;
i < chain_nr && nr_entries < max_stack; i++) {
u64 ip;
+ struct perf_build_id *bid = NULL;
+ u64 offset = 0;
if (callchain_param.order == ORDER_CALLEE)
j = i;
@@ -2979,13 +3003,19 @@ static int thread__resolve_callchain_sample(struct thread *thread,
continue;
#endif
ip = chain->ips[j];
+ if (sample->callchain_bids) {
+ bid = (struct perf_build_id *)&((u64 *)sample->callchain_bids)[j * 4];
+ offset = ((u64 *)sample->callchain_bids)[j * 4 + 3];
+ }
if (ip < PERF_CONTEXT_MAX)
++nr_entries;
else if (callchain_param.order != ORDER_CALLEE) {
err = find_prev_cpumode(chain, thread, cursor, parent,
root_al, &cpumode, j, symbols);
- if (err)
- return (err < 0) ? err : 0;
+ if (err) {
+ err = (err < 0) ? err : 0;
+ goto out;
+ }
continue;
}
@@ -3011,21 +3041,28 @@ static int thread__resolve_callchain_sample(struct thread *thread,
err = add_callchain_ip(thread, cursor, parent,
root_al, &cpumode, leaf_frame_caller,
- false, NULL, NULL, 0, symbols);
- if (err)
- return (err < 0) ? err : 0;
+ false, NULL, NULL, 0, symbols, bid, offset);
+ if (err) {
+ err = (err < 0) ? err : 0;
+ goto out;
+ }
}
}
err = add_callchain_ip(thread, cursor, parent,
root_al, &cpumode, ip,
- false, NULL, NULL, 0, symbols);
+ false, NULL, NULL, 0, symbols, bid, offset);
- if (err)
- return (err < 0) ? err : 0;
+ if (err) {
+ err = (err < 0) ? err : 0;
+ goto out;
+ }
}
- return 0;
+ err = 0;
+out:
+ free(alloc_chain);
+ return err;
}
static int unwind_entry(struct unwind_entry *entry, void *arg)
diff --git a/tools/perf/util/maps.c b/tools/perf/util/maps.c
index f808df2fe77b..7884720481d8 100644
--- a/tools/perf/util/maps.c
+++ b/tools/perf/util/maps.c
@@ -1251,6 +1251,35 @@ static int map__strcmp_name(const void *name, const void *b)
return strcmp(name, dso__short_name(dso));
}
+struct map *maps__find_by_build_id(struct maps *maps, struct build_id *bid)
+{
+ struct map *result = NULL;
+ bool done = false;
+
+ /* See locking/sorting note. */
+ while (!done) {
+ down_read(maps__lock(maps));
+ if (maps__maps_by_address_sorted(maps)) {
+ struct map **maps_by_address = maps__maps_by_address(maps);
+ unsigned int nr_maps = maps__nr_maps(maps);
+
+ for (unsigned int i = 0; i < nr_maps; i++) {
+ struct map *map = maps_by_address[i];
+
+ if (dso__build_id_equal(map__dso(map), bid)) {
+ result = map__get(map);
+ break;
+ }
+ }
+ done = true;
+ }
+ up_read(maps__lock(maps));
+ if (!done)
+ maps__sort_by_address(maps);
+ }
+ return result;
+}
+
struct map *maps__find_by_name(struct maps *maps, const char *name)
{
struct map *result = NULL;
diff --git a/tools/perf/util/maps.h b/tools/perf/util/maps.h
index 4ec9b7453a3b..6f1791457068 100644
--- a/tools/perf/util/maps.h
+++ b/tools/perf/util/maps.h
@@ -11,6 +11,7 @@ struct ref_reloc_sym;
struct machine;
struct map;
struct maps;
+struct build_id;
#define KMAP_NAME_LEN 256
@@ -76,6 +77,7 @@ int maps__find_ams(struct maps *maps, struct addr_map_symbol *ams);
int maps__fixup_overlap_and_insert(struct maps *maps, struct map *new);
struct map *maps__find_by_name(struct maps *maps, const char *name);
+struct map *maps__find_by_build_id(struct maps *maps, struct build_id *bid);
struct map *maps__find_next_entry(struct maps *maps, struct map *map);
diff --git a/tools/perf/util/perf_event_attr_fprintf.c b/tools/perf/util/perf_event_attr_fprintf.c
index 3933639d76c5..41ccb45eca86 100644
--- a/tools/perf/util/perf_event_attr_fprintf.c
+++ b/tools/perf/util/perf_event_attr_fprintf.c
@@ -40,7 +40,8 @@ static void __p_sample_type(char *buf, size_t size, u64 value)
bit_name(IDENTIFIER), bit_name(REGS_INTR), bit_name(DATA_SRC),
bit_name(WEIGHT), bit_name(PHYS_ADDR), bit_name(AUX),
bit_name(CGROUP), bit_name(DATA_PAGE_SIZE), bit_name(CODE_PAGE_SIZE),
- bit_name(WEIGHT_STRUCT),
+ bit_name(WEIGHT_STRUCT), bit_name(BUILD_ID_OFFSET),
+ bit_name(CALLCHAIN_BUILD_ID_OFFSET),
{ .name = NULL, }
};
#undef bit_name
diff --git a/tools/perf/util/sample.h b/tools/perf/util/sample.h
index c4eae8b2fd06..5041c193a953 100644
--- a/tools/perf/util/sample.h
+++ b/tools/perf/util/sample.h
@@ -8,6 +8,7 @@
struct evsel;
struct machine;
struct thread;
+struct perf_build_id;
/* number of register is bound by the number of bits in regs_dump::mask (64) */
#define PERF_SAMPLE_REGS_CACHE_SIZE (8 * sizeof(u64))
@@ -158,6 +159,18 @@ struct perf_sample {
u64 code_page_size;
/** @cgroup: The sample event PERF_SAMPLE_CGROUP value. */
u64 cgroup;
+ /** @bid: The sample event PERF_SAMPLE_BUILD_ID_OFFSET value. */
+ struct {
+ struct perf_build_id *bid;
+ u64 offset;
+ } bid;
+ /**
+ * @callchain_bids: Build IDs for the callchain when
+ * PERF_SAMPLE_CALLCHAIN_BUILD_ID_OFFSET is set.
+ */
+ struct perf_build_id *callchain_bids;
+ /** @callchain_bids_nr: Number of entries in callchain_bids. */
+ u32 callchain_bids_nr;
/** @file_offset: Byte offset of this event in the perf.data file. */
u64 file_offset;
/** @flags: Extra flag data from auxiliary events like intel-pt. */
diff --git a/tools/perf/util/synthetic-events.c b/tools/perf/util/synthetic-events.c
index f7dedfb6bab8..a7b2b2a5f6bd 100644
--- a/tools/perf/util/synthetic-events.c
+++ b/tools/perf/util/synthetic-events.c
@@ -1701,6 +1701,13 @@ size_t perf_event__sample_event_size(const struct perf_sample *sample, u64 type,
result += sample->aux_sample.size;
}
+ if (type & PERF_SAMPLE_BUILD_ID_OFFSET)
+ result += sizeof(struct perf_build_id) + sizeof(u64);
+
+ if (type & PERF_SAMPLE_CALLCHAIN_BUILD_ID_OFFSET)
+ result += sizeof(u64) + sample->callchain->nr *
+ (sizeof(struct perf_build_id) + sizeof(u64));
+
return result;
}
@@ -1933,6 +1940,19 @@ int perf_event__synthesize_sample(union perf_event *event, u64 type, u64 read_fo
array = (void *)array + sz;
}
+ if (type & PERF_SAMPLE_BUILD_ID_OFFSET) {
+ memcpy(array, sample->bid.bid, sizeof(struct perf_build_id));
+ array += sizeof(struct perf_build_id) / sizeof(u64);
+ *array++ = sample->bid.offset;
+ }
+
+ if (type & PERF_SAMPLE_CALLCHAIN_BUILD_ID_OFFSET) {
+ *array++ = sample->callchain->nr;
+ sz = sample->callchain->nr * (sizeof(struct perf_build_id) + sizeof(u64));
+ memcpy(array, sample->callchain_bids, sz);
+ array += sz / sizeof(u64);
+ }
+
return 0;
}
--
2.55.0.679.g6767b8d81c-goog
next prev parent reply other threads:[~2026-08-07 7:18 UTC|newest]
Thread overview: 18+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-07 7:18 [RFC PATCH v1 0/8] perf/core, perf/tools: Add PERF_SAMPLE_BUILD_ID_OFFSET support Ian Rogers
2026-08-07 7:18 ` [RFC PATCH v1 1/8] perf event: Factor build_id out into its own top-level struct Ian Rogers
2026-08-07 7:33 ` sashiko-bot
2026-08-07 7:18 ` [RFC PATCH v1 2/8] perf/core: Add BUILD_ID_OFFSET to UAPI Ian Rogers
2026-08-07 7:42 ` sashiko-bot
2026-08-07 7:18 ` [RFC PATCH v1 3/8] perf/core: Implement BUILD_ID_OFFSET sample type Ian Rogers
2026-08-07 7:54 ` sashiko-bot
2026-08-07 7:18 ` [RFC PATCH v1 4/8] perf: Refactor thread map and symbol APIs to take perf_sample Ian Rogers
2026-08-07 8:20 ` sashiko-bot
2026-08-07 7:18 ` Ian Rogers [this message]
2026-08-07 8:41 ` [RFC PATCH v1 5/8] perf tools: Internal support for BUILD_ID_OFFSET sashiko-bot
2026-08-07 7:18 ` [RFC PATCH v1 6/8] perf inject: Extend perf inject to support bid_offset conversion Ian Rogers
2026-08-07 9:18 ` sashiko-bot
2026-08-07 7:18 ` [RFC PATCH v1 7/8] perf record: Add --buildid-offset option Ian Rogers
2026-08-07 9:47 ` sashiko-bot
2026-08-07 7:18 ` [RFC PATCH v1 8/8] perf tests: Add build_id_offset test coverage Ian Rogers
2026-08-07 9:58 ` sashiko-bot
2026-08-07 11:18 ` [RFC PATCH v1 0/8] perf/core, perf/tools: Add PERF_SAMPLE_BUILD_ID_OFFSET support Peter Zijlstra
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=20260807071818.718751-6-irogers@google.com \
--to=irogers@google.com \
--cc=9erthalion6@gmail.com \
--cc=acme@kernel.org \
--cc=adrian.hunter@intel.com \
--cc=aleph.pi.gh@gmail.com \
--cc=alexander.shishkin@linux.intel.com \
--cc=andrii@kernel.org \
--cc=ankur.a.arora@oracle.com \
--cc=ast@kernel.org \
--cc=atomlin@atomlin.com \
--cc=bpf@vger.kernel.org \
--cc=cel@kernel.org \
--cc=coresight@lists.linaro.org \
--cc=daniel@iogearbox.net \
--cc=dapeng1.mi@linux.intel.com \
--cc=derek.foreman@collabora.com \
--cc=ebiggers@kernel.org \
--cc=eddyz87@gmail.com \
--cc=emil@etsalapatis.com \
--cc=gmx@google.com \
--cc=howardchu95@gmail.com \
--cc=james.clark@linaro.org \
--cc=john.fastabend@gmail.com \
--cc=john.g.garry@oracle.com \
--cc=jolsa@kernel.org \
--cc=leo.yan@arm.com \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-perf-users@vger.kernel.org \
--cc=mark.rutland@arm.com \
--cc=martin.lau@linux.dev \
--cc=memxor@gmail.com \
--cc=mhiramat@kernel.org \
--cc=mike.leach@arm.com \
--cc=mingo@redhat.com \
--cc=namhyung@kernel.org \
--cc=peterz@infradead.org \
--cc=qirui.001@bytedance.com \
--cc=ravi.bangoria@amd.com \
--cc=rostedt@goodmis.org \
--cc=shimin.guo@skydio.com \
--cc=song@kernel.org \
--cc=suzuki.poulose@arm.com \
--cc=swapnil.sapkal@amd.com \
--cc=tanze@kylinos.cn \
--cc=tglx@kernel.org \
--cc=thomas.falcon@intel.com \
--cc=tmricht@linux.ibm.com \
--cc=tshah@linux.ibm.com \
--cc=will@kernel.org \
--cc=wutengda@huaweicloud.com \
--cc=yonghong.song@linux.dev \
--cc=zli94@ncsu.edu \
/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