From: Ian Rogers <irogers@google.com>
To: irogers@google.com, acme@kernel.org, adrian.hunter@intel.com,
mingo@redhat.com, namhyung@kernel.org, peterz@infradead.org
Cc: ak@linux.intel.com, alexander.shishkin@linux.intel.com,
atrajeev@linux.ibm.com, dvyukov@google.com, fzczx123@gmail.com,
james.clark@linaro.org, jolsa@kernel.org, kjain@linux.ibm.com,
krzysztof.m.lopatowski@gmail.com, leo.yan@arm.com,
lihuafei1@huawei.com, linux-kernel@vger.kernel.org,
linux-perf-users@vger.kernel.org, linux@treblig.org,
m.liska@foxlink.cz, mark.rutland@arm.com, martin.liska@hey.com,
mpetlan@redhat.com, quic_zhonhan@quicinc.com,
scclevenger@os.amperecomputing.com, sesse@google.com,
stephen.s.brennan@oracle.com, thomas.falcon@intel.com,
yangyicong@hisilicon.com
Subject: [PATCH v2 3/8] perf/core: Implement BUILD_ID_OFFSET sample type
Date: Fri, 2 Oct 2026 10:38:36 -0700 [thread overview]
Message-ID: <20261002173848.3228217-4-irogers@google.com> (raw)
In-Reply-To: <20261002173848.3228217-1-irogers@google.com>
Implement PERF_SAMPLE_BUILD_ID_OFFSET and
PERF_SAMPLE_CALLCHAIN_BUILD_ID_OFFSET payload writing in the perf event
core by reusing BPF's stack_map_get_build_id_offset().
When attr.defer_callchain is set, user-space IPs and callchains request
a deferred unwind via unwind_deferred_request() and emit a
PERF_CONTEXT_USER_DEFERRED marker and cookie in the sample. In the
faultable task_work callback (perf_unwind_deferred_callback), the
unwound user IPs are resolved to build IDs and file offsets using
stack_map_get_build_id_offset(..., may_fault=true) and emitted in
PERF_RECORD_CALLCHAIN_DEFERRED with PERF_RECORD_MISC_MMAP_BUILD_ID set.
When attr.defer_callchain is not set (or if deferred unwinding is
unavailable), user-space IPs and callchains are resolved in-place during
perf_output_sample() using stack_map_get_build_id_offset(...,
may_fault=false). If the mmap_lock cannot be trylocked or the ELF
header/note pages are not present in the page cache (nor mlocked into
memory), resolution falls back to emitting a zero-sized build ID
(size = 0) with the virtual address as the offset. Using the deferred
approach (attr.defer_callchain and attr.defer_output) is therefore
preferred as it can fault in pages and wait on locks, resolving more
build IDs without requiring ELF header pages to be mlocked in the page
cache.
Kernel-space IPs and callchain entries are emitted with a zero-sized
build ID (size = 0) and the virtual address as the offset.
Signed-off-by: Ian Rogers <irogers@google.com>
---
include/linux/bpf.h | 14 ++
include/linux/perf_event.h | 1 +
kernel/bpf/stackmap.c | 4 +-
kernel/events/core.c | 298 +++++++++++++++++++++++++++++++++++--
4 files changed, 304 insertions(+), 13 deletions(-)
diff --git a/include/linux/bpf.h b/include/linux/bpf.h
index e57af902560c..750133762436 100644
--- a/include/linux/bpf.h
+++ b/include/linux/bpf.h
@@ -4217,4 +4217,18 @@ static inline int bpf_map_check_op_flags(struct bpf_map *map, u64 flags, u64 all
return 0;
}
+#if defined(CONFIG_BPF_SYSCALL) && defined(CONFIG_PERF_EVENTS)
+void stack_map_get_build_id_offset(struct bpf_stack_build_id *id_offs,
+ u32 trace_nr, bool user, bool may_fault);
+#else
+static inline void stack_map_get_build_id_offset(struct bpf_stack_build_id *id_offs,
+ u32 trace_nr, bool user, bool may_fault)
+{
+ for (u32 i = 0; i < trace_nr; i++) {
+ id_offs[i].status = BPF_STACK_BUILD_ID_IP;
+ memset(id_offs[i].build_id, 0, BPF_BUILD_ID_SIZE);
+ }
+}
+#endif
+
#endif /* _LINUX_BPF_H */
diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h
index 5842552294c1..3868923f6a79 100644
--- a/include/linux/perf_event.h
+++ b/include/linux/perf_event.h
@@ -1347,6 +1347,7 @@ struct perf_sample_data {
u64 data_page_size;
u64 code_page_size;
u64 aux_size;
+ u64 callchain_bid_nr;
} ____cacheline_aligned;
/* default value for data source */
diff --git a/kernel/bpf/stackmap.c b/kernel/bpf/stackmap.c
index d09d4c3fe547..4e06c1697786 100644
--- a/kernel/bpf/stackmap.c
+++ b/kernel/bpf/stackmap.c
@@ -411,8 +411,8 @@ static void stack_map_get_build_id_offset_sleepable(struct bpf_stack_build_id *i
* id_offs[i].build_id is zeroed out and id_offs[i].status is set to
* BPF_STACK_BUILD_ID_IP.
*/
-static void stack_map_get_build_id_offset(struct bpf_stack_build_id *id_offs,
- u32 trace_nr, bool user, bool may_fault)
+void stack_map_get_build_id_offset(struct bpf_stack_build_id *id_offs,
+ u32 trace_nr, bool user, bool may_fault)
{
struct mmap_unlock_irq_work *work;
bool has_user_ctx = user && current && current->mm;
diff --git a/kernel/events/core.c b/kernel/events/core.c
index 33210aff3ee6..7f6bf96f7473 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -460,6 +460,8 @@ static atomic_t nr_bpf_events __read_mostly;
static atomic_t nr_cgroup_events __read_mostly;
static atomic_t nr_text_poke_events __read_mostly;
static atomic_t nr_build_id_events __read_mostly;
+static atomic_t nr_build_id_offset_events __read_mostly;
+static atomic_t nr_callchain_build_id_offset_events __read_mostly;
static LIST_HEAD(pmus);
static DEFINE_MUTEX(pmus_lock);
@@ -2048,6 +2050,14 @@ static int __perf_event_read_size(u64 read_format, int nr_siblings)
return size + nr * entry;
}
+struct perf_sample_build_id_offset {
+ u8 size;
+ u8 res1;
+ u16 res2;
+ u8 build_id[BUILD_ID_SIZE_MAX];
+ u64 offset;
+};
+
static void __perf_event_header_size(struct perf_event *event, u64 sample_type)
{
struct perf_sample_data *data;
@@ -2086,6 +2096,9 @@ static void __perf_event_header_size(struct perf_event *event, u64 sample_type)
if (sample_type & PERF_SAMPLE_CODE_PAGE_SIZE)
size += sizeof(data->code_page_size);
+ if (sample_type & PERF_SAMPLE_BUILD_ID_OFFSET)
+ size += sizeof(struct perf_sample_build_id_offset);
+
event->header_size = size;
}
@@ -5341,7 +5354,7 @@ static bool is_sb_event(struct perf_event *event)
attr->comm || attr->comm_exec ||
attr->task || attr->ksymbol ||
attr->context_switch || attr->text_poke ||
- attr->bpf_event)
+ attr->bpf_event || attr->defer_output)
return true;
return false;
@@ -5619,6 +5632,10 @@ static void unaccount_event(struct perf_event *event)
atomic_dec(&nr_mmap_events);
if (event->attr.build_id)
atomic_dec(&nr_build_id_events);
+ if (event->attr.sample_type & PERF_SAMPLE_BUILD_ID_OFFSET)
+ atomic_dec(&nr_build_id_offset_events);
+ if (event->attr.sample_type & PERF_SAMPLE_CALLCHAIN_BUILD_ID_OFFSET)
+ atomic_dec(&nr_callchain_build_id_offset_events);
if (event->attr.comm)
atomic_dec(&nr_comm_events);
if (event->attr.namespaces)
@@ -8276,6 +8293,155 @@ static void perf_output_read(struct perf_output_handle *handle,
perf_output_read_one(handle, event, enabled, running);
}
+static struct unwind_work perf_unwind_work;
+
+struct perf_bpf_build_id_buf {
+ local_t active;
+ struct bpf_stack_build_id bids[PERF_MAX_STACK_DEPTH + 1];
+};
+
+static DEFINE_PER_CPU(struct perf_bpf_build_id_buf, perf_bpf_build_id_buf);
+
+static void perf_bpf_to_sample_bid_offset(struct bpf_stack_build_id *bpf_bid)
+{
+ struct perf_sample_build_id_offset *bid = (void *)bpf_bid;
+ u8 size = 0;
+
+ static_assert(sizeof(*bid) == sizeof(*bpf_bid));
+ static_assert(offsetof(struct perf_sample_build_id_offset, build_id) ==
+ offsetof(struct bpf_stack_build_id, build_id));
+ static_assert(offsetof(struct perf_sample_build_id_offset, offset) ==
+ offsetof(struct bpf_stack_build_id, offset));
+
+ if (bpf_bid->status == BPF_STACK_BUILD_ID_VALID)
+ size = BUILD_ID_SIZE_MAX;
+ else
+ memset(bid->build_id, 0, sizeof(bid->build_id));
+
+ bid->size = size;
+ bid->res1 = 0;
+ bid->res2 = 0;
+}
+
+static void perf_output_sample_build_id(struct perf_output_handle *handle,
+ struct perf_event_header *header,
+ struct perf_sample_data *data,
+ struct perf_event *event)
+{
+ u64 sample_type = data->type;
+ bool sample_bid = sample_type & PERF_SAMPLE_BUILD_ID_OFFSET;
+ bool callchain_bid = sample_type & PERF_SAMPLE_CALLCHAIN_BUILD_ID_OFFSET;
+ bool crosstask = event->ctx->task && event->ctx->task != current;
+ bool has_user_ctx = is_user_task(current) && current->mm && !crosstask;
+ bool is_user = (header->misc & PERF_RECORD_MISC_CPUMODE_MASK) ==
+ PERF_RECORD_MISC_USER;
+ u64 defer_cookie = 0;
+ u64 callchain_nr = callchain_bid ? data->callchain_bid_nr : 0;
+ u64 user_start = callchain_nr;
+ u32 resolve_ip_nr = 0, resolve_cc_nr = 0, total_resolve_nr;
+ struct perf_bpf_build_id_buf *buf = NULL;
+
+ if (sample_bid) {
+ bool defer_user = IS_ENABLED(CONFIG_UNWIND_USER) &&
+ is_user && has_user_ctx &&
+ event->attr.defer_callchain &&
+ !(sample_type & PERF_SAMPLE_CALLCHAIN);
+
+ if (defer_user &&
+ unwind_deferred_request(&perf_unwind_work, &defer_cookie) < 0)
+ defer_cookie = 0;
+
+ if (!defer_cookie && is_user && has_user_ctx)
+ resolve_ip_nr = 1;
+ }
+
+ if (callchain_bid && has_user_ctx) {
+ for (u64 i = 0; i < callchain_nr; i++) {
+ if (data->callchain->ip[i] == PERF_CONTEXT_USER) {
+ user_start = i + 1;
+ break;
+ }
+ }
+ if (user_start < callchain_nr) {
+ resolve_cc_nr = min_t(u64, callchain_nr - user_start,
+ PERF_MAX_STACK_DEPTH);
+ }
+ }
+
+ total_resolve_nr = resolve_ip_nr + resolve_cc_nr;
+ if (total_resolve_nr) {
+ buf = get_cpu_ptr(&perf_bpf_build_id_buf);
+ if (local_cmpxchg(&buf->active, 0, 1) == 0) {
+ if (resolve_ip_nr)
+ buf->bids[0].ip = data->ip;
+ for (u32 i = 0; i < resolve_cc_nr; i++) {
+ buf->bids[resolve_ip_nr + i].ip =
+ data->callchain->ip[user_start + i];
+ }
+ stack_map_get_build_id_offset(buf->bids,
+ total_resolve_nr,
+ true, false);
+ for (u32 i = 0; i < total_resolve_nr; i++)
+ perf_bpf_to_sample_bid_offset(&buf->bids[i]);
+ } else {
+ put_cpu_ptr(&perf_bpf_build_id_buf);
+ buf = NULL;
+ }
+ }
+
+ if (sample_bid) {
+ if (defer_cookie) {
+ u64 deferred_bid[4] = {
+ 0,
+ PERF_CONTEXT_USER_DEFERRED,
+ defer_cookie,
+ data->ip,
+ };
+
+ perf_output_put(handle, deferred_bid);
+ } else if (buf && resolve_ip_nr) {
+ perf_output_copy(handle, &buf->bids[0],
+ sizeof(buf->bids[0]));
+ } else {
+ struct perf_sample_build_id_offset bid_offset = {
+ .offset = data->ip,
+ };
+
+ perf_output_put(handle, bid_offset);
+ }
+ }
+
+ if (callchain_bid) {
+ u64 unres_prefix = buf ? user_start : callchain_nr;
+ u64 resolved_end = unres_prefix + (buf ? resolve_cc_nr : 0);
+
+ perf_output_put(handle, callchain_nr);
+ for (u64 i = 0; i < unres_prefix; i++) {
+ struct perf_sample_build_id_offset bid_offset = {
+ .offset = data->callchain->ip[i],
+ };
+
+ perf_output_put(handle, bid_offset);
+ }
+ if (buf && resolve_cc_nr) {
+ perf_output_copy(handle, &buf->bids[resolve_ip_nr],
+ resolve_cc_nr * sizeof(buf->bids[0]));
+ }
+ for (u64 i = resolved_end; i < callchain_nr; i++) {
+ struct perf_sample_build_id_offset bid_offset = {
+ .offset = data->callchain->ip[i],
+ };
+
+ perf_output_put(handle, bid_offset);
+ }
+ }
+
+ if (buf) {
+ local_set(&buf->active, 0);
+ put_cpu_ptr(&perf_bpf_build_id_buf);
+ }
+}
+
void perf_output_sample(struct perf_output_handle *handle,
struct perf_event_header *header,
struct perf_sample_data *data,
@@ -8455,6 +8621,10 @@ void perf_output_sample(struct perf_output_handle *handle,
perf_aux_sample_output(event, handle, data);
}
+ if (sample_type &
+ (PERF_SAMPLE_BUILD_ID_OFFSET | PERF_SAMPLE_CALLCHAIN_BUILD_ID_OFFSET))
+ perf_output_sample_build_id(handle, header, data, event);
+
if (!event->attr.watermark) {
int wakeup_events = event->attr.wakeup_events;
@@ -8598,8 +8768,6 @@ static u64 perf_get_page_size(unsigned long addr)
static struct perf_callchain_entry __empty_callchain = { .nr = 0, };
-static struct unwind_work perf_unwind_work;
-
struct perf_callchain_entry *
perf_callchain(struct perf_event *event, struct pt_regs *regs)
{
@@ -8663,7 +8831,7 @@ void perf_prepare_sample(struct perf_sample_data *data,
__perf_event_header__init_id(data, event, filtered_sample_type);
- if (filtered_sample_type & PERF_SAMPLE_IP) {
+ if (filtered_sample_type & (PERF_SAMPLE_IP | PERF_SAMPLE_BUILD_ID_OFFSET)) {
data->ip = perf_instruction_pointer(event, regs);
data->sample_flags |= PERF_SAMPLE_IP;
}
@@ -8671,6 +8839,14 @@ void perf_prepare_sample(struct perf_sample_data *data,
if (filtered_sample_type & PERF_SAMPLE_CALLCHAIN)
perf_sample_save_callchain(data, event, regs);
+ if (filtered_sample_type & PERF_SAMPLE_CALLCHAIN_BUILD_ID_OFFSET) {
+ if (!(data->sample_flags & PERF_SAMPLE_CALLCHAIN))
+ data->callchain = perf_callchain(event, regs);
+
+ data->dyn_size += sizeof(u64);
+ }
+
+
if (filtered_sample_type & PERF_SAMPLE_RAW) {
data->raw = NULL;
data->dyn_size += sizeof(u64);
@@ -8820,6 +8996,20 @@ void perf_prepare_sample(struct perf_sample_data *data,
data->dyn_size += size + sizeof(u64); /* size above */
data->sample_flags |= PERF_SAMPLE_AUX;
}
+
+ if (filtered_sample_type & PERF_SAMPLE_CALLCHAIN_BUILD_ID_OFFSET) {
+ u32 header_size = perf_sample_data_size(data, event);
+ u64 max_nr = 0, nr;
+
+ if (header_size < U16_MAX) {
+ max_nr = (U16_MAX - header_size) /
+ sizeof(struct perf_sample_build_id_offset);
+ }
+ nr = min_t(u64, data->callchain->nr, max_nr);
+ data->callchain_bid_nr = nr;
+ data->dyn_size += nr * sizeof(struct perf_sample_build_id_offset);
+ data->sample_flags |= PERF_SAMPLE_CALLCHAIN_BUILD_ID_OFFSET;
+ }
}
void perf_prepare_header(struct perf_event_header *header,
@@ -10414,6 +10604,8 @@ void perf_event_bpf_event(struct bpf_prog *prog,
struct perf_callchain_deferred_event {
struct unwind_stacktrace *trace;
+ struct perf_sample_build_id_offset *bids;
+ u16 nr_bids;
struct {
struct perf_event_header header;
u64 cookie;
@@ -10422,17 +10614,83 @@ struct perf_callchain_deferred_event {
} event;
};
+static struct perf_sample_build_id_offset *
+perf_resolve_build_id_offsets(struct unwind_stacktrace *trace, u16 *nr_bids_out)
+{
+ struct perf_sample_build_id_offset *bids;
+ struct bpf_stack_build_id *bpf_bids;
+ u16 nr = trace->nr;
+
+ *nr_bids_out = 0;
+ if (!nr || !current->mm)
+ return NULL;
+
+ if (!atomic_read(&nr_callchain_build_id_offset_events)) {
+ if (!atomic_read(&nr_build_id_offset_events))
+ return NULL;
+ nr = 1;
+ }
+
+ bids = kcalloc(nr, sizeof(*bids), GFP_KERNEL);
+ if (!bids)
+ return NULL;
+
+ bpf_bids = (struct bpf_stack_build_id *)bids;
+ for (u16 i = 0; i < nr; i++)
+ bpf_bids[i].ip = trace->entries[i];
+
+ stack_map_get_build_id_offset(bpf_bids, nr, true, true);
+
+ for (u16 i = 0; i < nr; i++)
+ perf_bpf_to_sample_bid_offset(&bpf_bids[i]);
+
+ *nr_bids_out = nr;
+ return bids;
+}
+
static void perf_callchain_deferred_output(struct perf_event *event, void *data)
{
struct perf_callchain_deferred_event *deferred_event = data;
struct perf_output_handle handle;
struct perf_sample_data sample;
- int ret, size = deferred_event->event.header.size;
+ u64 nr = deferred_event->trace->nr;
+ size_t elem_size;
+ bool use_bid;
+ u16 header_size, orig_misc, id_size;
+ int ret;
if (!event->attr.defer_output)
return;
+ if (event->attr.sample_type & PERF_SAMPLE_CALLCHAIN_BUILD_ID_OFFSET) {
+ use_bid = deferred_event->bids != NULL;
+ if (use_bid)
+ nr = min_t(u64, nr, deferred_event->nr_bids);
+ } else if ((event->attr.sample_type & PERF_SAMPLE_BUILD_ID_OFFSET) &&
+ !(event->attr.sample_type & PERF_SAMPLE_CALLCHAIN)) {
+ nr = min_t(u64, nr, 1);
+ use_bid = deferred_event->bids != NULL;
+ if (use_bid)
+ nr = min_t(u64, nr, deferred_event->nr_bids);
+ } else {
+ use_bid = false;
+ }
+
+ elem_size = use_bid ? sizeof(struct perf_sample_build_id_offset) :
+ sizeof(u64);
+ id_size = event->attr.sample_id_all ? event->id_header_size : 0;
+ nr = min_t(u64, nr,
+ (U16_MAX - sizeof(deferred_event->event) - id_size) / elem_size);
+
+ orig_misc = deferred_event->event.header.misc;
+ if (use_bid)
+ deferred_event->event.header.misc |= PERF_RECORD_MISC_MMAP_BUILD_ID;
+ header_size = sizeof(deferred_event->event) + (nr * elem_size);
+ deferred_event->event.header.size = header_size;
+ deferred_event->event.nr = nr;
+
/* XXX do we really need sample_id_all for this ??? */
+ perf_sample_data_init(&sample, 0, 0);
perf_event_header__init_id(&deferred_event->event.header, &sample, event);
ret = perf_output_begin(&handle, &sample, event,
@@ -10441,22 +10699,33 @@ static void perf_callchain_deferred_output(struct perf_event *event, void *data)
goto out;
perf_output_put(&handle, deferred_event->event);
- for (int i = 0; i < deferred_event->trace->nr; i++) {
- u64 entry = deferred_event->trace->entries[i];
- perf_output_put(&handle, entry);
+ if (use_bid) {
+ for (u64 i = 0; i < nr; i++)
+ perf_output_put(&handle, deferred_event->bids[i]);
+ } else {
+ for (u64 i = 0; i < nr; i++) {
+ u64 entry = deferred_event->trace->entries[i];
+
+ perf_output_put(&handle, entry);
+ }
}
perf_event__output_id_sample(event, &handle, &sample);
perf_output_end(&handle);
out:
- deferred_event->event.header.size = size;
+ deferred_event->event.header.misc = orig_misc;
}
static void perf_unwind_deferred_callback(struct unwind_work *work,
struct unwind_stacktrace *trace, u64 cookie)
{
+ u16 nr_bids = 0;
+ struct perf_sample_build_id_offset *bids =
+ perf_resolve_build_id_offsets(trace, &nr_bids);
struct perf_callchain_deferred_event deferred_event = {
.trace = trace,
+ .bids = bids,
+ .nr_bids = nr_bids,
.event = {
.header = {
.type = PERF_RECORD_CALLCHAIN_DEFERRED,
@@ -10470,6 +10739,7 @@ static void perf_unwind_deferred_callback(struct unwind_work *work,
};
perf_iterate_sb(perf_callchain_deferred_output, &deferred_event, NULL);
+ kfree(bids);
}
struct perf_text_poke_event {
@@ -13314,6 +13584,10 @@ static void account_event(struct perf_event *event)
atomic_inc(&nr_mmap_events);
if (event->attr.build_id)
atomic_inc(&nr_build_id_events);
+ if (event->attr.sample_type & PERF_SAMPLE_BUILD_ID_OFFSET)
+ atomic_inc(&nr_build_id_offset_events);
+ if (event->attr.sample_type & PERF_SAMPLE_CALLCHAIN_BUILD_ID_OFFSET)
+ atomic_inc(&nr_callchain_build_id_offset_events);
if (event->attr.comm)
atomic_inc(&nr_comm_events);
if (event->attr.namespaces)
@@ -13582,7 +13856,8 @@ perf_event_alloc(struct perf_event_attr *attr, int cpu,
}
if (!event->parent) {
- if (event->attr.sample_type & PERF_SAMPLE_CALLCHAIN) {
+ if (event->attr.sample_type &
+ (PERF_SAMPLE_CALLCHAIN | PERF_SAMPLE_CALLCHAIN_BUILD_ID_OFFSET)) {
err = get_callchain_buffers(attr->sample_max_stack);
if (err)
return ERR_PTR(err);
@@ -13943,7 +14218,8 @@ SYSCALL_DEFINE5(perf_event_open,
return err;
if (!attr.exclude_kernel ||
- ((attr.sample_type & PERF_SAMPLE_CALLCHAIN) &&
+ ((attr.sample_type &
+ (PERF_SAMPLE_CALLCHAIN | PERF_SAMPLE_CALLCHAIN_BUILD_ID_OFFSET)) &&
!attr.exclude_callchain_kernel)) {
err = perf_allow_kernel();
if (err)
--
2.56.0.rc1.315.gc6ed9934b7-goog
next prev parent reply other threads:[~2026-10-02 17:39 UTC|newest]
Thread overview: 19+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-04-24 6:19 [PATCH v1 0/5] perf: Default use of build IDs and improvements Ian Rogers
2025-04-24 6:19 ` [PATCH v1 1/5] perf build-id: Reduce size of "size" variable Ian Rogers
2025-04-24 6:19 ` [PATCH v1 2/5] perf build-id: Truncate to avoid overflowing the build_id data Ian Rogers
2025-04-24 6:19 ` [PATCH v1 3/5] perf build-id: Change sprintf functions to snprintf Ian Rogers
2025-04-24 6:19 ` [PATCH v1 4/5] perf dso: Move build_id to dso_id Ian Rogers
2025-04-24 6:19 ` [PATCH v1 5/5] perf record: Make --buildid-mmap the default Ian Rogers
2025-04-24 7:20 ` Ian Rogers
2025-04-25 14:45 ` Arnaldo Carvalho de Melo
2025-04-25 14:59 ` Arnaldo Carvalho de Melo
2025-04-25 16:03 ` Ian Rogers
2026-10-02 17:38 ` [PATCH v2 0/8] perf/core, perf/tools: Add PERF_SAMPLE_BUILD_ID_OFFSET support Ian Rogers
2026-10-02 17:38 ` [PATCH v2 1/8] perf event: Factor build_id out into its own top-level struct Ian Rogers
2026-10-02 17:38 ` [PATCH v2 2/8] perf/core: Add BUILD_ID_OFFSET to UAPI Ian Rogers
2026-10-02 17:38 ` Ian Rogers [this message]
2026-10-02 17:38 ` [PATCH v2 4/8] perf: Refactor thread map and symbol APIs to take perf_sample Ian Rogers
2026-10-02 17:38 ` [PATCH v2 5/8] perf tools: Internal support for BUILD_ID_OFFSET Ian Rogers
2026-10-02 17:38 ` [PATCH v2 6/8] perf inject: Extend perf inject to support bid_offset conversion Ian Rogers
2026-10-02 17:38 ` [PATCH v2 7/8] perf record: Add --buildid-offset option Ian Rogers
2026-10-02 17:38 ` [PATCH v2 8/8] perf tests: Add build_id_offset test coverage 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=20261002173848.3228217-4-irogers@google.com \
--to=irogers@google.com \
--cc=acme@kernel.org \
--cc=adrian.hunter@intel.com \
--cc=ak@linux.intel.com \
--cc=alexander.shishkin@linux.intel.com \
--cc=atrajeev@linux.ibm.com \
--cc=dvyukov@google.com \
--cc=fzczx123@gmail.com \
--cc=james.clark@linaro.org \
--cc=jolsa@kernel.org \
--cc=kjain@linux.ibm.com \
--cc=krzysztof.m.lopatowski@gmail.com \
--cc=leo.yan@arm.com \
--cc=lihuafei1@huawei.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-perf-users@vger.kernel.org \
--cc=linux@treblig.org \
--cc=m.liska@foxlink.cz \
--cc=mark.rutland@arm.com \
--cc=martin.liska@hey.com \
--cc=mingo@redhat.com \
--cc=mpetlan@redhat.com \
--cc=namhyung@kernel.org \
--cc=peterz@infradead.org \
--cc=quic_zhonhan@quicinc.com \
--cc=scclevenger@os.amperecomputing.com \
--cc=sesse@google.com \
--cc=stephen.s.brennan@oracle.com \
--cc=thomas.falcon@intel.com \
--cc=yangyicong@hisilicon.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
all inboxes | Powered by JetHome®