From nobody Tue Sep 29 13:18:52 2026 Received: from mail-pg1-f200.google.com (mail-pg1-f200.google.com [209.85.215.200]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 6C7E03B38A4 for ; Fri, 7 Aug 2026 07:18:28 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.215.200 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786087110; cv=none; b=CNHrGl7id0T0UVDdgk2aJ0RMAEgOb9J3K1AfoO78predozAChdbo+6N25BkVvX6gqfVAoWiq4bXnEgTU584okg7jyQMe5BVDCa+4Vtfzl3EfHOzPrk7FIXf0CMzc+lvUpl8htvcOiYCm+GkdfjqRND4TnuifCbPOmV3EOQ3FN2c= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786087110; c=relaxed/simple; bh=3eeRY5Aa9pvngR2Af34iEV+b3xWsYHturOXlMa/4JjA=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Content-Type; b=nV5Pgeoi60DQX5BYa/EWYR2ZSdUde5gxHBG9hnWAbLT4NCYE/Vpb1NBgT2sKRyffHDWn2RWy8skzM6KSNquNwM8JmDyZHUcMduPd1QSDgvsF37JQD+ED7666znNHybEaoG0aK0mp+8/IZPsgmTBcvkCSHDBIguqK9m09LM5Oasc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--irogers.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=gGuSy8/2; arc=none smtp.client-ip=209.85.215.200 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--irogers.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="gGuSy8/2" Received: by mail-pg1-f200.google.com with SMTP id 41be03b00d2f7-cbe77d6864dso3502771a12.2 for ; Fri, 07 Aug 2026 00:18:28 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20251104; t=1786087108; x=1786691908; darn=vger.kernel.org; h=content-type:to:from:subject:message-id:references:mime-version :in-reply-to:date:from:to:cc:subject:date:message-id:reply-to :content-type; bh=mKhluK2oW7axNaXGt2f+mOTb9EIBwlM5B6rGh/lUQwU=; b=gGuSy8/2xrw/REvmTk/DlyPpWB8HjLYsyE8gpXWYGq89lJblmMZhjO3fK5XDGhhuTf 6PgddiGiz5UeEOBNHgXGl7aGp4yVc7gCEeR6P4A0sbxe06eB31CXT9lxdfRZCU66hV0A pLUhw3DfNgaYaNbCVAB7BaTjgdFgzfNo+Mc1CZme8wWfzuHbK+Jw4NKi5jz+SMB/I0aq GFf/uhQI5vtF/wF2f/a4Uo6oD48zQLaBf8nD5mcWscZc/5xL6nmLqLBjc10/3JJbwZLY JgNx3yfCagdrUVbQLgbrO3F9G7NpbPqFkXVCLAehlOkksgIvQShWj63tqz/jVUD2swyU CKCQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1786087108; x=1786691908; h=content-type:to:from:subject:message-id:references:mime-version :in-reply-to:date:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to:content-type; bh=mKhluK2oW7axNaXGt2f+mOTb9EIBwlM5B6rGh/lUQwU=; b=CVYX4ROjF4WihqEWlQiXCPcIYA2uzdAOx0S4w4J26QmBQzwGZwZjgNWQrJp4M30ueI Yqr1RY8T6tCz3l4D/8efgd7FY44HLXFVF9K6BmLx+UxFMDmbjOtgqH6GXZnyfw0nySbU c4pHZ17z6HaxRRQkm5P9C/c4jorQFRwzAr3OYEUXHQgL4zlmuI8wkskFQjY8fgEItYUH UtIfyhfRO9Qp5bUS3c6LHgkDMAeQRRLMC21zHBrOJINIR8W/eewNyJ0yJZAuTNWzjuAs PxXFngYds+Tx6XSNXRW1c668JoLLMwRlK7Gor5GDdK6IwpeHMgutnEzIvMaj+oKSHk2l gwqA== X-Forwarded-Encrypted: i=1; AHgh+Ro5jJbELnfPSrPP+jopDAeselQrwqh/Lu60Iau/+4ybS0+hV2Vipr09U1J1hH8PqvTMfLMscop/SVny72M=@vger.kernel.org X-Gm-Message-State: AOJu0YxKE5/rYPfwyvnOeYPKx77oZM4ZAsU7BPaZ5DLOcKyPYw2ESl4q WGUf8Cej1VZ4k4RYjjNpOePQJMR6I6m90W3EqMRkWgyPVYCwZ8yOR476e9YnBRYUX/oU9of5ebr hcV318g1Z9A== X-Received: from dlbsi7.prod.google.com ([2002:a05:7022:b887:b0:13d:d48:df85]) (user=irogers job=prod-delivery.src-stubby-dispatcher) by 2002:a05:6a20:cd95:b0:3c3:89ce:b5bc with SMTP id adf61e73a8af0-3cbc01c89d2mr2588400637.15.1786087107367; Fri, 07 Aug 2026 00:18:27 -0700 (PDT) Date: Fri, 7 Aug 2026 00:18:11 -0700 In-Reply-To: <20260807071818.718751-1-irogers@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20260807071818.718751-1-irogers@google.com> X-Mailer: git-send-email 2.55.0.679.g6767b8d81c-goog Message-ID: <20260807071818.718751-2-irogers@google.com> Subject: [RFC PATCH v1 1/8] perf event: Factor build_id out into its own top-level struct From: Ian Rogers To: Steven Rostedt , Masami Hiramatsu , Alexei Starovoitov , Daniel Borkmann , John Fastabend , Andrii Nakryiko , Eduard Zingerman , Kumar Kartikeya Dwivedi , Martin KaFai Lau , Song Liu , Yonghong Song , Jiri Olsa , Emil Tsalapatis , Peter Zijlstra , Ingo Molnar , Arnaldo Carvalho de Melo , Namhyung Kim , Mark Rutland , Alexander Shishkin , Ian Rogers , Adrian Hunter , James Clark , Suzuki K Poulose , Mike Leach , Leo Yan , John Garry , Will Deacon , Thomas Gleixner , Dapeng Mi , Ravi Bangoria , Swapnil Sapkal , Thomas Falcon , Thomas Richter , Dmitrii Dolgov <9erthalion6@gmail.com>, Eric Biggers , Zecheng Li , Gabriel Marin , Tengda Wu , Derek Foreman , Tanushree Shah , Ankur Arora , Aaron Tomlin , tanze , Rui Qi , Howard Chu , Chuck Lever , Shimin Guo , Alessio Podda , 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 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Future changes will use build_id in more contexts. For consistency make the struct its own type and update usage to be of this type. Signed-off-by: Ian Rogers --- tools/include/uapi/linux/perf_event.h | 19 +++++++++---- tools/lib/perf/include/perf/event.h | 18 +++++++----- tools/perf/builtin-inject.c | 3 +- tools/perf/util/event.c | 4 +-- tools/perf/util/machine.c | 3 +- tools/perf/util/python.c | 8 +++--- tools/perf/util/synthetic-events.c | 40 +++++++++++++++------------ 7 files changed, 57 insertions(+), 38 deletions(-) diff --git a/tools/include/uapi/linux/perf_event.h b/tools/include/uapi/lin= ux/perf_event.h index fd10aa8d697f..2479a38883d0 100644 --- a/tools/include/uapi/linux/perf_event.h +++ b/tools/include/uapi/linux/perf_event.h @@ -1058,6 +1058,18 @@ enum perf_event_type { */ PERF_RECORD_SAMPLE =3D 9, =20 + /* + * Build IDs may be present in a number of events. They have a + * consistent encoding of: + * + * struct build_id { + * u8 size; + * u8 __reserved_1; + * u16 __reserved_2; + * u8 data[20]; + * }; + */ + /* * The MMAP2 records are an augmented version of MMAP, they add * maj, min, ino numbers to be used to uniquely identify each mapping @@ -1076,12 +1088,7 @@ enum perf_event_type { * u64 ino; * u64 ino_generation; * }; - * struct { - * u8 build_id_size; - * u8 __reserved_1; - * u16 __reserved_2; - * u8 build_id[20]; - * }; + * struct build_id build_id; * }; * u32 prot, flags; * char filename[]; diff --git a/tools/lib/perf/include/perf/event.h b/tools/lib/perf/include/p= erf/event.h index fdced574c889..173eab43c148 100644 --- a/tools/lib/perf/include/perf/event.h +++ b/tools/lib/perf/include/perf/event.h @@ -26,6 +26,15 @@ struct perf_record_mmap { char filename[PATH_MAX]; }; =20 +#define PERF_BUILD_ID_SIZE 20 + +struct perf_build_id { + __u8 size; + __u8 __reserved_1; + __u16 __reserved_2; + __u8 data[PERF_BUILD_ID_SIZE]; +}; + struct perf_record_mmap2 { struct perf_event_header header; __u32 pid, tid; @@ -39,12 +48,7 @@ struct perf_record_mmap2 { __u64 ino; __u64 ino_generation; }; - struct { - __u8 build_id_size; - __u8 __reserved_1; - __u16 __reserved_2; - __u8 build_id[20]; - }; + struct perf_build_id build_id; }; __u32 prot; __u32 flags; @@ -321,7 +325,7 @@ struct perf_record_header_build_id { union { __u8 build_id[24]; struct { - __u8 data[20]; + __u8 data[PERF_BUILD_ID_SIZE]; __u8 size; __u8 reserved1__; __u16 reserved2__; diff --git a/tools/perf/builtin-inject.c b/tools/perf/builtin-inject.c index 70bbfad5653e..8559c0eab5f1 100644 --- a/tools/perf/builtin-inject.c +++ b/tools/perf/builtin-inject.c @@ -811,7 +811,8 @@ static int perf_event__repipe_mmap2(const struct perf_t= ool *tool, struct dso_id id =3D dso_id_empty; =20 if (event->header.misc & PERF_RECORD_MISC_MMAP_BUILD_ID) { - build_id__init(&id.build_id, event->mmap2.build_id, event->mmap2.build_i= d_size); + build_id__init(&id.build_id, event->mmap2.build_id.data, + event->mmap2.build_id.size); } else { id.maj =3D event->mmap2.maj; id.min =3D event->mmap2.min; diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c index ea75816d126a..c69ae57ce679 100644 --- a/tools/perf/util/event.c +++ b/tools/perf/util/event.c @@ -335,8 +335,8 @@ size_t perf_event__fprintf_mmap2(union perf_event *even= t, FILE *fp) char sbuild_id[SBUILD_ID_SIZE]; struct build_id bid; =20 - build_id__init(&bid, event->mmap2.build_id, - event->mmap2.build_id_size); + build_id__init(&bid, event->mmap2.build_id.data, + event->mmap2.build_id.size); build_id__snprintf(&bid, sbuild_id, sizeof(sbuild_id)); =20 return fprintf(fp, " %d/%d: [%#" PRI_lx64 "(%#" PRI_lx64 ") @ %#" PRI_lx= 64 diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c index f86b3b7df742..21d54ebc866b 100644 --- a/tools/perf/util/machine.c +++ b/tools/perf/util/machine.c @@ -1797,7 +1797,8 @@ int machine__process_mmap2_event(struct machine *mach= ine, perf_event__fprintf_mmap2(event, stdout); =20 if (event->header.misc & PERF_RECORD_MISC_MMAP_BUILD_ID) { - build_id__init(&dso_id.build_id, event->mmap2.build_id, event->mmap2.bui= ld_id_size); + build_id__init(&dso_id.build_id, event->mmap2.build_id.data, + event->mmap2.build_id.size); } else { dso_id.maj =3D event->mmap2.maj; dso_id.min =3D event->mmap2.min; diff --git a/tools/perf/util/python.c b/tools/perf/util/python.c index af85c0771c44..d35190052d97 100644 --- a/tools/perf/util/python.c +++ b/tools/perf/util/python.c @@ -233,12 +233,12 @@ static PyObject *pyrf_mmap2_event__get_build_id(PyObj= ect *self, void *closure __ if (!(pevent->event.header.misc & PERF_RECORD_MISC_MMAP_BUILD_ID)) Py_RETURN_NONE; =20 - int size =3D pevent->event.mmap2.build_id_size; + size_t size =3D pevent->event.mmap2.build_id.size; =20 - if (size > 20) - size =3D 20; + if (size > sizeof(pevent->event.mmap2.build_id.data)) + size =3D sizeof(pevent->event.mmap2.build_id.data); =20 - return PyBytes_FromStringAndSize((const char *)pevent->event.mmap2.build_= id, size); + return PyBytes_FromStringAndSize((const char *)pevent->event.mmap2.build_= id.data, size); } =20 static PyGetSetDef pyrf_mmap2_event__getset[] =3D { diff --git a/tools/perf/util/synthetic-events.c b/tools/perf/util/synthetic= -events.c index 75a32ae8ef62..f7dedfb6bab8 100644 --- a/tools/perf/util/synthetic-events.c +++ b/tools/perf/util/synthetic-events.c @@ -452,7 +452,7 @@ static void perf_record_mmap2__read_build_id(struct per= f_record_mmap2 *event, } =20 if (event->header.misc & PERF_RECORD_MISC_MMAP_BUILD_ID) { - build_id__init(&dso_id.build_id, event->build_id, event->build_id_size); + build_id__init(&dso_id.build_id, event->build_id.data, event->build_id.s= ize); } else { dso_id.maj =3D event->maj; dso_id.min =3D event->min; @@ -478,16 +478,20 @@ static void perf_record_mmap2__read_build_id(struct p= erf_record_mmap2 *event, nsinfo__put(nsi); =20 out: + event->build_id.__reserved_1 =3D 0; + event->build_id.__reserved_2 =3D 0; if (rc =3D=3D 0) { - memcpy(event->build_id, bid.data, sizeof(bid.data)); - event->build_id_size =3D (u8) bid.size; + memcpy(event->build_id.data, bid.data, sizeof(bid.data)); + event->build_id.size =3D (u8) bid.size; event->header.misc |=3D PERF_RECORD_MISC_MMAP_BUILD_ID; - event->__reserved_1 =3D 0; - event->__reserved_2 =3D 0; =20 if (dso && !dso__has_build_id(dso)) dso__set_build_id(dso, &bid); } else { + memset(&event->build_id, 0, sizeof(event->build_id)); + event->build_id.size =3D 0; + event->header.misc &=3D ~PERF_RECORD_MISC_MMAP_BUILD_ID; + if (event->filename[0] =3D=3D '/') { pr_debug2("Failed to read build ID for %s\n", event->filename); @@ -611,8 +615,10 @@ int perf_event__synthesize_mmap_events(const struct pe= rf_tool *tool, event->mmap2.prot =3D prot; event->mmap2.flags =3D flags; =20 - if (!symbol_conf.no_buildid_mmap2) - perf_record_mmap2__read_build_id(&event->mmap2, machine, false); + if (!symbol_conf.no_buildid_mmap2) { + perf_record_mmap2__read_build_id(&event->mmap2, machine, + /*is_kernel=3D*/false); + } =20 if (perf_tool__process_synth_event(tool, event, machine, process) !=3D 0= ) { rc =3D -1; @@ -807,12 +813,12 @@ static int perf_event__synthesize_modules_maps_cb(str= uct map *map, void *data) =20 /* Clear stale build ID and entire union from previous module iteration = */ event->mmap2.header.misc &=3D ~PERF_RECORD_MISC_MMAP_BUILD_ID; - memset(event->mmap2.build_id, 0, sizeof(event->mmap2.build_id)); - event->mmap2.build_id_size =3D 0; - event->mmap2.__reserved_1 =3D 0; - event->mmap2.__reserved_2 =3D 0; + memset(event->mmap2.build_id.data, 0, sizeof(event->mmap2.build_id.data)= ); + event->mmap2.build_id.size =3D 0; + event->mmap2.build_id.__reserved_1 =3D 0; + event->mmap2.build_id.__reserved_2 =3D 0; =20 - perf_record_mmap2__read_build_id(&event->mmap2, args->machine, false); + perf_record_mmap2__read_build_id(&event->mmap2, args->machine, /*is_kern= el=3D*/false); } else { const char *long_name =3D dso__long_name(dso); =20 @@ -1293,7 +1299,7 @@ static int __perf_event__synthesize_kernel_mmap(const= struct perf_tool *tool, event->mmap2.len =3D map__end(map) - event->mmap.start; event->mmap2.pid =3D machine->pid; =20 - perf_record_mmap2__read_build_id(&event->mmap2, machine, true); + perf_record_mmap2__read_build_id(&event->mmap2, machine, /*is_kernel=3D*= /true); } else { size =3D snprintf(event->mmap.filename, sizeof(event->mmap.filename), "%s%s", machine->mmap_name, kmap->ref_reloc_sym->name) + 1; @@ -2486,10 +2492,10 @@ int perf_event__synthesize_mmap2_build_id(const str= uct perf_tool *tool, ev.mmap2.len =3D len; ev.mmap2.pgoff =3D pgoff; =20 - ev.mmap2.build_id_size =3D bid->size; - if (ev.mmap2.build_id_size > sizeof(ev.mmap2.build_id)) - ev.mmap2.build_id_size =3D sizeof(ev.mmap2.build_id); - memcpy(ev.mmap2.build_id, bid->data, ev.mmap2.build_id_size); + ev.mmap2.build_id.size =3D bid->size; + if (ev.mmap2.build_id.size > sizeof(ev.mmap2.build_id.data)) + ev.build_id.size =3D sizeof(ev.mmap2.build_id.data); + memcpy(ev.mmap2.build_id.data, bid->data, ev.mmap2.build_id.size); =20 ev.mmap2.prot =3D prot; ev.mmap2.flags =3D flags; --=20 2.55.0.679.g6767b8d81c-goog From nobody Tue Sep 29 13:18:52 2026 Received: from mail-pj1-f72.google.com (mail-pj1-f72.google.com [209.85.216.72]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 2875D3B27E3 for ; Fri, 7 Aug 2026 07:18:29 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.216.72 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786087111; cv=none; b=b1yhRRhmNLRnFF75ikujGRAEAFkdripsEr1y6GmuVkWwoy0NLpG6jpWRLnQS6CxCrfb6nCmcZSlpNlg2UCJpbl6B8iFFlY376Desg7BqBZkoCEzAXODKlapyDRj7cx3wkGwAB2+hRSXxNMUqZRESA5f627NqBSRlPI7mdJBzgv0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786087111; c=relaxed/simple; bh=6iGRZQU5iqk18vK28n1WtlfO4rJ+lBelMHpOKQwJLXQ=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Content-Type; b=d1R19aBkZrGM8b4ixEyKrFRWYAV0ImxmTcbmj5WZyAk640EZ4yqEjuptjuHiOnIZgVzgZ6oOaLApxgxlx2a8FM8VyfrXYxIv9cxzREYVVlsv4h356xMEQ1sDiLxZMZr6fZr5CO82Ayl2KzAfF74+oK8czGpp1+opDcWNzSmhj3E= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--irogers.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=qwYmsc9U; arc=none smtp.client-ip=209.85.216.72 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--irogers.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="qwYmsc9U" Received: by mail-pj1-f72.google.com with SMTP id 98e67ed59e1d1-38ce7fabf76so4941570a91.2 for ; Fri, 07 Aug 2026 00:18:29 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20251104; t=1786087109; x=1786691909; darn=vger.kernel.org; h=content-type:to:from:subject:message-id:references:mime-version :in-reply-to:date:from:to:cc:subject:date:message-id:reply-to :content-type; bh=+/LzAIB86djFW/dc+XDdigV1b7wOoI55acdChTs0xt0=; b=qwYmsc9UmV9EIf+RxELrLKKTgYvimST1xCeb5eUSAJYMJDX+brOrIVcVLeLswx7fmh q+DNyRJevZPSFB2cD7Pk04OyBSGT5onmJ+x+ZhJEvca0ZdF33feAb1t/9Ij7/M/q7g8Y /UYU1mnXO5V2k8Be9pVMp21vIQL7uUIfERfDwFl5dYGl7L803PcBiIbAlapg9TCPNKDb gQWWQxTolNAslHc75Wi3iErTgTQyr0iu1A0b58B3KjdizP6oqCrTE23q3GSpfdjXTjbQ Z+/YrSkjlRPxm0b5x/E/88vzhP3o6yqjPht6M0uyPpRmI0PQkO9rLY8m3eCatBeIrZhE Uopw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1786087109; x=1786691909; h=content-type:to:from:subject:message-id:references:mime-version :in-reply-to:date:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to:content-type; bh=+/LzAIB86djFW/dc+XDdigV1b7wOoI55acdChTs0xt0=; b=gO7lvHRJDGTGllp5j+KsJyWAAc6UaesILeSJhlRbu51B+bbhqvS/iikxzrLlMPfhuC a7Sic9LIAJzz4wo49rhvWIX81XLuwoCgBztjBumG0fre6vyBI4w1uVRruScDuyy70uoq kTCpvPokJG9ILocdrBVv/7oJioOV5EqRmJtB0PB8HRlSN9+pEXOBtngFvXBOLm1Go/kd o40vgjBWqUMGgUP2j4smodklNXMNXoAOC8ZBX+SCedrw/XqreIAr+6WCpOjvJ4msKDaC 1TIBjKR+BHjPHPEeJconX/OcNZv3qHxD1uQy3vMtJyHfhjmch6GXUwoTv/jcjW4XbuXS Cavw== X-Forwarded-Encrypted: i=1; AHgh+Rr9+OWbbkL1sYMws/6JvQ72AOAvEWQeKydHHKqDvZ5cMvwNsb201zjbf1WbvGl+c1en539FSfjp1b1vKuo=@vger.kernel.org X-Gm-Message-State: AOJu0Yz7lf0mKl9jhYCrMCHZJOwe34iXLkpkNN25OU6r3pXlsQ3lvqoe rWopqESM1wQuvRUZ5H676kZhGQUZpuEB7frJSr0btOAJDUjwejQi/vB7sKDNDe3WlurNa0cqG5+ P0XPCcGlYbw== X-Received: from dlj3.prod.google.com ([2002:a05:7022:503:b0:13b:962e:3bc8]) (user=irogers job=prod-delivery.src-stubby-dispatcher) by 2002:a17:90b:578e:b0:383:5a16:bd70 with SMTP id 98e67ed59e1d1-3903c5ebc8cmr21858591a91.16.1786087109050; Fri, 07 Aug 2026 00:18:29 -0700 (PDT) Date: Fri, 7 Aug 2026 00:18:12 -0700 In-Reply-To: <20260807071818.718751-1-irogers@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20260807071818.718751-1-irogers@google.com> X-Mailer: git-send-email 2.55.0.679.g6767b8d81c-goog Message-ID: <20260807071818.718751-3-irogers@google.com> Subject: [RFC PATCH v1 2/8] perf/core: Add BUILD_ID_OFFSET to UAPI From: Ian Rogers To: Steven Rostedt , Masami Hiramatsu , Alexei Starovoitov , Daniel Borkmann , John Fastabend , Andrii Nakryiko , Eduard Zingerman , Kumar Kartikeya Dwivedi , Martin KaFai Lau , Song Liu , Yonghong Song , Jiri Olsa , Emil Tsalapatis , Peter Zijlstra , Ingo Molnar , Arnaldo Carvalho de Melo , Namhyung Kim , Mark Rutland , Alexander Shishkin , Ian Rogers , Adrian Hunter , James Clark , Suzuki K Poulose , Mike Leach , Leo Yan , John Garry , Will Deacon , Thomas Gleixner , Dapeng Mi , Ravi Bangoria , Swapnil Sapkal , Thomas Falcon , Thomas Richter , Dmitrii Dolgov <9erthalion6@gmail.com>, Eric Biggers , Zecheng Li , Gabriel Marin , Tengda Wu , Derek Foreman , Tanushree Shah , Ankur Arora , Aaron Tomlin , tanze , Rui Qi , Howard Chu , Chuck Lever , Shimin Guo , Alessio Podda , 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 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Introduce PERF_SAMPLE_BUILD_ID_OFFSET and PERF_SAMPLE_CALLCHAIN_BUILD_ID_OFFSET Signed-off-by: Ian Rogers --- include/uapi/linux/perf_event.h | 4 +++- tools/include/uapi/linux/perf_event.h | 11 ++++++++++- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/include/uapi/linux/perf_event.h b/include/uapi/linux/perf_even= t.h index fd10aa8d697f..f0712c1471d3 100644 --- a/include/uapi/linux/perf_event.h +++ b/include/uapi/linux/perf_event.h @@ -165,8 +165,10 @@ enum perf_event_sample_format { PERF_SAMPLE_DATA_PAGE_SIZE =3D 1U << 22, PERF_SAMPLE_CODE_PAGE_SIZE =3D 1U << 23, PERF_SAMPLE_WEIGHT_STRUCT =3D 1U << 24, + PERF_SAMPLE_BUILD_ID_OFFSET =3D 1U << 25, + PERF_SAMPLE_CALLCHAIN_BUILD_ID_OFFSET =3D 1U << 26, =20 - PERF_SAMPLE_MAX =3D 1U << 25, /* non-ABI */ + PERF_SAMPLE_MAX =3D 1U << 27, /* non-ABI */ }; =20 #define PERF_SAMPLE_WEIGHT_TYPE (PERF_SAMPLE_WEIGHT | PERF_SAMPLE_WEIGHT_S= TRUCT) diff --git a/tools/include/uapi/linux/perf_event.h b/tools/include/uapi/lin= ux/perf_event.h index 2479a38883d0..d5660e2d6b60 100644 --- a/tools/include/uapi/linux/perf_event.h +++ b/tools/include/uapi/linux/perf_event.h @@ -165,8 +165,10 @@ enum perf_event_sample_format { PERF_SAMPLE_DATA_PAGE_SIZE =3D 1U << 22, PERF_SAMPLE_CODE_PAGE_SIZE =3D 1U << 23, PERF_SAMPLE_WEIGHT_STRUCT =3D 1U << 24, + PERF_SAMPLE_BUILD_ID_OFFSET =3D 1U << 25, + PERF_SAMPLE_CALLCHAIN_BUILD_ID_OFFSET =3D 1U << 26, =20 - PERF_SAMPLE_MAX =3D 1U << 25, /* non-ABI */ + PERF_SAMPLE_MAX =3D 1U << 27, /* non-ABI */ }; =20 #define PERF_SAMPLE_WEIGHT_TYPE (PERF_SAMPLE_WEIGHT | PERF_SAMPLE_WEIGHT_S= TRUCT) @@ -1054,6 +1056,13 @@ enum perf_event_type { * { u64 code_page_size;} && PERF_SAMPLE_CODE_PAGE_SIZE * { u64 size; * char data[size]; } && PERF_SAMPLE_AUX + * { struct build_id bid; + * u64 offset; } && PERF_SAMPLE_BUILD_ID_OFFSET + * { u64 nr; + * struct { + * struct build_id bid; + * u64 offset; + * }[nr]; } && PERF_SAMPLE_CALLCHAIN_BUILD_ID_OFFSET * }; */ PERF_RECORD_SAMPLE =3D 9, --=20 2.55.0.679.g6767b8d81c-goog From nobody Tue Sep 29 13:18:52 2026 Received: from mail-pj1-f69.google.com (mail-pj1-f69.google.com [209.85.216.69]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id E089E3BA253 for ; Fri, 7 Aug 2026 07:18:31 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.216.69 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786087115; cv=none; b=la3KpJp6sSErPQafHMkYmntpEEOHNognehFW64CvpKfI9G6EE7yRkCoN0xtVvnzs5DEE+0ScGt3Em3A9zGqIM2GyS6Eq8W+AZrU3CTM+qruPQ6gZbpW0WBeAPEblSMV37ZFgcxNMRSSt6GTSUJsjneuh++Cxf97Fd9NdrLGqXbc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786087115; c=relaxed/simple; bh=cpzuJlngGAm43tFscMlXRZnMARJWPTr0CBcPuQjRuwk=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Content-Type; b=bVJOitxCeBqLPaCJ6CBZeetT31Af+XMeXxqDtRovnCaJSyHhKtNByFzh1O2E5MTNRLVB5Wur7wwtz3EDO5tMyKEY0r/Nule2Hsr9DkFBqeTrre53SLHS2flLlhYNISlSsX8vZ5wNhSS8nDBCvUDFKNMtNvZiS4xGDsFygu9hGvM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--irogers.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=tmz1Nh3U; arc=none smtp.client-ip=209.85.216.69 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--irogers.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="tmz1Nh3U" Received: by mail-pj1-f69.google.com with SMTP id 98e67ed59e1d1-381250979d5so3216131a91.0 for ; Fri, 07 Aug 2026 00:18:31 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20251104; t=1786087111; x=1786691911; darn=vger.kernel.org; h=content-type:to:from:subject:message-id:references:mime-version :in-reply-to:date:from:to:cc:subject:date:message-id:reply-to :content-type; bh=Bcl1RSiBLZ6miVSqvsuamblwEoHgWcooZQBMrgJQ6Do=; b=tmz1Nh3UxVxDDDGNhoshXuYXF3gKWvhFUBSf5Z0hK8J7224n2DQQNB8CN2LWP5nu9S WfcD45hBaOWS3wxFtyZr/zJVSBcicvWGbPZnN+kZfuQlg8uRaTDxXDXIkKwMOGiRvLMr SAwFnnqaYeEm3PSi3dCNleIQczulVaZsauFWymsE/9Qec4Vre5nrlFGkElH4F/q+QSj2 1zN3vDOy9Ip9OFnx0qsDkBjiG0+qWjJYLwin+7D1WrZfyF2e6XqS9YxnyRM6UYGJdejT nnchRa6BI6F7sytMV2+4pj+KWn7ybS82BZw6+P23upCBcdT8VYNu6PJe8vt/5q+L4Ajh Q5Dg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1786087111; x=1786691911; h=content-type:to:from:subject:message-id:references:mime-version :in-reply-to:date:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to:content-type; bh=Bcl1RSiBLZ6miVSqvsuamblwEoHgWcooZQBMrgJQ6Do=; b=lpwQPH20oIMKBHEZZ/OXcHOFzqNklzLykT8Pyiz6akDE7T7/qIKHfZdnqncNPVRzms iCPEBdbc8lo51EiuYYQ2euHFzfbIBpLmcRPhmPsNf/b1skFMp7AXjssj+XOGi/ZLQgc1 TdQtwq1CB8cnX2jM/xqa2C8tXFpvClG7ZdLvDIsPS5/3oaHg0fr4REH2puMpWDulDVRe cNkF40mMHb8+wGrbXszdq8X19fyj7tXtRXzoeCEq0geyUYnjPMrTrt1GmNbUbzDTlfCb 0zeDTFPqI9QHKhlxGnM9eXdd9wi1ZmlAhYdJmhgImxuqmkdl2rmbtYTZJZIOASkkiJcF Aw+Q== X-Forwarded-Encrypted: i=1; AHgh+RrHFmeaZ5wdU3teSds5AxxDC5louC7CyF06r4/7Cq7JdE3duRUKSKh4jVHqdVXaD2gThnTReCoBhl5NQgE=@vger.kernel.org X-Gm-Message-State: AOJu0YwKx8Jf2x9H0fDmvznAISflpl8bVhdLa7SF5DAbtONiDEG4Ndva m+9a3xms6tdL2zwMl6MW93V4LYYHzgbvdx7db38qRFlKF5KgkdmxgJBdQfNpot2j8W2gS8WvZV/ ZhlCsHaTk9Q== X-Received: from dled12-n2.prod.google.com ([2002:a05:701b:42cc:20b0:13b:9ad0:582f]) (user=irogers job=prod-delivery.src-stubby-dispatcher) by 2002:a17:90b:1e53:b0:381:1f51:1ff0 with SMTP id 98e67ed59e1d1-3903c54b3a1mr18644417a91.2.1786087110681; Fri, 07 Aug 2026 00:18:30 -0700 (PDT) Date: Fri, 7 Aug 2026 00:18:13 -0700 In-Reply-To: <20260807071818.718751-1-irogers@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20260807071818.718751-1-irogers@google.com> X-Mailer: git-send-email 2.55.0.679.g6767b8d81c-goog Message-ID: <20260807071818.718751-4-irogers@google.com> Subject: [RFC PATCH v1 3/8] perf/core: Implement BUILD_ID_OFFSET sample type From: Ian Rogers To: Steven Rostedt , Masami Hiramatsu , Alexei Starovoitov , Daniel Borkmann , John Fastabend , Andrii Nakryiko , Eduard Zingerman , Kumar Kartikeya Dwivedi , Martin KaFai Lau , Song Liu , Yonghong Song , Jiri Olsa , Emil Tsalapatis , Peter Zijlstra , Ingo Molnar , Arnaldo Carvalho de Melo , Namhyung Kim , Mark Rutland , Alexander Shishkin , Ian Rogers , Adrian Hunter , James Clark , Suzuki K Poulose , Mike Leach , Leo Yan , John Garry , Will Deacon , Thomas Gleixner , Dapeng Mi , Ravi Bangoria , Swapnil Sapkal , Thomas Falcon , Thomas Richter , Dmitrii Dolgov <9erthalion6@gmail.com>, Eric Biggers , Zecheng Li , Gabriel Marin , Tengda Wu , Derek Foreman , Tanushree Shah , Ankur Arora , Aaron Tomlin , tanze , Rui Qi , Howard Chu , Chuck Lever , Shimin Guo , Alessio Podda , 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 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Expose stack_map_get_build_id_offset for perf_events to use when generating these samples, and implement the payload writing in the perf event core. Signed-off-by: Ian Rogers --- include/linux/bpf.h | 13 +++++++ kernel/bpf/stackmap.c | 2 +- kernel/events/core.c | 85 ++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 98 insertions(+), 2 deletions(-) diff --git a/include/linux/bpf.h b/include/linux/bpf.h index 7719f6528445..fd76900a8e47 100644 --- a/include/linux/bpf.h +++ b/include/linux/bpf.h @@ -4209,4 +4209,17 @@ static inline int bpf_map_check_op_flags(struct bpf_= map *map, u64 flags, u64 all return 0; } =20 +struct bpf_stack_build_id; +#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) +{ + if (id_offs) + id_offs->status =3D 1; /* BPF_STACK_BUILD_ID_EMPTY */ +} +#endif + #endif /* _LINUX_BPF_H */ diff --git a/kernel/bpf/stackmap.c b/kernel/bpf/stackmap.c index 41fe87d7302f..889ceb7cf29b 100644 --- a/kernel/bpf/stackmap.c +++ b/kernel/bpf/stackmap.c @@ -411,7 +411,7 @@ static void stack_map_get_build_id_offset_sleepable(str= uct 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_of= fs, +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 =3D NULL; diff --git a/kernel/events/core.c b/kernel/events/core.c index ba5bd6a78fe7..97ac70441602 100644 --- a/kernel/events/core.c +++ b/kernel/events/core.c @@ -2048,6 +2048,15 @@ static int __perf_event_read_size(u64 read_format, i= nt nr_siblings) return size + nr * entry; } =20 + +struct perf_sample_build_id_offset { + u8 size; + u8 res1; + u16 res2; + u8 build_id[BPF_BUILD_ID_SIZE]; + u64 offset; +}; + static void __perf_event_header_size(struct perf_event *event, u64 sample_= type) { struct perf_sample_data *data; @@ -2086,6 +2095,11 @@ static void __perf_event_header_size(struct perf_eve= nt *event, u64 sample_type) if (sample_type & PERF_SAMPLE_CODE_PAGE_SIZE) size +=3D sizeof(data->code_page_size); =20 + if (sample_type & PERF_SAMPLE_BUILD_ID_OFFSET) + size +=3D sizeof(struct perf_sample_build_id_offset); + + + event->header_size =3D size; } =20 @@ -8287,6 +8301,62 @@ void perf_output_sample(struct perf_output_handle *h= andle, if (sample_type & PERF_SAMPLE_READ) perf_output_read(handle, event); =20 + if (sample_type & PERF_SAMPLE_BUILD_ID_OFFSET) { + struct bpf_stack_build_id bpf_bid =3D { .ip =3D data->ip }; + struct perf_sample_build_id_offset bid_offset =3D { 0 }; + + bool is_user =3D (header->misc & PERF_RECORD_MISC_CPUMODE_MASK) =3D=3D + PERF_RECORD_MISC_USER; + + stack_map_get_build_id_offset( + &bpf_bid, /*trace_nr=3D*/1, + is_user, /*may_fault=3D*/false); + if (bpf_bid.status =3D=3D BPF_STACK_BUILD_ID_VALID) { + bid_offset.size =3D BPF_BUILD_ID_SIZE; + memcpy(bid_offset.build_id, bpf_bid.build_id, + BPF_BUILD_ID_SIZE); + bid_offset.offset =3D bpf_bid.offset; + } else { + bid_offset.offset =3D bpf_bid.ip; + } + perf_output_put(handle, bid_offset); + } + + if (sample_type & PERF_SAMPLE_CALLCHAIN_BUILD_ID_OFFSET) { + u64 nr =3D data->callchain ? data->callchain->nr : 0; + struct perf_sample_build_id_offset bid_offset; + struct bpf_stack_build_id bpf_bid; + u64 i; + + perf_output_put(handle, nr); + + for (i =3D 0; i < nr; i++) { + memset(&bid_offset, /*c=3D*/0, sizeof(bid_offset)); + memset(&bpf_bid, /*c=3D*/0, sizeof(bpf_bid)); + bpf_bid.ip =3D data->callchain->ip[i]; + + if (data->callchain->ip[i] =3D=3D PERF_CONTEXT_USER) { + bpf_bid.status =3D BPF_STACK_BUILD_ID_EMPTY; + } else { + bool is_user =3D data->callchain->ip[i] < PERF_CONTEXT_MAX; + + stack_map_get_build_id_offset(&bpf_bid, /*trace_nr=3D*/1, + is_user, /*may_fault=3D*/false); + } + + if (bpf_bid.status =3D=3D BPF_STACK_BUILD_ID_VALID) { + bid_offset.size =3D BPF_BUILD_ID_SIZE; + memcpy(bid_offset.build_id, bpf_bid.build_id, + BPF_BUILD_ID_SIZE); + bid_offset.offset =3D bpf_bid.offset; + } else { + bid_offset.offset =3D bpf_bid.ip; + } + perf_output_put(handle, bid_offset); + } + } + + if (sample_type & PERF_SAMPLE_CALLCHAIN) { int size =3D 1; =20 @@ -8632,7 +8702,7 @@ void perf_prepare_sample(struct perf_sample_data *dat= a, =20 __perf_event_header__init_id(data, event, filtered_sample_type); =20 - if (filtered_sample_type & PERF_SAMPLE_IP) { + if (filtered_sample_type & (PERF_SAMPLE_IP | PERF_SAMPLE_BUILD_ID_OFFSET)= ) { data->ip =3D perf_instruction_pointer(event, regs); data->sample_flags |=3D PERF_SAMPLE_IP; } @@ -8640,6 +8710,19 @@ void perf_prepare_sample(struct perf_sample_data *da= ta, if (filtered_sample_type & PERF_SAMPLE_CALLCHAIN) perf_sample_save_callchain(data, event, regs); =20 + if (filtered_sample_type & PERF_SAMPLE_CALLCHAIN_BUILD_ID_OFFSET) { + int size =3D 1; + + if (!data->callchain) + data->callchain =3D perf_callchain(event, regs); + + size +=3D data->callchain->nr * + (sizeof(struct perf_sample_build_id_offset) / sizeof(u64)); + data->dyn_size +=3D size * sizeof(u64); + data->sample_flags |=3D PERF_SAMPLE_CALLCHAIN_BUILD_ID_OFFSET; + } + + if (filtered_sample_type & PERF_SAMPLE_RAW) { data->raw =3D NULL; data->dyn_size +=3D sizeof(u64); --=20 2.55.0.679.g6767b8d81c-goog From nobody Tue Sep 29 13:18:52 2026 Received: from mail-pl1-f199.google.com (mail-pl1-f199.google.com [209.85.214.199]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 435C93B42ED for ; Fri, 7 Aug 2026 07:18:34 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.214.199 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786087117; cv=none; b=SPJ5vY2UrXYr9WEEdAxPyPJVhFAyw8Fnouw7nTNHffxYJCq3fFjSyDCxIuAe7t84ouRYemdzLvVgKlHd9djtxqBFqtn5+82Qwb8wb3NKY0fo6D6qHHVmcD/QUBW09trbdhupLy9uYnAmFSddGvCE3/ZueqdVbADKy6VP66Ndpi0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786087117; c=relaxed/simple; bh=W2iZtBwbMeUW5cxW0un0JB1gS83mXqwqrdUOZ1j1Rjc=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Content-Type; b=WMiBawwd0aspXtba2zmacd5W9Jpjm1RX2hd8+ummkz2cbPVH9I3G91iORFQRbTWfgIfunL9g+CqZt48Xl6h7U80d55/SEnYCZyWtDmVsvV3rwTIOLEctwu2nqxc7LLmUe0GmSlsFw0K/ndnM2SoCaVSTho0R2EOH7SxohGLDXJw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--irogers.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=fIphrk5R; arc=none smtp.client-ip=209.85.214.199 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--irogers.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="fIphrk5R" Received: by mail-pl1-f199.google.com with SMTP id d9443c01a7336-2cacf17c7e0so41024055ad.0 for ; Fri, 07 Aug 2026 00:18:34 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20251104; t=1786087113; x=1786691913; darn=vger.kernel.org; h=content-type:to:from:subject:message-id:references:mime-version :in-reply-to:date:from:to:cc:subject:date:message-id:reply-to :content-type; bh=OtbJ0rSorxaytiiVxkbbUemcKwkjUmBSIKc/6USecP8=; b=fIphrk5RgUViBgzqTCh97A49v/chhZTMC9rJ49JPS7tV50A7Y6vJ4UdTVE1/mHZMiv bJ6xJYGipSBqNcA9UV696gGHxzptv0stXohzjMUU/Unr+VBg3kDkTJnpK3iw4y4Eoyc7 Bur5C5WEOVeqB7KETDthKdt7vpGpcXNUQLh9F2GerYvEIcEzQFx5U9q13ItkKwIT3aPG 07PVjTcGjEDFQZZG0U1lsSupvCIdudSvMEksuYTvDs4raLD+V9OOmhR3qt9lhp9rz5TD P3iSDr80CquqcqAq7ASK3IV9j9nx7XG69ZEpU+3QYB+06QxMN/i7e+vEn435g232R6en XZGA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1786087113; x=1786691913; h=content-type:to:from:subject:message-id:references:mime-version :in-reply-to:date:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to:content-type; bh=OtbJ0rSorxaytiiVxkbbUemcKwkjUmBSIKc/6USecP8=; b=ilQXbPd+HXYkulfhKMZQc856prr+Ahnc5FmAsnHPQ037suKU01rl5Iw5rtrf82HL6u zZdDu06tc0JnRarAQCfjIU7JnhLOAsN4dV3ru2UMjggd2McnnocC84S8ZfKiO1uNb+hb Sr0qnkP6P2RNQiSp5i/w0tJrwtsGAt2h9UcKuakPMmpe5yWWKwMTWsOaF2dIdb7Hinck g6Q8+A3QS8qtOV/M8HK+LYJ0WBZaudy5LMK2fROfOTCkunfUeearpNM1iAph5g3Fi1qe J27LlC52MQS8SSJBrLuNsoiCwhi6ig0zphTuToQp8s18gdrQctSLEG25k5VarE1cXm2u p9Yw== X-Forwarded-Encrypted: i=1; AHgh+Rr4ReKGq9pguqjpM2v+u1qX1rAOziJm8ihAGU9Jn6E7vq/OBPwI4Q0u5vhFTvY1zKLYiY7rneSWhVe/z40=@vger.kernel.org X-Gm-Message-State: AOJu0YwU/UMe7NHlyuTtY8sfLQkQwD36gfwUZwyA68NChYpeSaj/pnLY TaVTu3OTqExPn57gnM9kapgfajxb9En5qb6coYLxvq/ndAty2JrUvQn1O36sZpwzGZf95LefWhJ EsT/INGMndQ== X-Received: from dlcip6.prod.google.com ([2002:a05:7023:c086:b0:13e:5e3d:db8]) (user=irogers job=prod-delivery.src-stubby-dispatcher) by 2002:a05:6a20:7349:b0:3c6:3c5b:f2e1 with SMTP id adf61e73a8af0-3cbadcfcacfmr7705992637.32.1786087112933; Fri, 07 Aug 2026 00:18:32 -0700 (PDT) Date: Fri, 7 Aug 2026 00:18:14 -0700 In-Reply-To: <20260807071818.718751-1-irogers@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20260807071818.718751-1-irogers@google.com> X-Mailer: git-send-email 2.55.0.679.g6767b8d81c-goog Message-ID: <20260807071818.718751-5-irogers@google.com> Subject: [RFC PATCH v1 4/8] perf: Refactor thread map and symbol APIs to take perf_sample From: Ian Rogers To: Steven Rostedt , Masami Hiramatsu , Alexei Starovoitov , Daniel Borkmann , John Fastabend , Andrii Nakryiko , Eduard Zingerman , Kumar Kartikeya Dwivedi , Martin KaFai Lau , Song Liu , Yonghong Song , Jiri Olsa , Emil Tsalapatis , Peter Zijlstra , Ingo Molnar , Arnaldo Carvalho de Melo , Namhyung Kim , Mark Rutland , Alexander Shishkin , Ian Rogers , Adrian Hunter , James Clark , Suzuki K Poulose , Mike Leach , Leo Yan , John Garry , Will Deacon , Thomas Gleixner , Dapeng Mi , Ravi Bangoria , Swapnil Sapkal , Thomas Falcon , Thomas Richter , Dmitrii Dolgov <9erthalion6@gmail.com>, Eric Biggers , Zecheng Li , Gabriel Marin , Tengda Wu , Derek Foreman , Tanushree Shah , Ankur Arora , Aaron Tomlin , tanze , Rui Qi , Howard Chu , Chuck Lever , Shimin Guo , Alessio Podda , 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 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Refactor thread__find_map and thread__find_symbol family of APIs to take a struct perf_sample * instead of cpumode and addr. This prepares for looking up symbols using build ID and offset, which is contained in the sample payload instead of the address. Signed-off-by: Ian Rogers --- .../arch/powerpc/util/skip-callchain-idx.c | 4 +- tools/perf/builtin-inject.c | 6 +- tools/perf/builtin-script.c | 33 +++++++---- tools/perf/builtin-timechart.c | 4 +- tools/perf/builtin-trace.c | 12 +++- tools/perf/tests/code-reading.c | 4 +- tools/perf/tests/mmap-thread-lookup.c | 9 ++- tools/perf/util/annotate-data.c | 5 +- tools/perf/util/aslr.c | 16 +++-- tools/perf/util/build-id.c | 5 +- tools/perf/util/capstone.c | 4 +- tools/perf/util/cs-etm.c | 4 +- tools/perf/util/data-convert-json.c | 4 +- tools/perf/util/debug.c | 4 +- tools/perf/util/dlfilter.c | 8 ++- tools/perf/util/event.c | 59 +++++++++++-------- tools/perf/util/intel-pt.c | 12 +++- tools/perf/util/machine.c | 18 ++++-- tools/perf/util/python.c | 5 +- .../scripting-engines/trace-event-python.c | 20 ++++--- tools/perf/util/thread.c | 11 ++-- tools/perf/util/thread.h | 14 ++--- tools/perf/util/unwind-libdw.c | 7 ++- tools/perf/util/unwind-libunwind.c | 8 ++- 24 files changed, 188 insertions(+), 88 deletions(-) diff --git a/tools/perf/arch/powerpc/util/skip-callchain-idx.c b/tools/perf= /arch/powerpc/util/skip-callchain-idx.c index e57f10798fa6..7a15efa0a699 100644 --- a/tools/perf/arch/powerpc/util/skip-callchain-idx.c +++ b/tools/perf/arch/powerpc/util/skip-callchain-idx.c @@ -223,7 +223,9 @@ int arch_skip_callchain_idx(struct thread *thread, stru= ct ip_callchain *chain) addr_location__init(&al); ip =3D chain->ips[1]; =20 - thread__find_symbol(thread, PERF_RECORD_MISC_USER, ip, &al); + thread__find_symbol(thread, + &(struct perf_sample){.cpumode =3D PERF_RECORD_MISC_USER, .ip =3D i= p}, + &al); =20 if (al.map) dso =3D map__dso(al.map); diff --git a/tools/perf/builtin-inject.c b/tools/perf/builtin-inject.c index 8559c0eab5f1..6aa9e3eea438 100644 --- a/tools/perf/builtin-inject.c +++ b/tools/perf/builtin-inject.c @@ -1167,7 +1167,11 @@ static int perf_event__inject_buildid(const struct p= erf_tool *tool, union perf_e goto repipe; } =20 - if (thread__find_map(thread, sample->cpumode, sample->ip, &al)) { + if (thread__find_map(thread, + &(struct perf_sample){.cpumode =3D sample->cpumode, + .ip =3D sample->ip, + .bid =3D sample->bid}, + &al)) { mark_dso_hit(inject, tool, sample, machine, args.mmap_evsel, al.map, /*sample_in_dso=3D*/true); } diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c index f91d8b1fbd01..93cffafb1af7 100644 --- a/tools/perf/builtin-script.c +++ b/tools/perf/builtin-script.c @@ -1000,8 +1000,10 @@ static int perf_sample__fprintf_brstack(struct perf_= sample *sample, =20 addr_location__init(&alf); addr_location__init(&alt); - thread__find_map_fb(thread, sample->cpumode, from, &alf); - thread__find_map_fb(thread, sample->cpumode, to, &alt); + thread__find_map_fb(thread, + &(struct perf_sample){.cpumode =3D sample->cpumode, .ip =3D from}, = &alf); + thread__find_map_fb(thread, + &(struct perf_sample){.cpumode =3D sample->cpumode, .ip =3D to}, &a= lt); =20 printed +=3D map__fprintf_dsoname_dsoff(alf.map, PRINT_FIELD(DSOFF), al= f.addr, fp); printed +=3D fprintf(fp, "/0x%"PRIx64, to); @@ -1037,8 +1039,10 @@ static int perf_sample__fprintf_brstacksym(struct pe= rf_sample *sample, from =3D entries[i].from; to =3D entries[i].to; =20 - thread__find_symbol_fb(thread, sample->cpumode, from, &alf); - thread__find_symbol_fb(thread, sample->cpumode, to, &alt); + thread__find_symbol_fb(thread, + &(struct perf_sample){.cpumode =3D sample->cpumode, .ip =3D from= }, &alf); + thread__find_symbol_fb(thread, + &(struct perf_sample){.cpumode =3D sample->cpumode, .ip =3D to},= &alt); =20 printed +=3D symbol__fprintf_symname_offs(alf.sym, &alf, fp); if (PRINT_FIELD(DSO)) @@ -1075,11 +1079,15 @@ static int perf_sample__fprintf_brstackoff(struct p= erf_sample *sample, from =3D entries[i].from; to =3D entries[i].to; =20 - if (thread__find_map_fb(thread, sample->cpumode, from, &alf) && + if (thread__find_map_fb(thread, + &(struct perf_sample){.cpumode =3D sample->cpumode, + .ip =3D from}, &alf) && !dso__adjust_symbols(map__dso(alf.map))) from =3D map__dso_map_ip(alf.map, from); =20 - if (thread__find_map_fb(thread, sample->cpumode, to, &alt) && + if (thread__find_map_fb(thread, + &(struct perf_sample){.cpumode =3D sample->cpumode, + .ip =3D to}, &alt) && !dso__adjust_symbols(map__dso(alt.map))) to =3D map__dso_map_ip(alt.map, to); =20 @@ -1137,7 +1145,10 @@ static int grab_bb(u8 *buffer, u64 start, u64 end, } =20 addr_location__init(&al); - if (!thread__find_map(thread, *cpumode, start, &al) || (dso =3D map__dso(= al.map)) =3D=3D NULL) { + if (!thread__find_map(thread, + &(struct perf_sample){.cpumode =3D *cpumode, + .ip =3D start}, &al) || + (dso =3D map__dso(al.map)) =3D=3D NULL) { pr_debug("\tcannot resolve %" PRIx64 "-%" PRIx64 "\n", start, end); goto out; } @@ -1212,7 +1223,7 @@ static int print_srccode(struct thread *thread, u8 cp= umode, uint64_t addr) int ret =3D 0; =20 addr_location__init(&al); - thread__find_map(thread, cpumode, addr, &al); + thread__find_map(thread, &(struct perf_sample){.cpumode =3D cpumode, .ip = =3D addr}, &al); if (!al.map) goto out; ret =3D map__fprintf_srccode(al.map, al.addr, stdout, @@ -1267,7 +1278,9 @@ static int ip__fprintf_jump(uint64_t ip, struct branc= h_entry *en, struct addr_location al; =20 addr_location__init(&al); - thread__find_map(thread, x->cpumode, ip, &al); + thread__find_map(thread, + &(struct perf_sample){.cpumode =3D x->cpumode, + .ip =3D ip}, &al); printed +=3D map__fprintf_srcline(al.map, al.addr, " srcline: ", fp); printed +=3D fprintf(fp, "\t"); addr_location__exit(&al); @@ -1327,7 +1340,7 @@ static int ip__fprintf_sym(uint64_t addr, struct thre= ad *thread, int off, printed =3D 0, ret =3D 0; =20 addr_location__init(&al); - thread__find_map(thread, cpumode, addr, &al); + thread__find_map(thread, &(struct perf_sample){.cpumode =3D cpumode, .ip = =3D addr}, &al); =20 if ((*lastsym) && al.addr >=3D (*lastsym)->start && al.addr < (*lastsym)-= >end) goto out; diff --git a/tools/perf/builtin-timechart.c b/tools/perf/builtin-timechart.c index 3f9153d5ecfb..77b79188afe6 100644 --- a/tools/perf/builtin-timechart.c +++ b/tools/perf/builtin-timechart.c @@ -564,7 +564,9 @@ static char *cat_backtrace(struct perf_sample *sample, =20 addr_location__init(&tal); tal.filtered =3D 0; - if (thread__find_symbol(al.thread, cpumode, ip, &tal)) + if (thread__find_symbol(al.thread, + &(struct perf_sample){.cpumode =3D cpumode, + .ip =3D ip}, &tal)) fprintf(f, "..... %016" PRIx64 " %s\n", ip, tal.sym->name); else fprintf(f, "..... %016" PRIx64 "\n", ip); diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index c3c7f1f85c53..efe2ff239480 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -3565,7 +3565,9 @@ static int trace__pgfault(struct trace *trace, if (trace->summary_only) goto out; =20 - thread__find_symbol(thread, sample->cpumode, sample->ip, &al); + thread__find_symbol(thread, + &(struct perf_sample){.cpumode =3D sample->cpumode, + .ip =3D sample->ip}, &al); =20 trace__fprintf_entry_head(trace, thread, 0, true, sample->time, sample->cpu, trace->output); @@ -3578,10 +3580,14 @@ static int trace__pgfault(struct trace *trace, =20 fprintf(trace->output, "] =3D> "); =20 - thread__find_symbol(thread, sample->cpumode, sample->addr, &al); + thread__find_symbol(thread, + &(struct perf_sample){.cpumode =3D sample->cpumode, + .ip =3D sample->addr}, &al); =20 if (!al.map) { - thread__find_symbol(thread, sample->cpumode, sample->addr, &al); + thread__find_symbol(thread, + &(struct perf_sample){.cpumode =3D sample->cpumode, + .ip =3D sample->addr}, &al); =20 if (al.map) map_type =3D 'x'; diff --git a/tools/perf/tests/code-reading.c b/tools/perf/tests/code-readin= g.c index f0e8ea8754ef..ca118d0262ad 100644 --- a/tools/perf/tests/code-reading.c +++ b/tools/perf/tests/code-reading.c @@ -394,7 +394,9 @@ static int read_object_code(u64 addr, size_t len, u8 cp= umode, pr_debug("Reading object code for memory address: %#"PRIx64"\n", addr); =20 addr_location__init(&al); - if (!thread__find_map(thread, cpumode, addr, &al) || !map__dso(al.map)) { + if (!thread__find_map(thread, + &(struct perf_sample){.cpumode =3D cpumode, + .ip =3D addr}, &al) || !map__dso(al.map)) { if (cpumode =3D=3D PERF_RECORD_MISC_HYPERVISOR) { pr_debug("Hypervisor address can not be resolved - skipping\n"); goto out; diff --git a/tools/perf/tests/mmap-thread-lookup.c b/tools/perf/tests/mmap-= thread-lookup.c index 0c5619c6e6e9..dca8bbfe780a 100644 --- a/tools/perf/tests/mmap-thread-lookup.c +++ b/tools/perf/tests/mmap-thread-lookup.c @@ -195,8 +195,10 @@ static int mmap_events(synth_cb synth) =20 pr_debug("looking for map %p\n", td->map); =20 - thread__find_map(thread, PERF_RECORD_MISC_USER, - (unsigned long) (td->map + 1), &al); + thread__find_map(thread, &(struct perf_sample){ + .cpumode =3D PERF_RECORD_MISC_USER, + .ip =3D (unsigned long) (td->map + 1), + }, &al); =20 thread__put(thread); =20 @@ -208,7 +210,10 @@ static int mmap_events(synth_cb synth) } =20 pr_debug("map %p, addr %" PRIx64 "\n", al.map, map__start(al.map)); + addr_location__exit(&al); + if (err) + break; } =20 machine__delete(machine); diff --git a/tools/perf/util/annotate-data.c b/tools/perf/util/annotate-dat= a.c index 4e4c58764082..e3fc9c68ebe0 100644 --- a/tools/perf/util/annotate-data.c +++ b/tools/perf/util/annotate-data.c @@ -734,8 +734,9 @@ bool get_global_var_info(struct data_loc_info *dloc, u6= 4 addr, mem_addr =3D addr + map__reloc(dloc->ms->map); =20 addr_location__init(&al); - sym =3D thread__find_symbol_fb(dloc->thread, dloc->cpumode, - mem_addr, &al); + sym =3D thread__find_symbol_fb(dloc->thread, + &(struct perf_sample){.cpumode =3D dloc->cpumode, + .ip =3D mem_addr}, &al); if (sym) { *var_name =3D sym->name; /* Calculate type offset from the start of variable */ diff --git a/tools/perf/util/aslr.c b/tools/perf/util/aslr.c index 027695d96779..cb8e3ca437a1 100644 --- a/tools/perf/util/aslr.c +++ b/tools/perf/util/aslr.c @@ -154,7 +154,9 @@ static u64 aslr_tool__remap_address(struct aslr_tool *a= slr, return 0; /* No thread. */ =20 addr_location__init(&al); - if (!thread__find_map(aslr_thread, cpumode, addr, &al)) { + if (!thread__find_map(aslr_thread, + &(struct perf_sample){.cpumode =3D cpumode, .ip =3D addr}, + &al)) { /* * If lookup fails with specified cpumode, try fallback to the other spa= ce * to be robust against bad cpumode in samples. @@ -168,7 +170,9 @@ static u64 aslr_tool__remap_address(struct aslr_tool *a= slr, else if (cpumode =3D=3D PERF_RECORD_MISC_GUEST_USER) effective_cpumode =3D PERF_RECORD_MISC_GUEST_KERNEL; =20 - if (!thread__find_map(aslr_thread, effective_cpumode, addr, &al)) { + if (!thread__find_map(aslr_thread, + &(struct perf_sample){.cpumode =3D effective_cpumode, + .ip =3D addr}, &al)) { addr_location__exit(&al); return 0; /* No mmap. */ } @@ -285,7 +289,9 @@ static u64 aslr_tool__findnew_mapping(struct aslr_tool = *aslr, remap_key.pid =3D (cpumode =3D=3D PERF_RECORD_MISC_KERNEL || cpumode =3D=3D PERF_RECORD_MISC_GUEST_KERNEL) ? kernel_pid : thread__pid(aslr_thread); - if (thread__find_map(aslr_thread, cpumode, start, &al)) { + if (thread__find_map(aslr_thread, + &(struct perf_sample){.cpumode =3D cpumode, .ip =3D start}, + &al)) { struct dso *dso =3D map__dso(al.map); const char *dso_name =3D dso ? dso__long_name(dso) : NULL; =20 @@ -342,7 +348,9 @@ static u64 aslr_tool__findnew_mapping(struct aslr_tool = *aslr, remap_addr =3D top->remapped_max; =20 addr_location__init(&prev_al); - if (thread__find_map(aslr_thread, cpumode, start - 1, &prev_al)) { + if (thread__find_map(aslr_thread, + &(struct perf_sample){.cpumode =3D cpumode, + .ip =3D start - 1}, &prev_al)) { if (map__end(prev_al.map) =3D=3D start) is_contiguous =3D true; } diff --git a/tools/perf/util/build-id.c b/tools/perf/util/build-id.c index eb95ab90f974..39e69f2299ab 100644 --- a/tools/perf/util/build-id.c +++ b/tools/perf/util/build-id.c @@ -69,7 +69,10 @@ int build_id__mark_dso_hit(const struct perf_tool *tool = __maybe_unused, } =20 addr_location__init(&al); - if (thread__find_map(thread, sample->cpumode, sample->ip, &al)) + if (thread__find_map(thread, + &(struct perf_sample){.cpumode =3D sample->cpumode, + .ip =3D sample->ip, + .bid =3D sample->bid}, &al)) dso__set_hit(map__dso(al.map)); =20 addr_location__exit(&al); diff --git a/tools/perf/util/capstone.c b/tools/perf/util/capstone.c index 74213daf8786..dc31047149e3 100644 --- a/tools/perf/util/capstone.c +++ b/tools/perf/util/capstone.c @@ -241,7 +241,9 @@ static size_t print_insn_x86(struct thread *thread, u8 = cpumode, struct cs_insn * =20 addr_location__init(&al); if (op->type =3D=3D X86_OP_IMM && - thread__find_symbol(thread, cpumode, op->imm, &al)) { + thread__find_symbol(thread, + &(struct perf_sample){.cpumode =3D cpumode, + .ip =3D op->imm}, &al)) { printed +=3D fprintf(fp, "%s ", insn[0].mnemonic); printed +=3D symbol__fprintf_symname_offs(al.sym, &al, fp); if (print_opts & PRINT_INSN_IMM_HEX) diff --git a/tools/perf/util/cs-etm.c b/tools/perf/util/cs-etm.c index 114b3cd2da49..a0bfd9aa6dbe 100644 --- a/tools/perf/util/cs-etm.c +++ b/tools/perf/util/cs-etm.c @@ -1152,7 +1152,9 @@ static u32 __cs_etm__mem_access(struct cs_etm_queue *= etmq, =20 cpumode =3D cs_etm__cpu_mode(etmq, address, el); =20 - if (!thread__find_map(thread, cpumode, address, &al)) + if (!thread__find_map(thread, + &(struct perf_sample){.cpumode =3D cpumode, + .ip =3D address}, &al)) goto out; =20 dso =3D map__dso(al.map); diff --git a/tools/perf/util/data-convert-json.c b/tools/perf/util/data-con= vert-json.c index 40888b7c4467..8fa7bfdaadff 100644 --- a/tools/perf/util/data-convert-json.c +++ b/tools/perf/util/data-convert-json.c @@ -235,7 +235,9 @@ static int process_sample_event(const struct perf_tool = *tool, fputc(',', out); =20 addr_location__init(&tal); - ok =3D thread__find_symbol(al.thread, cpumode, ip, &tal); + ok =3D thread__find_symbol(al.thread, + &(struct perf_sample){.cpumode =3D cpumode, + .ip =3D ip}, &tal); output_sample_callchain_entry(tool, ip, ok ? &tal : NULL); addr_location__exit(&tal); } diff --git a/tools/perf/util/debug.c b/tools/perf/util/debug.c index 6b5ffe81f141..ea88c4942ccb 100644 --- a/tools/perf/util/debug.c +++ b/tools/perf/util/debug.c @@ -339,7 +339,9 @@ void __dump_stack(FILE *file, void **stackdump, size_t = stackdump_size) bool printed =3D false; =20 addr_location__init(&al); - if (thread && thread__find_map(thread, PERF_RECORD_MISC_USER, addr, &al)= ) { + if (thread && thread__find_map(thread, + &(struct perf_sample){.cpumode =3D PERF_RECORD_MISC_USER, + .ip =3D addr}, &al)) { al.sym =3D map__find_symbol(al.map, al.addr); if (al.sym) { fprintf(file, " #%zd %p in %s ", i, stackdump[i], al.sym->name); diff --git a/tools/perf/util/dlfilter.c b/tools/perf/util/dlfilter.c index e11e144af62b..8a33bfe50939 100644 --- a/tools/perf/util/dlfilter.c +++ b/tools/perf/util/dlfilter.c @@ -177,7 +177,9 @@ static __s32 dlfilter__resolve_address(void *ctx, __u64= address, struct perf_dlf return -1; =20 addr_location__init(&al); - thread__find_symbol_fb(thread, d->sample->cpumode, address, &al); + thread__find_symbol_fb(thread, + &(struct perf_sample){.cpumode =3D d->sample->cpumode, + .ip =3D address}, &al); =20 al_to_d_al(&al, &d_al); =20 @@ -314,7 +316,9 @@ static __s32 dlfilter__object_code(void *ctx, __u64 ip,= void *buf, __u32 len) =20 addr_location__init(&a); =20 - thread__find_map_fb(al->thread, d->sample->cpumode, ip, &a); + thread__find_map_fb(al->thread, + &(struct perf_sample){.cpumode =3D d->sample->cpumode, + .ip =3D ip}, &a); ret =3D a.map ? code_read(ip, a.map, d->machine, buf, len) : -1; =20 addr_location__exit(&a); diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c index c69ae57ce679..982fb9ed049f 100644 --- a/tools/perf/util/event.c +++ b/tools/perf/util/event.c @@ -691,7 +691,7 @@ int perf_event__process(const struct perf_tool *tool __= maybe_unused, return machine__process_event(machine, event, sample); } =20 -struct map *thread__find_map(struct thread *thread, u8 cpumode, u64 addr, +struct map *thread__find_map(struct thread *thread, struct perf_sample *sa= mple, struct addr_location *al) { struct maps *maps =3D thread__maps(thread); @@ -702,34 +702,39 @@ struct map *thread__find_map(struct thread *thread, u= 8 cpumode, u64 addr, thread__zput(al->thread); al->thread =3D thread__get(thread); =20 - al->addr =3D addr; - al->cpumode =3D cpumode; + if (sample->ip) { + al->addr =3D sample->ip; + } else { + pr_debug("Sample missing IP data\n"); + return NULL; + } + al->cpumode =3D sample->cpumode; al->filtered =3D 0; =20 if (machine =3D=3D NULL) return NULL; =20 - if (cpumode =3D=3D PERF_RECORD_MISC_KERNEL && perf_host) { + if (sample->cpumode =3D=3D PERF_RECORD_MISC_KERNEL && perf_host) { al->level =3D 'k'; maps =3D machine__kernel_maps(machine); load_map =3D !symbol_conf.lazy_load_kernel_maps; - } else if (cpumode =3D=3D PERF_RECORD_MISC_USER && perf_host) { + } else if (sample->cpumode =3D=3D PERF_RECORD_MISC_USER && perf_host) { al->level =3D '.'; - } else if (cpumode =3D=3D PERF_RECORD_MISC_GUEST_KERNEL && perf_guest) { + } else if (sample->cpumode =3D=3D PERF_RECORD_MISC_GUEST_KERNEL && perf_g= uest) { al->level =3D 'g'; maps =3D machine__kernel_maps(machine); load_map =3D !symbol_conf.lazy_load_kernel_maps; - } else if (cpumode =3D=3D PERF_RECORD_MISC_GUEST_USER && perf_guest) { + } else if (sample->cpumode =3D=3D PERF_RECORD_MISC_GUEST_USER && perf_gue= st) { al->level =3D 'u'; } else { al->level =3D 'H'; =20 - if ((cpumode =3D=3D PERF_RECORD_MISC_GUEST_USER || - cpumode =3D=3D PERF_RECORD_MISC_GUEST_KERNEL) && + if ((sample->cpumode =3D=3D PERF_RECORD_MISC_GUEST_USER || + sample->cpumode =3D=3D PERF_RECORD_MISC_GUEST_KERNEL) && !perf_guest) al->filtered |=3D (1 << HIST_FILTER__GUEST); - if ((cpumode =3D=3D PERF_RECORD_MISC_USER || - cpumode =3D=3D PERF_RECORD_MISC_KERNEL) && + if ((sample->cpumode =3D=3D PERF_RECORD_MISC_USER || + sample->cpumode =3D=3D PERF_RECORD_MISC_KERNEL) && !perf_host) al->filtered |=3D (1 << HIST_FILTER__HOST); =20 @@ -754,33 +759,34 @@ struct map *thread__find_map(struct thread *thread, u= 8 cpumode, u64 addr, * because it applies only to the sample 'ip' and not necessary to 'addr' = or * branch stack addresses. If possible, use a fallback to deal with those = cases. */ -struct map *thread__find_map_fb(struct thread *thread, u8 cpumode, u64 add= r, +struct map *thread__find_map_fb(struct thread *thread, struct perf_sample = *sample, struct addr_location *al) { - struct map *map =3D thread__find_map(thread, cpumode, addr, al); + struct map *map =3D thread__find_map(thread, sample, al); struct machine *machine =3D maps__machine(thread__maps(thread)); - u8 addr_cpumode =3D machine__addr_cpumode(machine, cpumode, addr); + u8 addr_cpumode =3D machine__addr_cpumode(machine, sample->cpumode, sampl= e->ip); =20 - if (map || addr_cpumode =3D=3D cpumode) + if (map || addr_cpumode =3D=3D sample->cpumode) return map; =20 - return thread__find_map(thread, addr_cpumode, addr, al); + sample->cpumode =3D addr_cpumode; + return thread__find_map(thread, sample, al); } =20 -struct symbol *thread__find_symbol(struct thread *thread, u8 cpumode, - u64 addr, struct addr_location *al) +struct symbol *thread__find_symbol(struct thread *thread, struct perf_samp= le *sample, + struct addr_location *al) { al->sym =3D NULL; - if (thread__find_map(thread, cpumode, addr, al)) + if (thread__find_map(thread, sample, al)) al->sym =3D map__find_symbol(al->map, al->addr); return al->sym; } =20 -struct symbol *thread__find_symbol_fb(struct thread *thread, u8 cpumode, - u64 addr, struct addr_location *al) +struct symbol *thread__find_symbol_fb(struct thread *thread, struct perf_s= ample *sample, + struct addr_location *al) { al->sym =3D NULL; - if (thread__find_map_fb(thread, cpumode, addr, al)) + if (thread__find_map_fb(thread, sample, al)) al->sym =3D map__find_symbol(al->map, al->addr); return al->sym; } @@ -816,7 +822,10 @@ int machine__resolve(struct machine *machine, struct a= ddr_location *al, return -1; =20 dump_printf(" ... thread: %s:%d\n", thread__comm_str(thread), thread__tid= (thread)); - thread__find_map(thread, sample->cpumode, sample->ip, al); + thread__find_map(thread, + &(struct perf_sample){.cpumode =3D sample->cpumode, + .ip =3D sample->ip, + .bid =3D sample->bid}, al); dso =3D al->map ? map__dso(al->map) : NULL; dump_printf(" ...... dso: %s\n", dso @@ -934,7 +943,9 @@ bool sample_addr_correlates_sym(struct perf_event_attr = *attr) void thread__resolve(struct thread *thread, struct addr_location *al, struct perf_sample *sample) { - thread__find_map_fb(thread, sample->cpumode, sample->addr, al); + thread__find_map_fb(thread, + &(struct perf_sample){.cpumode =3D sample->cpumode, + .ip =3D sample->addr}, al); =20 al->cpu =3D sample->cpu; al->sym =3D NULL; diff --git a/tools/perf/util/intel-pt.c b/tools/perf/util/intel-pt.c index 9d6628169fd9..228af524e9ce 100644 --- a/tools/perf/util/intel-pt.c +++ b/tools/perf/util/intel-pt.c @@ -812,7 +812,9 @@ static int intel_pt_walk_next_insn(struct intel_pt_insn= *intel_pt_insn, while (1) { struct dso *dso; =20 - if (!thread__find_map(thread, cpumode, *ip, &al) || !map__dso(al.map)) { + if (!thread__find_map(thread, + &(struct perf_sample){.cpumode =3D cpumode, + .ip =3D *ip}, &al) || !map__dso(al.map)) { if (al.map) intel_pt_log("ERROR: thread has no dso for %#" PRIx64 "\n", *ip); else @@ -1007,7 +1009,9 @@ static int __intel_pt_pgd_ip(uint64_t ip, void *data) return -EINVAL; =20 addr_location__init(&al); - if (!thread__find_map(thread, cpumode, ip, &al) || !map__dso(al.map)) + if (!thread__find_map(thread, + &(struct perf_sample){.cpumode =3D cpumode, + .ip =3D ip}, &al) || !map__dso(al.map)) return -EINVAL; =20 offset =3D map__map_ip(al.map, ip); @@ -3656,7 +3660,9 @@ static int intel_pt_find_map(struct thread *thread, u= 8 cpumode, u64 addr, struct addr_location *al) { if (!al->map || addr < map__start(al->map) || addr >=3D map__end(al->map)= ) { - if (!thread__find_map(thread, cpumode, addr, al)) + if (!thread__find_map(thread, + &(struct perf_sample){.cpumode =3D cpumode, + .ip =3D addr}, al)) return -1; } =20 diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c index 21d54ebc866b..aeace492b4e7 100644 --- a/tools/perf/util/machine.c +++ b/tools/perf/util/machine.c @@ -2072,7 +2072,9 @@ static void ip__resolve_ams(struct thread *thread, * Thus, we have to try consecutively until we find a match * or else, the symbol is unknown */ - thread__find_cpumode_addr_location(thread, ip, /*symbols=3D*/true, &al); + thread__find_cpumode_addr_location(thread, + &(struct perf_sample){.ip =3D ip}, + /*symbols=3D*/true, &al); =20 ams->addr =3D ip; ams->al_addr =3D al.addr; @@ -2093,7 +2095,7 @@ static void ip__resolve_data(struct thread *thread, =20 addr_location__init(&al); =20 - thread__find_symbol(thread, m, addr, &al); + thread__find_symbol(thread, &(struct perf_sample){.cpumode =3D m, .ip =3D= addr}, &al); =20 ams->addr =3D addr; ams->al_addr =3D al.addr; @@ -2227,7 +2229,9 @@ static int add_callchain_ip(struct thread *thread, al.sym =3D NULL; al.srcline =3D NULL; if (!cpumode) { - thread__find_cpumode_addr_location(thread, ip, symbols, &al); + thread__find_cpumode_addr_location(thread, + &(struct perf_sample){.ip =3D ip}, + symbols, &al); } else { if (ip >=3D PERF_CONTEXT_MAX) { switch (ip) { @@ -2255,9 +2259,13 @@ static int add_callchain_ip(struct thread *thread, goto out; } if (symbols) - thread__find_symbol(thread, *cpumode, ip, &al); + thread__find_symbol(thread, + &(struct perf_sample){.cpumode =3D *cpumode, .ip =3D ip}, + &al); else - thread__find_map(thread, *cpumode, ip, &al); + thread__find_map(thread, + &(struct perf_sample){.cpumode =3D *cpumode, .ip =3D ip}, + &al); } =20 if (al.sym !=3D NULL) { diff --git a/tools/perf/util/python.c b/tools/perf/util/python.c index d35190052d97..8857faf445cb 100644 --- a/tools/perf/util/python.c +++ b/tools/perf/util/python.c @@ -808,7 +808,10 @@ static PyObject *pyrf_sample_event__srccode(PyObject *= self, PyObject *args) =20 if (addr !=3D pevent->sample.ip) { addr_location__init(&al); - thread__find_symbol_fb(pevent->al.thread, pevent->sample.cpumode, addr, = &al); + thread__find_symbol_fb(pevent->al.thread, + &(struct perf_sample){ + .cpumode =3D pevent->sample.cpumode, + .ip =3D addr}, &al); } else { addr_location__init(&al); al.thread =3D thread__get(pevent->al.thread); diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools= /perf/util/scripting-engines/trace-event-python.c index 8f832ae316ca..8f7512c889a7 100644 --- a/tools/perf/util/scripting-engines/trace-event-python.c +++ b/tools/perf/util/scripting-engines/trace-event-python.c @@ -520,14 +520,16 @@ static PyObject *python_process_brstack(struct perf_s= ample *sample, PyLong_FromUnsignedLongLong(entries[i].flags.cycles)); =20 addr_location__init(&al); - thread__find_map_fb(thread, sample->cpumode, - entries[i].from, &al); + thread__find_map_fb(thread, + &(struct perf_sample){.cpumode =3D sample->cpumode, + .ip =3D entries[i].from}, &al); dsoname =3D get_dsoname(al.map); pydict_set_item_string_decref(pyelem, "from_dsoname", _PyUnicode_FromString(dsoname)); =20 - thread__find_map_fb(thread, sample->cpumode, - entries[i].to, &al); + thread__find_map_fb(thread, + &(struct perf_sample){.cpumode =3D sample->cpumode, + .ip =3D entries[i].to}, &al); dsoname =3D get_dsoname(al.map); pydict_set_item_string_decref(pyelem, "to_dsoname", _PyUnicode_FromString(dsoname)); @@ -593,14 +595,16 @@ static PyObject *python_process_brstacksym(struct per= f_sample *sample, if (!pyelem) Py_FatalError("couldn't create Python dictionary"); =20 - thread__find_symbol_fb(thread, sample->cpumode, - entries[i].from, &al); + thread__find_symbol_fb(thread, + &(struct perf_sample){.cpumode =3D sample->cpumode, + .ip =3D entries[i].from}, &al); get_symoff(al.sym, &al, true, bf, sizeof(bf)); pydict_set_item_string_decref(pyelem, "from", _PyUnicode_FromString(bf)); =20 - thread__find_symbol_fb(thread, sample->cpumode, - entries[i].to, &al); + thread__find_symbol_fb(thread, + &(struct perf_sample){.cpumode =3D sample->cpumode, + .ip =3D entries[i].to}, &al); get_symoff(al.sym, &al, true, bf, sizeof(bf)); pydict_set_item_string_decref(pyelem, "to", _PyUnicode_FromString(bf)); diff --git a/tools/perf/util/thread.c b/tools/perf/util/thread.c index e483ffcb5d93..e79b2c0dd5d5 100644 --- a/tools/perf/util/thread.c +++ b/tools/perf/util/thread.c @@ -413,7 +413,7 @@ int thread__fork(struct thread *thread, struct thread *= parent, u64 timestamp, bo return thread__clone_maps(thread, parent, do_maps_clone); } =20 -void thread__find_cpumode_addr_location(struct thread *thread, u64 addr, +void thread__find_cpumode_addr_location(struct thread *thread, struct perf= _sample *sample, bool symbols, struct addr_location *al) { size_t i; @@ -425,10 +425,11 @@ void thread__find_cpumode_addr_location(struct thread= *thread, u64 addr, }; =20 for (i =3D 0; i < ARRAY_SIZE(cpumodes); i++) { + sample->cpumode =3D cpumodes[i]; if (symbols) - thread__find_symbol(thread, cpumodes[i], addr, al); + thread__find_symbol(thread, sample, al); else - thread__find_map(thread, cpumodes[i], addr, al); + thread__find_map(thread, sample, al); =20 if (al->map) break; @@ -581,6 +582,7 @@ int thread__memcpy(struct thread *thread, struct machin= e *machine, void *buf, u64 ip, int len, bool *is64bit) { u8 cpumode =3D PERF_RECORD_MISC_USER; + struct perf_sample sample =3D { .ip =3D ip }; struct addr_location al; struct dso *dso; long offset; @@ -589,7 +591,8 @@ int thread__memcpy(struct thread *thread, struct machin= e *machine, cpumode =3D PERF_RECORD_MISC_KERNEL; =20 addr_location__init(&al); - if (!thread__find_map(thread, cpumode, ip, &al)) { + sample.cpumode =3D cpumode; + if (!thread__find_map(thread, &sample, &al)) { addr_location__exit(&al); return -1; } diff --git a/tools/perf/util/thread.h b/tools/perf/util/thread.h index d82fce8173ae..f0c50eafeee5 100644 --- a/tools/perf/util/thread.h +++ b/tools/perf/util/thread.h @@ -124,17 +124,17 @@ size_t thread__fprintf(struct thread *thread, FILE *f= p); =20 struct thread *thread__main_thread(struct machine *machine, struct thread = *thread); =20 -struct map *thread__find_map(struct thread *thread, u8 cpumode, u64 addr, +struct map *thread__find_map(struct thread *thread, struct perf_sample *sa= mple, struct addr_location *al); -struct map *thread__find_map_fb(struct thread *thread, u8 cpumode, u64 add= r, +struct map *thread__find_map_fb(struct thread *thread, struct perf_sample = *sample, struct addr_location *al); =20 -struct symbol *thread__find_symbol(struct thread *thread, u8 cpumode, - u64 addr, struct addr_location *al); -struct symbol *thread__find_symbol_fb(struct thread *thread, u8 cpumode, - u64 addr, struct addr_location *al); +struct symbol *thread__find_symbol(struct thread *thread, struct perf_samp= le *sample, + struct addr_location *al); +struct symbol *thread__find_symbol_fb(struct thread *thread, struct perf_s= ample *sample, + struct addr_location *al); =20 -void thread__find_cpumode_addr_location(struct thread *thread, u64 addr, +void thread__find_cpumode_addr_location(struct thread *thread, struct perf= _sample *sample, bool symbols, struct addr_location *al); =20 int thread__memcpy(struct thread *thread, struct machine *machine, diff --git a/tools/perf/util/unwind-libdw.c b/tools/perf/util/unwind-libdw.c index 63a5c2253174..10779a0c793e 100644 --- a/tools/perf/util/unwind-libdw.c +++ b/tools/perf/util/unwind-libdw.c @@ -77,7 +77,9 @@ static int __report_module(struct addr_location *al, u64 = ip, * Some callers will use al->sym, so we can't just use the * cheaper thread__find_map() here. */ - thread__find_symbol(ui->thread, PERF_RECORD_MISC_USER, ip, al); + thread__find_symbol(ui->thread, + &(struct perf_sample){.cpumode =3D PERF_RECORD_MISC_USER, .ip =3D i= p}, + al); =20 if (al->map) dso =3D map__dso(al->map); @@ -203,12 +205,13 @@ static bool get_thread(Dwfl *dwfl __maybe_unused, pid= _t tid, void *arg, static int access_dso_mem(struct unwind_info *ui, Dwarf_Addr addr, Dwarf_Word *data) { + struct perf_sample sample =3D { .cpumode =3D PERF_RECORD_MISC_USER, .ip = =3D addr }; struct addr_location al; ssize_t size; struct dso *dso; =20 addr_location__init(&al); - if (!thread__find_map(ui->thread, PERF_RECORD_MISC_USER, addr, &al)) { + if (!thread__find_map(ui->thread, &sample, &al)) { pr_debug("unwind: no map for %lx\n", (unsigned long)addr); goto out_fail; } diff --git a/tools/perf/util/unwind-libunwind.c b/tools/perf/util/unwind-li= bunwind.c index 73d191ce51a5..5d9f9002710a 100644 --- a/tools/perf/util/unwind-libunwind.c +++ b/tools/perf/util/unwind-libunwind.c @@ -351,7 +351,9 @@ static struct map *find_map(uint64_t ip, struct unwind_= info *ui) struct map *ret; =20 addr_location__init(&al); - thread__find_map(ui->thread, PERF_RECORD_MISC_USER, ip, &al); + thread__find_map(ui->thread, + &(struct perf_sample){.cpumode =3D PERF_RECORD_MISC_USER, .ip =3D ip}, + &al); ret =3D map__get(al.map); addr_location__exit(&al); return ret; @@ -596,7 +598,9 @@ static int entry(uint64_t ip, struct thread *thread, un= wind_entry_cb_t cb, void int ret; =20 addr_location__init(&al); - e.ms.sym =3D thread__find_symbol(thread, PERF_RECORD_MISC_USER, ip, &al); + e.ms.sym =3D thread__find_symbol(thread, + &(struct perf_sample){.cpumode =3D PERF_RECORD_MISC_USER, + .ip =3D ip}, &al); e.ip =3D ip; e.ms.map =3D al.map; e.ms.thread =3D thread__get(al.thread); --=20 2.55.0.679.g6767b8d81c-goog From nobody Tue Sep 29 13:18:52 2026 Received: from mail-pg1-f199.google.com (mail-pg1-f199.google.com [209.85.215.199]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 3F1E23C062C for ; Fri, 7 Aug 2026 07:18:36 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.215.199 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786087119; cv=none; b=h964C8CXCi2tqm4FXgWUuGnxykqWdJlkR85h4xPHEc9uY5Vy/gHH4jJjfrZ0o6NuM7eVxTmX6OiCkksXDRCdi2/Snjx8aSv2Ffoz/G09rogNoqNbDW5IlL3SF0rhfBzAhXy9c1lFkXTxzM5a/z/hHS9GuEpIZGVDOLiMaT7lrw4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786087119; c=relaxed/simple; bh=ZCCc99i/EoDgKN+cfkIOUGAGG11H8cIUbt47iXLmBNo=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Content-Type; b=rkBaFG52ji8h5oGc/nMbj/X2pXTzenZlKk2bDIwK9WlilsflzjHLWSkdxPm8Sj/0a4bxeeFHAibOIC8C5SJ5F/2wOiVNmvzitj5xeXKTSAohoG/d1tzeBJXYuuNFJyhMw1UEki1+5MRldELrEGsq/Lh+YLhoM9+4SK0Zbi9ed3A= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--irogers.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=I9YJld5N; arc=none smtp.client-ip=209.85.215.199 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--irogers.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="I9YJld5N" Received: by mail-pg1-f199.google.com with SMTP id 41be03b00d2f7-c9fe4c5eb39so2280715a12.1 for ; Fri, 07 Aug 2026 00:18:36 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20251104; t=1786087115; x=1786691915; darn=vger.kernel.org; h=content-type:to:from:subject:message-id:references:mime-version :in-reply-to:date:from:to:cc:subject:date:message-id:reply-to :content-type; bh=rWScONZGZwN2NQDuInfCsrpxwH4OLRaI7pljij4G41I=; b=I9YJld5NZszfpIVD7q5wvtfhVKg5R1PytZcXHAf2q9N2FoqHyW3TPvrMLwqRPg52nx viC9thw5053+f9be+d1pRIlkBm5/VeDcuKDvVODn3ovtf3OcyXqUHGFtEuybS1/ApG8C MZtJZmAZyhw0dIbM+dIuPn53gnITmGlTLF0ihsyzNONXluNSWcgbbJkMYIzViXoPVaON 3m7rFDbT4p0qUCyMTmoJN/rzNfO3ktrfjVBdA98UHTtWfZ6iLMlBHE5tn+UdlwJzvGEQ kjg4SPuoskrXXmwPrE7uHTCHNiRNd6IDcKcJ50fgL9YUcl910NS4NZpxPdotSAhXWCml Htug== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1786087115; x=1786691915; h=content-type:to:from:subject:message-id:references:mime-version :in-reply-to:date:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to:content-type; bh=rWScONZGZwN2NQDuInfCsrpxwH4OLRaI7pljij4G41I=; b=A4bCynnx7z70jKS8xKluVAdRkvw6sJFaKBp6NVghSElZM9cXTby4YnRjV0QdKxee7u C/vlu3Olv3icvpoEu7lHgBmNzI6CFgnPaeWNpRp6uyaa55p2i7NKzHBv+SAdAkJQS70C eaA+fKYV9WXOW70+Ybazu4aJlp7wGNvdWojitRAepAR/mD24Pk8srwXeqw4fRRKDd61y NW7QXeH8i1Ruw1vCufQnVUtKIWkqECqlamOIwlwC1CsJMDCqfUFn0CWhtcfY8DmxgOyF 2YdaZ6MTrzruUm/Csm3KNahy7crPVKaZcuan3f5aFH+OqzlwWSqSzvc3MnxhC9q+r+0J hg9Q== X-Forwarded-Encrypted: i=1; AHgh+RpfOAmNYGdQHA2JqtckO95YhFmeKnmYu18h/5w1iPpd89WB3bI+6R7CF0UwWmdvwmyYEARBrK4V5zN+t2k=@vger.kernel.org X-Gm-Message-State: AOJu0Yz6BwK3fPirl2sTuApIvoZDoVVh5cppmPlcnmJwfnOrXq8rNOeH 0UYrNbT3ZHu9CuqEufaFpPAsrfXOwEynvUmaUx4efoixZpXHfupoqoke3KuEPcndAgMS4esVfaK +B8CQSoBA7w== X-Received: from dyx18.prod.google.com ([2002:a05:693c:8212:b0:30c:5c4a:b8b1]) (user=irogers job=prod-delivery.src-stubby-dispatcher) by 2002:a05:6a21:e58b:b0:3a3:a9c4:3d60 with SMTP id adf61e73a8af0-3cb85f5c2b0mr25707036637.27.1786087114976; Fri, 07 Aug 2026 00:18:34 -0700 (PDT) Date: Fri, 7 Aug 2026 00:18:15 -0700 In-Reply-To: <20260807071818.718751-1-irogers@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20260807071818.718751-1-irogers@google.com> X-Mailer: git-send-email 2.55.0.679.g6767b8d81c-goog Message-ID: <20260807071818.718751-6-irogers@google.com> Subject: [RFC PATCH v1 5/8] perf tools: Internal support for BUILD_ID_OFFSET From: Ian Rogers To: Steven Rostedt , Masami Hiramatsu , Alexei Starovoitov , Daniel Borkmann , John Fastabend , Andrii Nakryiko , Eduard Zingerman , Kumar Kartikeya Dwivedi , Martin KaFai Lau , Song Liu , Yonghong Song , Jiri Olsa , Emil Tsalapatis , Peter Zijlstra , Ingo Molnar , Arnaldo Carvalho de Melo , Namhyung Kim , Mark Rutland , Alexander Shishkin , Ian Rogers , Adrian Hunter , James Clark , Suzuki K Poulose , Mike Leach , Leo Yan , John Garry , Will Deacon , Thomas Gleixner , Dapeng Mi , Ravi Bangoria , Swapnil Sapkal , Thomas Falcon , Thomas Richter , Dmitrii Dolgov <9erthalion6@gmail.com>, Eric Biggers , Zecheng Li , Gabriel Marin , Tengda Wu , Derek Foreman , Tanushree Shah , Ankur Arora , Aaron Tomlin , tanze , Rui Qi , Howard Chu , Chuck Lever , Shimin Guo , Alessio Podda , 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 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" 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 --- 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, struc= t perf_session *session) return -EINVAL; =20 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_OFFS= ET, + "IP", PERF_OUTPUT_IP)) return -EINVAL; } =20 @@ -511,7 +512,8 @@ static int evsel__check_attr(struct evsel *evsel, struc= t perf_session *session) return -EINVAL; =20 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, struc= t 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_sampl= e *sample, unsigned int print_opts =3D output[type].print_ip_opts; struct callchain_cursor *cursor =3D NULL; =20 - if (symbol_conf.use_callchain && sample->callchain) { + if (symbol_conf.use_callchain && (sample->callchain || sample->callchain= _bids)) { cursor =3D 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); =20 - if (symbol_conf.use_callchain && sample->callchain) { + if (symbol_conf.use_callchain && (sample->callchain || sample->callchain= _bids)) { cursor =3D 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 =3D NULL; =20 - if (symbol_conf.use_callchain && sample->callchain) { + if (symbol_conf.use_callchain && (sample->callchain || sample->callchain= _bids)) { cursor =3D 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, st= ruct perf_sample *sample, thread__zput(al->thread); al->thread =3D thread__get(thread); =20 - if (sample->ip) { - al->addr =3D sample->ip; - } else { - pr_debug("Sample missing IP data\n"); - return NULL; - } al->cpumode =3D sample->cpumode; al->filtered =3D 0; =20 @@ -740,15 +734,33 @@ struct map *thread__find_map(struct thread *thread, s= truct perf_sample *sample, =20 return NULL; } - al->map =3D maps__find(maps, al->addr); - if (al->map !=3D 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 =3D map__map_ip(al->map, al->addr); + + if (sample->ip) { + al->addr =3D sample->ip; + al->map =3D maps__find(maps, al->addr); + if (al->map !=3D 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 =3D 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 =3D sample->bid.offset; + al->map =3D maps__find_by_build_id(maps, &bid); + if (al->map !=3D 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; } =20 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 =3D (void *)array + sz; } =20 + if (type & PERF_SAMPLE_BUILD_ID_OFFSET) { + data->bid.bid =3D (struct perf_build_id *) array; + array +=3D sizeof(struct perf_build_id) / sizeof(u64); + data->bid.offset =3D *array; + array++; + } else { + data->bid.bid =3D NULL; + data->bid.offset =3D 0; + } + + + if (type & PERF_SAMPLE_CALLCHAIN_BUILD_ID_OFFSET) { + OVERFLOW_CHECK_u64(array); + sz =3D *array++; + + OVERFLOW_CHECK(array, sz * (sizeof(struct perf_build_id) + sizeof(u64)),= max_size); + data->callchain_bids =3D (struct perf_build_id *) array; + data->callchain_bids_nr =3D sz; + array +=3D sz * (sizeof(struct perf_build_id) + sizeof(u64)) / sizeof(u6= 4); + } else { + data->callchain_bids =3D NULL; + data->callchain_bids_nr =3D 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 ev= sel *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; } =20 diff --git a/tools/perf/util/evsel_fprintf.c b/tools/perf/util/evsel_fprint= f.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 *sampl= e, int left_alignment, if (cursor =3D=3D NULL) return fprintf(fp, "%s", pri= nt_oneline ? "" : "\n"); =20 - if (sample->callchain) { + if (sample->callchain || sample->callchain_bids) { callchain_cursor_commit(cursor); =20 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 =3D {}; struct addr_location al; @@ -2230,7 +2232,9 @@ static int add_callchain_ip(struct thread *thread, al.srcline =3D NULL; if (!cpumode) { thread__find_cpumode_addr_location(thread, - &(struct perf_sample){.ip =3D ip}, + &(struct perf_sample){.ip =3D ip, + .bid =3D { .bid =3D bid, + .offset =3D offset }}, symbols, &al); } else { if (ip >=3D PERF_CONTEXT_MAX) { @@ -2411,7 +2415,7 @@ static int lbr_callchain_add_kernel_ip(struct thread = *thread, err =3D add_callchain_ip(thread, cursor, parent, root_al, &cpumode, chain->ips[i], false, NULL, NULL, branch_from, - symbols); + symbols, /*bid=3D*/NULL, /*offset=3D*/0); if (err) return err; } @@ -2422,7 +2426,7 @@ static int lbr_callchain_add_kernel_ip(struct thread = *thread, err =3D add_callchain_ip(thread, cursor, parent, root_al, &cpumode, chain->ips[i], false, NULL, NULL, branch_from, - symbols); + symbols, /*bid=3D*/NULL, /*offset=3D*/0); if (err) return err; } @@ -2505,7 +2509,7 @@ static int lbr_callchain_add_lbr_ip(struct thread *th= read, err =3D add_callchain_ip(thread, cursor, parent, root_al, &cpumode, ip, true, flags, NULL, - *branch_from, symbols); + *branch_from, symbols, /*bid=3D*/NULL, /*offset=3D*/0); if (err) return err; =20 @@ -2530,7 +2534,7 @@ static int lbr_callchain_add_lbr_ip(struct thread *th= read, err =3D add_callchain_ip(thread, cursor, parent, root_al, &cpumode, ip, true, flags, NULL, - *branch_from, symbols); + *branch_from, symbols, /*bid=3D*/NULL, /*offset=3D*/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 *th= read, err =3D add_callchain_ip(thread, cursor, parent, root_al, &cpumode, ip, true, flags, NULL, - *branch_from, symbols); + *branch_from, symbols, /*bid=3D*/NULL, /*offset=3D*/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 *th= read, err =3D add_callchain_ip(thread, cursor, parent, root_al, &cpumode, ip, true, flags, NULL, - *branch_from, symbols); + *branch_from, symbols, /*bid=3D*/NULL, /*offset=3D*/0); if (err) return err; } @@ -2829,7 +2833,8 @@ static int find_prev_cpumode(struct ip_callchain *cha= in, struct thread *thread, if (ip >=3D PERF_CONTEXT_MAX) { err =3D add_callchain_ip(thread, cursor, parent, root_al, cpumode, ip, - false, NULL, NULL, 0, symbols); + false, NULL, NULL, 0, symbols, + /*bid=3D*/NULL, /*offset=3D*/0); break; } } @@ -2857,6 +2862,7 @@ static int thread__resolve_callchain_sample(struct th= read *thread, struct branch_stack *branch =3D sample->branch_stack; struct branch_entry *entries =3D perf_sample__branch_entries(sample); struct ip_callchain *chain =3D sample->callchain; + struct ip_callchain *alloc_chain =3D NULL; int chain_nr =3D 0; u8 cpumode =3D PERF_RECORD_MISC_USER; int i, j, err, nr_entries, usr_idx; @@ -2864,6 +2870,16 @@ static int thread__resolve_callchain_sample(struct t= hread *thread, int first_call =3D 0; u64 leaf_frame_caller; =20 + if (!chain && sample->callchain_bids_nr > 0) { + alloc_chain =3D malloc(sizeof(*chain) + sample->callchain_bids_nr * size= of(u64)); + if (alloc_chain) { + alloc_chain->nr =3D sample->callchain_bids_nr; + for (i =3D 0; i < (int)sample->callchain_bids_nr; i++) + alloc_chain->ips[i] =3D ((u64 *)sample->callchain_bids)[i * 4 + 3]; + chain =3D alloc_chain; + } + } + if (chain) chain_nr =3D chain->nr; =20 @@ -2874,8 +2890,10 @@ static int thread__resolve_callchain_sample(struct t= hread *thread, root_al, max_stack, !env ? 0 : env->max_branches, symbols); - if (err) - return (err < 0) ? err : 0; + if (err) { + err =3D (err < 0) ? err : 0; + goto out; + } } =20 /* @@ -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=3D*/NULL, /*offset=3D*/0); =20 if (!err) { err =3D 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=3D*/NULL, /*offset=3D*/0); } if (err =3D=3D -EINVAL) break; if (err) - return err; + goto out; } =20 if (chain_nr =3D=3D 0) @@ -2962,12 +2982,16 @@ static int thread__resolve_callchain_sample(struct = thread *thread, if (chain && callchain_param.order !=3D ORDER_CALLEE) { err =3D 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 =3D (err < 0) ? err : 0; + goto out; + } } for (i =3D first_call, nr_entries =3D 0; i < chain_nr && nr_entries < max_stack; i++) { u64 ip; + struct perf_build_id *bid =3D NULL; + u64 offset =3D 0; =20 if (callchain_param.order =3D=3D ORDER_CALLEE) j =3D i; @@ -2979,13 +3003,19 @@ static int thread__resolve_callchain_sample(struct = thread *thread, continue; #endif ip =3D chain->ips[j]; + if (sample->callchain_bids) { + bid =3D (struct perf_build_id *)&((u64 *)sample->callchain_bids)[j * 4]; + offset =3D ((u64 *)sample->callchain_bids)[j * 4 + 3]; + } if (ip < PERF_CONTEXT_MAX) ++nr_entries; else if (callchain_param.order !=3D ORDER_CALLEE) { err =3D find_prev_cpumode(chain, thread, cursor, parent, root_al, &cpumode, j, symbols); - if (err) - return (err < 0) ? err : 0; + if (err) { + err =3D (err < 0) ? err : 0; + goto out; + } continue; } =20 @@ -3011,21 +3041,28 @@ static int thread__resolve_callchain_sample(struct = thread *thread, =20 err =3D 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 =3D (err < 0) ? err : 0; + goto out; + } } } =20 err =3D add_callchain_ip(thread, cursor, parent, root_al, &cpumode, ip, - false, NULL, NULL, 0, symbols); + false, NULL, NULL, 0, symbols, bid, offset); =20 - if (err) - return (err < 0) ? err : 0; + if (err) { + err =3D (err < 0) ? err : 0; + goto out; + } } =20 - return 0; + err =3D 0; +out: + free(alloc_chain); + return err; } =20 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)); } =20 +struct map *maps__find_by_build_id(struct maps *maps, struct build_id *bid) +{ + struct map *result =3D NULL; + bool done =3D false; + + /* See locking/sorting note. */ + while (!done) { + down_read(maps__lock(maps)); + if (maps__maps_by_address_sorted(maps)) { + struct map **maps_by_address =3D maps__maps_by_address(maps); + unsigned int nr_maps =3D maps__nr_maps(maps); + + for (unsigned int i =3D 0; i < nr_maps; i++) { + struct map *map =3D maps_by_address[i]; + + if (dso__build_id_equal(map__dso(map), bid)) { + result =3D map__get(map); + break; + } + } + done =3D 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 =3D 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; =20 #define KMAP_NAME_LEN 256 =20 @@ -76,6 +77,7 @@ int maps__find_ams(struct maps *maps, struct addr_map_sym= bol *ams); int maps__fixup_overlap_and_insert(struct maps *maps, struct map *new); =20 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= ); =20 struct map *maps__find_next_entry(struct maps *maps, struct map *map); =20 diff --git a/tools/perf/util/perf_event_attr_fprintf.c b/tools/perf/util/pe= rf_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 v= alue) 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 =3D 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; =20 /* number of register is bound by the number of bits in regs_dump::mask (6= 4) */ #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 pe= rf_sample *sample, u64 type, result +=3D sample->aux_sample.size; } =20 + if (type & PERF_SAMPLE_BUILD_ID_OFFSET) + result +=3D sizeof(struct perf_build_id) + sizeof(u64); + + if (type & PERF_SAMPLE_CALLCHAIN_BUILD_ID_OFFSET) + result +=3D sizeof(u64) + sample->callchain->nr * + (sizeof(struct perf_build_id) + sizeof(u64)); + return result; } =20 @@ -1933,6 +1940,19 @@ int perf_event__synthesize_sample(union perf_event *= event, u64 type, u64 read_fo array =3D (void *)array + sz; } =20 + if (type & PERF_SAMPLE_BUILD_ID_OFFSET) { + memcpy(array, sample->bid.bid, sizeof(struct perf_build_id)); + array +=3D sizeof(struct perf_build_id) / sizeof(u64); + *array++ =3D sample->bid.offset; + } + + if (type & PERF_SAMPLE_CALLCHAIN_BUILD_ID_OFFSET) { + *array++ =3D sample->callchain->nr; + sz =3D sample->callchain->nr * (sizeof(struct perf_build_id) + sizeof(u6= 4)); + memcpy(array, sample->callchain_bids, sz); + array +=3D sz / sizeof(u64); + } + return 0; } =20 --=20 2.55.0.679.g6767b8d81c-goog From nobody Tue Sep 29 13:18:52 2026 Received: from mail-pg1-f200.google.com (mail-pg1-f200.google.com [209.85.215.200]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id DD6BB3C1D61 for ; Fri, 7 Aug 2026 07:18:38 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.215.200 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786087122; cv=none; b=L6WLvmHS2LTwOZdSA/3KIMRjBETmvgXbOEIeBmm2snGFEO7UDDryDZyeJOSTxNxwjQI8JsleCS+rxa8iYwXZpDyMC3AKN5ylgvyzsjvVI77WQdPsN61uCvDWltX6NpaAPlw0Vp+oVqMsHMIVeanlY4fY61VxJe8rU/a3QzC/axw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786087122; c=relaxed/simple; bh=S9QT8b0kd2xRVLf3lLP5oiZ/aD5o4IvDCLPYvHHsR7M=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Content-Type; b=TswZGU6rKrqfVLyed+JoY4gorICJt1MeGZctJcZ6OIAkGG6f4KHXHEQDGpPNKsRHsSlVjBtErCb+l9v9F3jiwraF909vJE1gMgLp0XxqVwNSfHwPkYTs/tYy4eNPxkkxBgNrz66hmlPZsqxokJ+jJN1YhkkpZXQgzbsIRLmdcQg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--irogers.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=rNF0Ynmh; arc=none smtp.client-ip=209.85.215.200 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--irogers.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="rNF0Ynmh" Received: by mail-pg1-f200.google.com with SMTP id 41be03b00d2f7-cb6cf425e86so3495452a12.1 for ; Fri, 07 Aug 2026 00:18:38 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20251104; t=1786087118; x=1786691918; darn=vger.kernel.org; h=content-type:to:from:subject:message-id:references:mime-version :in-reply-to:date:from:to:cc:subject:date:message-id:reply-to :content-type; bh=MgsJriLIU9dRPdYwuhTOgbzKSY3swUpCCJFzn9PAz+E=; b=rNF0YnmhP0fx0ELiTjufJhyMvioSI08C6gBIFsGubuOP6J7svkX9E2LALnPr9PyuDv htGiq2j+TeC8H0O23I1CfYEEdAyzyy7L/vmUK4PpXy14QtaH46htOHBqJIb8HlRuRN64 TueYWHIi0T7C6LZteq/iMLaid9UOpkHbvv1H1qdpGA/mjhx+K5SwqNdMWOhX6GTM+uGg tYqJ257IEVqRAIq5rBIg2LaphaJ3si/AV5aC8oseR34KqPOzNpQBsvi2YynJornR5L4h DDU/U8CthYBth2dI6yq2YmC5AQANzmIFKG6pF+pyHZ9uWewUpIac+QX1axoi/12jaM4t lWdg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1786087118; x=1786691918; h=content-type:to:from:subject:message-id:references:mime-version :in-reply-to:date:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to:content-type; bh=MgsJriLIU9dRPdYwuhTOgbzKSY3swUpCCJFzn9PAz+E=; b=MGG7sFJ4uKNztwb8AD7xdy76kwDHNX9Sc9+KrJW276EY+E5wnR6NnTizQ/F7CF5Znk q6+XtZWHTXYTZ5QGkdaSkzb+zR1aEYYL4lbe6WwvYKSsm2vhyLfrl7w5nA5bCykhr9G0 GCDJlTqtCSZYinBD785lv3mKmryiUvpEuMHiNr72wC52zwqp1R9yucQCOi+jaiSLOMPD ZW0WiCo7sD+20jySnoozSipBW5TNTIV5kD8SgPi0XNBb/ZCmLPJh/8ib3VlJINYc/ImB c15g5/8U6ByuIoddzuCKCvcGVO0ij3QbZsIEiP/9wL8SMnNB8OputSgijdHqgdsi4hhC I3Xg== X-Forwarded-Encrypted: i=1; AHgh+RqfL91ker5NrGQqjeidC6IEkhUPEf027UEM/9krDZWLS0pdgwoIIj3vzo3XHLm/0SpxM/PTeHEdm6b6x/E=@vger.kernel.org X-Gm-Message-State: AOJu0Yx5PQoxx9xQ/GbaFO0PP4lZOc4oE1SO9OOgkfRlLg/op+/8zN5f y6NcovcCYvVYQiEE6IVzZw915NCbSXC4EWSZ3b0KJhB4JSQMRJGd/dFTiP9NwTVPkeVulP22xX5 mHT4AFotO8A== X-Received: from dybmx3.prod.google.com ([2002:a05:7300:d403:b0:315:a379:c9e7]) (user=irogers job=prod-delivery.src-stubby-dispatcher) by 2002:a05:6a20:914b:b0:3c3:bbe6:95b1 with SMTP id adf61e73a8af0-3cb85eef9d6mr21031304637.24.1786087117513; Fri, 07 Aug 2026 00:18:37 -0700 (PDT) Date: Fri, 7 Aug 2026 00:18:16 -0700 In-Reply-To: <20260807071818.718751-1-irogers@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20260807071818.718751-1-irogers@google.com> X-Mailer: git-send-email 2.55.0.679.g6767b8d81c-goog Message-ID: <20260807071818.718751-7-irogers@google.com> Subject: [RFC PATCH v1 6/8] perf inject: Extend perf inject to support bid_offset conversion From: Ian Rogers To: Steven Rostedt , Masami Hiramatsu , Alexei Starovoitov , Daniel Borkmann , John Fastabend , Andrii Nakryiko , Eduard Zingerman , Kumar Kartikeya Dwivedi , Martin KaFai Lau , Song Liu , Yonghong Song , Jiri Olsa , Emil Tsalapatis , Peter Zijlstra , Ingo Molnar , Arnaldo Carvalho de Melo , Namhyung Kim , Mark Rutland , Alexander Shishkin , Ian Rogers , Adrian Hunter , James Clark , Suzuki K Poulose , Mike Leach , Leo Yan , John Garry , Will Deacon , Thomas Gleixner , Dapeng Mi , Ravi Bangoria , Swapnil Sapkal , Thomas Falcon , Thomas Richter , Dmitrii Dolgov <9erthalion6@gmail.com>, Eric Biggers , Zecheng Li , Gabriel Marin , Tengda Wu , Derek Foreman , Tanushree Shah , Ankur Arora , Aaron Tomlin , tanze , Rui Qi , Howard Chu , Chuck Lever , Shimin Guo , Alessio Podda , 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 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" This adds the --sample-buildids option to perf inject, allowing it to drop MMAP events and rewrite samples to use build IDs and offsets instead of virtual addresses. Signed-off-by: Ian Rogers --- tools/perf/builtin-inject.c | 14 +- tools/perf/util/Build | 1 + tools/perf/util/inject_bid_offset.c | 504 ++++++++++++++++++++++++++++ tools/perf/util/inject_bid_offset.h | 21 ++ 4 files changed, 539 insertions(+), 1 deletion(-) create mode 100644 tools/perf/util/inject_bid_offset.c create mode 100644 tools/perf/util/inject_bid_offset.h diff --git a/tools/perf/builtin-inject.c b/tools/perf/builtin-inject.c index 6aa9e3eea438..8f8d5267a37e 100644 --- a/tools/perf/builtin-inject.c +++ b/tools/perf/builtin-inject.c @@ -9,6 +9,7 @@ #include "builtin.h" =20 #include "util/aslr.h" +#include "util/inject_bid_offset.h" #include "util/color.h" #include "util/dso.h" #include "util/vdso.h" @@ -112,6 +113,7 @@ enum build_id_rewrite_style { BID_RWS__INJECT_HEADER_ALL, BID_RWS__MMAP2_BUILDID_ALL, BID_RWS__MMAP2_BUILDID_LAZY, + BID_RWS__SAMPLE_BUILDID, }; =20 struct perf_inject { @@ -371,7 +373,7 @@ static s64 perf_event__repipe_auxtrace(const struct per= f_tool *tool, return event->auxtrace.size; } =20 -static int perf_event__repipe(const struct perf_tool *tool, +int perf_event__repipe(const struct perf_tool *tool, union perf_event *event, struct perf_sample *sample __maybe_unused, struct machine *machine __maybe_unused) @@ -2687,6 +2689,7 @@ int cmd_inject(int argc, const char **argv) bool build_id_all =3D false; bool mmap2_build_ids =3D false; bool mmap2_build_id_all =3D false; + bool build_id_sample =3D false; =20 struct option options[] =3D { OPT_BOOLEAN('b', "build-ids", &build_ids, @@ -2695,8 +2698,11 @@ int cmd_inject(int argc, const char **argv) "Inject build-ids of all DSOs into the output stream"), OPT_BOOLEAN('B', "mmap2-buildids", &mmap2_build_ids, "Drop unused mmap events, make others mmap2 with build IDs"), + OPT_BOOLEAN(0, "mmap2-buildid-all", &mmap2_build_id_all, "Rewrite all mmap events as mmap2 events with build IDs"), + OPT_BOOLEAN('S', "sample-buildids", &build_id_sample, + "Drop all mmap events and rewrite samples to use build ID + offset"= ), OPT_STRING(0, "known-build-ids", &known_build_ids, "buildid path [,buildid path...]", "build-ids to use for given paths"), @@ -2815,8 +2821,11 @@ int cmd_inject(int argc, const char **argv) inject.build_id_style =3D BID_RWS__MMAP2_BUILDID_ALL; if (build_ids) inject.build_id_style =3D BID_RWS__INJECT_HEADER_LAZY; + if (build_id_all) inject.build_id_style =3D BID_RWS__INJECT_HEADER_ALL; + if (build_id_sample) + inject.build_id_style =3D BID_RWS__SAMPLE_BUILDID; =20 data.path =3D inject.input_name; =20 @@ -2880,8 +2889,11 @@ int cmd_inject(int argc, const char **argv) =20 if (IS_ERR(inject.session)) { ret =3D PTR_ERR(inject.session); + if (inject.aslr) aslr_tool__delete(tool); + if (inject.build_id_style =3D=3D BID_RWS__SAMPLE_BUILDID) + inject_bid_offset_tool__delete(tool); goto out_close_output; } =20 diff --git a/tools/perf/util/Build b/tools/perf/util/Build index 330311cac550..cefbf2ef3fac 100644 --- a/tools/perf/util/Build +++ b/tools/perf/util/Build @@ -7,6 +7,7 @@ perf-util-y +=3D addr2line.o perf-util-y +=3D addr_location.o perf-util-y +=3D annotate.o perf-util-y +=3D aslr.o +perf-util-y +=3D inject_bid_offset.o perf-util-y +=3D blake2s.o perf-util-y +=3D block-info.o perf-util-y +=3D block-range.o diff --git a/tools/perf/util/inject_bid_offset.c b/tools/perf/util/inject_b= id_offset.c new file mode 100644 index 000000000000..f7b5fb05fac7 --- /dev/null +++ b/tools/perf/util/inject_bid_offset.c @@ -0,0 +1,504 @@ +// SPDX-License-Identifier: GPL-2.0 +#include "inject_bid_offset.h" + +#include + +#include +#include +#include + +#include "addr_location.h" +#include "debug.h" +#include "dso.h" +#include "event.h" +#include "evlist.h" +#include "evsel.h" +#include "machine.h" +#include "map.h" +#include "session.h" +#include "synthetic-events.h" +#include "thread.h" +#include "tool.h" + +struct inject_bid_offset_tool { + struct delegate_tool tool; + char event_copy[PERF_SAMPLE_MAX_SIZE] __aligned(8); +}; + +int perf_event__rewrite_attr_for_build_id_offset(struct perf_event_attr *a= ttr) +{ + if (attr->sample_type & (PERF_SAMPLE_BUILD_ID_OFFSET | + PERF_SAMPLE_CALLCHAIN_BUILD_ID_OFFSET)) { + /* + * Expect to add build ID information from virtual address, if + * it is already present then things would be confused so fail. + */ + return -1; + } + if (attr->sample_type & PERF_SAMPLE_IP) { + attr->sample_type &=3D ~PERF_SAMPLE_IP; + attr->sample_type |=3D PERF_SAMPLE_BUILD_ID_OFFSET; + } + if (attr->sample_type & PERF_SAMPLE_CALLCHAIN) { + attr->sample_type &=3D ~PERF_SAMPLE_CALLCHAIN; + attr->sample_type |=3D PERF_SAMPLE_CALLCHAIN_BUILD_ID_OFFSET; + } + return 0; +} + +int perf_event__rewrite_attr_for_sample_ip(struct perf_event_attr *attr) +{ + if (attr->sample_type & (PERF_SAMPLE_IP | PERF_SAMPLE_CALLCHAIN)) { + /* + * Expect to remove build ID information for virtual address, if + * it is already present then things would be confused so fail. + */ + return -1; + } + if (attr->sample_type & PERF_SAMPLE_BUILD_ID_OFFSET) { + attr->sample_type &=3D ~PERF_SAMPLE_BUILD_ID_OFFSET; + attr->sample_type |=3D PERF_SAMPLE_IP; + } + if (attr->sample_type & PERF_SAMPLE_CALLCHAIN_BUILD_ID_OFFSET) { + attr->sample_type &=3D ~PERF_SAMPLE_CALLCHAIN_BUILD_ID_OFFSET; + attr->sample_type |=3D PERF_SAMPLE_CALLCHAIN; + } + return 0; +} + +static void perf_event__inject_sample_buildid_array(struct thread *thread, + u64 ip, u8 cpumode, + __u64 *array) +{ + struct perf_build_id bid =3D { .size =3D 0 }; + u64 offset =3D ip; + struct addr_location al; + struct dso *dso; + const struct build_id *dso_bid; + + struct perf_sample ps =3D { .ip =3D ip, .cpumode =3D cpumode }; + + addr_location__init(&al); + + if (!thread) + goto write_bid; + + if (!thread__find_map(thread, &ps, &al)) + goto write_bid; + + dso =3D al.map ? dso__get(map__dso(al.map)) : NULL; + if (!dso) + goto write_bid; + dso_bid =3D dso__bid(dso); + if (!dso_bid) { + dso__put(dso); + goto write_bid; + } + + bid.size =3D dso_bid->size; + if (bid.size > sizeof(bid.data)) + bid.size =3D sizeof(bid.data); + memcpy(bid.data, &dso_bid->data, bid.size); + offset =3D map__dso_map_ip(al.map, offset); + dso__put(dso); + +write_bid: + compiletime_assert(sizeof(struct perf_build_id) =3D=3D 3 * sizeof(u64), + "Unexpected perf_build_id size"); + memcpy(&array[0], &bid, 3 * sizeof(u64)); + array[3] =3D offset; + addr_location__exit(&al); +} + +static void mark_dso_hit(const struct perf_tool *tool, + struct perf_sample *sample, struct machine *machine, + struct thread *thread, u64 ip, u8 cpumode) +{ + struct addr_location al; + struct dso *dso; + + struct perf_sample ps =3D { .ip =3D ip, .cpumode =3D cpumode }; + + addr_location__init(&al); + + if (thread__find_map(thread, &ps, &al)) { + dso =3D al.map ? dso__get(map__dso(al.map)) : NULL; + if (dso) { + if (!dso__hit(dso)) { + const struct build_id *bid =3D dso__bid(dso); + + dso__set_hit(dso); + if (bid) { + perf_event__synthesize_build_id( + tool, sample, machine, + perf_event__repipe, + dso__kernel(dso) ? + PERF_RECORD_MISC_KERNEL : + PERF_RECORD_MISC_USER, + bid, dso->long_name); + } + } + dso__put(dso); + } + } + addr_location__exit(&al); +} + +static int inject_bid_offset_tool__sample(const struct perf_tool *tool, + union perf_event *event, + struct perf_sample *sample, + struct machine *machine) +{ + struct delegate_tool *dt =3D + container_of(tool, struct delegate_tool, tool); + struct inject_bid_offset_tool *ibo =3D + container_of(dt, struct inject_bid_offset_tool, tool); + union perf_event *ev; + struct evsel *evsel =3D sample->evsel; + __u64 i =3D 0, j =3D 0; + __u64 *in_array, *out_array; + __u64 sample_type =3D evsel->core.attr.sample_type; + const __u64 max_i =3D event->header.size / sizeof(__u64); + struct thread *thread; + u16 max_size =3D event->header.size; + + if ((sample_type & (PERF_SAMPLE_IP | PERF_SAMPLE_CALLCHAIN)) =3D=3D 0) + return ibo->tool.delegate->sample(ibo->tool.delegate, event, + sample, machine); + + if (symbol_conf.guest_code && !machine__is_host(machine)) + thread =3D machine__findnew_guest_code(machine, sample->pid); + else + thread =3D machine__findnew_thread(machine, sample->pid, + sample->tid); + + if (sample_type & PERF_SAMPLE_IP) + max_size +=3D sizeof(struct perf_build_id) + sizeof(u64) - + sizeof(u64); + + if (sample_type & PERF_SAMPLE_CALLCHAIN) { + max_size +=3D + sample->callchain->nr * (sizeof(struct perf_build_id) + + sizeof(u64) - sizeof(u64)); + } + + if (max_size > PERF_SAMPLE_MAX_SIZE) { + pr_debug("Insufficient space to copy event\n"); + thread__put(thread); + return -E2BIG; + } + + ev =3D (union perf_event *)ibo->event_copy; + ev->sample.header =3D + (struct perf_event_header){ .type =3D event->header.type, + .misc =3D event->header.misc, + .size =3D max_size }; + + in_array =3D &event->sample.array[0]; + out_array =3D &ev->sample.array[0]; + + if (sample_type & PERF_SAMPLE_IDENTIFIER) { + if (i > max_i) + goto err; + out_array[j++] =3D in_array[i++]; + } + if (sample_type & PERF_SAMPLE_IP) { + i++; + if (evsel && thread) + mark_dso_hit(ibo->tool.delegate, sample, machine, + thread, sample->ip, sample->cpumode); + } + if (sample_type & PERF_SAMPLE_TID) { + if (i > max_i) + goto err; + out_array[j++] =3D in_array[i++]; + } + if (sample_type & PERF_SAMPLE_TIME) { + if (i > max_i) + goto err; + out_array[j++] =3D in_array[i++]; + } + if (sample_type & PERF_SAMPLE_ADDR) { + if (i > max_i) + goto err; + out_array[j++] =3D in_array[i++]; + } + if (sample_type & PERF_SAMPLE_ID) { + if (i > max_i) + goto err; + out_array[j++] =3D in_array[i++]; + } + if (sample_type & PERF_SAMPLE_STREAM_ID) { + if (i > max_i) + goto err; + out_array[j++] =3D in_array[i++]; + } + if (sample_type & PERF_SAMPLE_CPU) { + if (i > max_i) + goto err; + out_array[j++] =3D in_array[i++]; + } + if (sample_type & PERF_SAMPLE_PERIOD) { + if (i > max_i) + goto err; + out_array[j++] =3D in_array[i++]; + } + if (sample_type & PERF_SAMPLE_READ) { + if ((evsel->core.attr.read_format & PERF_FORMAT_GROUP) =3D=3D 0) { + if (i > max_i) + goto err; + out_array[j++] =3D in_array[i++]; + if (evsel->core.attr.read_format & + PERF_FORMAT_TOTAL_TIME_ENABLED) + if (i > max_i) + goto err; + out_array[j++] =3D in_array[i++]; + if (evsel->core.attr.read_format & + PERF_FORMAT_TOTAL_TIME_RUNNING) + if (i > max_i) + goto err; + out_array[j++] =3D in_array[i++]; + if (evsel->core.attr.read_format & PERF_FORMAT_ID) + if (i > max_i) + goto err; + out_array[j++] =3D in_array[i++]; + if (evsel->core.attr.read_format & PERF_FORMAT_LOST) + if (i > max_i) + goto err; + out_array[j++] =3D in_array[i++]; + } else { + u64 nr; + + if (i > max_i) + goto err; + nr =3D out_array[j++] =3D in_array[i++]; + if (evsel->core.attr.read_format & + PERF_FORMAT_TOTAL_TIME_ENABLED) + if (i > max_i) + goto err; + out_array[j++] =3D in_array[i++]; + if (evsel->core.attr.read_format & + PERF_FORMAT_TOTAL_TIME_RUNNING) + if (i > max_i) + goto err; + out_array[j++] =3D in_array[i++]; + for (u64 cntr =3D 0; cntr < nr; cntr++) { + if (i > max_i) + goto err; + out_array[j++] =3D in_array[i++]; + if (evsel->core.attr.read_format & + PERF_FORMAT_ID) + if (i > max_i) + goto err; + out_array[j++] =3D in_array[i++]; + if (evsel->core.attr.read_format & + PERF_FORMAT_LOST) + if (i > max_i) + goto err; + out_array[j++] =3D in_array[i++]; + } + } + } + if (sample_type & PERF_SAMPLE_CALLCHAIN) { + i++; + if (evsel && thread) { + for (u64 x =3D 0; x < sample->callchain->nr; x++) + mark_dso_hit(ibo->tool.delegate, sample, + machine, thread, + sample->callchain->ips[x], + sample->cpumode); + } + i +=3D sample->callchain->nr; + } + if (sample_type & PERF_SAMPLE_RAW) { + size_t bytes =3D sizeof(u32) + sample->raw_size; + + if ((i + (bytes / sizeof(u64))) > max_i) + goto err; + memcpy(&out_array[j], &in_array[i], bytes); + i +=3D bytes / sizeof(u64); + j +=3D bytes / sizeof(u64); + } + if (sample_type & PERF_SAMPLE_BRANCH_STACK) { + if (i > max_i) + goto err; + out_array[j++] =3D in_array[i++]; + if (sample_type & PERF_SAMPLE_BRANCH_HW_INDEX) { + if (i > max_i) + goto err; + out_array[j++] =3D in_array[i++]; + } + if (i + (sample->branch_stack->nr * 3) > max_i) + goto err; + memcpy(&out_array[j], &in_array[i], + sample->branch_stack->nr * 3 * sizeof(u64)); + i +=3D sample->branch_stack->nr * 3; + j +=3D sample->branch_stack->nr * 3; + if (sample_type & PERF_SAMPLE_BRANCH_COUNTERS) { + if (i + sample->branch_stack->nr > max_i) + goto err; + memcpy(&out_array[j], &in_array[i], + sample->branch_stack->nr * sizeof(u64)); + i +=3D sample->branch_stack->nr; + j +=3D sample->branch_stack->nr; + } + } + if (sample_type & PERF_SAMPLE_REGS_USER) { + if (i > max_i) + goto err; + out_array[j++] =3D in_array[i++]; + if (sample->user_regs->abi !=3D PERF_SAMPLE_REGS_ABI_NONE) { + u64 nr =3D hweight64(evsel->core.attr.sample_regs_user); + + if (i + nr > max_i) + goto err; + memcpy(&out_array[j], &in_array[i], nr * sizeof(u64)); + i +=3D nr; + j +=3D nr; + } + } + if (sample_type & PERF_SAMPLE_STACK_USER) { + u64 size; + + if (i > max_i) + goto err; + size =3D out_array[j++] =3D in_array[i++]; + if (size > 0) { + memcpy(&out_array[j], &in_array[i], size); + i +=3D size / sizeof(u64); + j +=3D size / sizeof(u64); + if (i > max_i) + goto err; + out_array[j++] =3D in_array[i++]; + } + } + if (sample_type & PERF_SAMPLE_WEIGHT_TYPE) { + if (i > max_i) + goto err; + out_array[j++] =3D in_array[i++]; + } + if (sample_type & PERF_SAMPLE_DATA_SRC) { + if (i > max_i) + goto err; + out_array[j++] =3D in_array[i++]; + } + if (sample_type & PERF_SAMPLE_TRANSACTION) { + if (i > max_i) + goto err; + out_array[j++] =3D in_array[i++]; + } + if (sample_type & PERF_SAMPLE_REGS_INTR) { + if (i > max_i) + goto err; + out_array[j++] =3D in_array[i++]; + if (sample->intr_regs->abi !=3D PERF_SAMPLE_REGS_ABI_NONE) { + u64 nr =3D hweight64(evsel->core.attr.sample_regs_intr); + + if (i + nr > max_i) + goto err; + memcpy(&out_array[j], &in_array[i], nr * sizeof(u64)); + i +=3D nr; + j +=3D nr; + } + } + if (sample_type & PERF_SAMPLE_PHYS_ADDR) { + if (i > max_i) + goto err; + out_array[j++] =3D in_array[i++]; + } + if (sample_type & PERF_SAMPLE_CGROUP) { + if (i > max_i) + goto err; + out_array[j++] =3D in_array[i++]; + } + if (sample_type & PERF_SAMPLE_DATA_PAGE_SIZE) { + if (i > max_i) + goto err; + out_array[j++] =3D in_array[i++]; + } + if (sample_type & PERF_SAMPLE_CODE_PAGE_SIZE) { + if (i > max_i) + goto err; + out_array[j++] =3D in_array[i++]; + } + if (sample_type & PERF_SAMPLE_AUX) { + u64 size; + + if (i > max_i) + goto err; + size =3D out_array[j++] =3D in_array[i++]; + if (i + (size / sizeof(u64)) > max_i) + goto err; + memcpy(&out_array[j], &in_array[i], size); + i +=3D size / sizeof(u64); + j +=3D size / sizeof(u64); + } + + if (sample_type & PERF_SAMPLE_IP) { + perf_event__inject_sample_buildid_array( + thread, sample->ip, sample->cpumode, &out_array[j]); + j +=3D 4; + } + if (sample_type & PERF_SAMPLE_CALLCHAIN) { + out_array[j++] =3D sample->callchain->nr; + for (u64 x =3D 0; x < sample->callchain->nr; x++) { + perf_event__inject_sample_buildid_array( + thread, sample->callchain->ips[x], + sample->cpumode, &out_array[j]); + j +=3D 4; + } + } + + thread__put(thread); + + return ibo->tool.delegate->sample(ibo->tool.delegate, ev, sample, + machine); + +err: + thread__put(thread); + return -EFAULT; +} + +static int +inject_bid_offset_tool__mmap(const struct perf_tool *tool __maybe_unused, + union perf_event *event, + struct perf_sample *sample, + struct machine *machine) +{ + perf_event__process_mmap(tool, event, sample, machine); + return 0; // Drop mmap events from output stream +} +static int +inject_bid_offset_tool__mmap2(const struct perf_tool *tool __maybe_unused, + union perf_event *event, + struct perf_sample *sample, + struct machine *machine) +{ + perf_event__process_mmap2(tool, event, sample, machine); + return 0; // Drop mmap2 events from output stream +} + +struct perf_tool *inject_bid_offset_tool__new(struct perf_tool *delegate) +{ + struct inject_bid_offset_tool *ibo =3D zalloc(sizeof(*ibo)); + + if (!ibo) + return NULL; + + delegate_tool__init(&ibo->tool, delegate); + ibo->tool.tool.sample =3D inject_bid_offset_tool__sample; + ibo->tool.tool.mmap =3D inject_bid_offset_tool__mmap; + ibo->tool.tool.mmap2 =3D inject_bid_offset_tool__mmap2; + + return &ibo->tool.tool; +} + +void inject_bid_offset_tool__delete(struct perf_tool *tool) +{ + struct delegate_tool *dt; + + if (!tool) + return; + dt =3D container_of(tool, struct delegate_tool, tool); + free(container_of(dt, struct inject_bid_offset_tool, tool)); +} diff --git a/tools/perf/util/inject_bid_offset.h b/tools/perf/util/inject_b= id_offset.h new file mode 100644 index 000000000000..e4cfea255f6b --- /dev/null +++ b/tools/perf/util/inject_bid_offset.h @@ -0,0 +1,21 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef __PERF_INJECT_BID_OFFSET_H +#define __PERF_INJECT_BID_OFFSET_H + +#include + +struct perf_tool; +struct evlist; + +int perf_event__rewrite_attr_for_build_id_offset(struct perf_event_attr *a= ttr); +int perf_event__rewrite_attr_for_sample_ip(struct perf_event_attr *attr); +union perf_event; +struct perf_sample; +struct machine; + +int perf_event__repipe(const struct perf_tool *tool, union perf_event *eve= nt, + struct perf_sample *sample, struct machine *machine); +struct perf_tool *inject_bid_offset_tool__new(struct perf_tool *delegate); +void inject_bid_offset_tool__delete(struct perf_tool *tool); + +#endif /* __PERF_INJECT_BID_OFFSET_H */ --=20 2.55.0.679.g6767b8d81c-goog From nobody Tue Sep 29 13:18:52 2026 Received: from mail-pl1-f198.google.com (mail-pl1-f198.google.com [209.85.214.198]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id B12203B5306 for ; Fri, 7 Aug 2026 07:18:40 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.214.198 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786087122; cv=none; b=TrbMJogJM1J9bXqqc/5f3rpNnXHQQAHjNZSRoWFXUcuJ3mR9vhwdyR9PvBTula9FXF3reJVp10E3QS4GL/UN7hD1Hx5JjUQKd/XuSJyCkxzHOmFDiMqkbMnS1CiF9mdqS3glrcANSjyrs+UM7JoBkgNQHAf614hsO6SWiOemRX0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786087122; c=relaxed/simple; bh=5xQAqmvorxXdNNFmQzGl8mnKvCDu0Bkadw40xjrakYM=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Content-Type; b=HYbLOAR4qvvYG8/tC1C1gpKYjQayrlMRU/OaDQy8rWMTtwJ6zORWiYe8xlWBGsR9oYu8BAklpIFx0rr+nxfBQsB4B/oyv3tS8qPb2woJuCUD/emFlm8ogOpVJIQT25wj6e4jfea8PepmnKYTCTrFG5+EdBp7SIg4ZgqvYn2qJDo= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--irogers.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=WRUlq72G; arc=none smtp.client-ip=209.85.214.198 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--irogers.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="WRUlq72G" Received: by mail-pl1-f198.google.com with SMTP id d9443c01a7336-2cec4226c70so50721635ad.1 for ; Fri, 07 Aug 2026 00:18:40 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20251104; t=1786087120; x=1786691920; darn=vger.kernel.org; h=content-type:to:from:subject:message-id:references:mime-version :in-reply-to:date:from:to:cc:subject:date:message-id:reply-to :content-type; bh=id+6dnzU4I7sg38xB44NTSjVHYaER430HX1yg72oJFQ=; b=WRUlq72G0QxhV5q2yCiFYNvZEOfg95muzH8jPnmMlxDh8rawA6c3VO8HzN3IQE4a3e le6+AYBsEFK61FVsdcPB7a9R3FOEA/uOkbr/EqdOh5L8TR0C8A88T+7wzSRXrTMPf7r7 xUh1E7HBEoE+RHL7Zg4aWG3RoCg57lEy0HFwrYV9cRO6VXqRYdBbAPmogz6aPWj9zJ0f DDHq/7LHtndn0FbPZ8dCUFR2tG9Vave6kg8l1N/JWx8wD/Azs/m5b5c4NFZnnVq1kRcC DkxpBLO5TFQb48HDHfSjx8KSfWLaGQJQMGNsracFrEayzy5oiHIBL7NA1HmOCzH2Tkqc HEvg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1786087120; x=1786691920; h=content-type:to:from:subject:message-id:references:mime-version :in-reply-to:date:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to:content-type; bh=id+6dnzU4I7sg38xB44NTSjVHYaER430HX1yg72oJFQ=; b=pQhBU6TSKSicv4jef6EZnX7dLX0JII+ARjVKnbWQCoYCfakE6vOyJaZ9z2wVhGFmgS 2bIpcl7qv+SJ0MMn/6SaPOr9Fbe+djxjT8FA0wZT22eQHfrwig3TZidxf5DlfLEZhjke WGAmiVKlNkPgXKRnHWgjW2pFYIrVxNA6buuEot3s0PnZdLKrxFbKwdiLfpNcI8DTV9Ft UpxJC8Lfc63elKwgP0zMkuMw7XHxtWXToRA2O+b7GQMORO59sR1UgBFpGlhmScIyqXDV LM/pm05E2wzZLZOWrktMkDK5CljziuUJ54mROlYOMtcs+kjxkuwAxFrqF/nZPTbi4+s5 f0XQ== X-Forwarded-Encrypted: i=1; AHgh+RrNqR/5xlM46G/z6omEaucwGP9drVyZNl75V7f1cXiiA6ReuflumwFpaG943KKSn7NKSgz5uP5I9yZJ8ZQ=@vger.kernel.org X-Gm-Message-State: AOJu0YwNfEC14LtGIP8AzQz1/pVL4w+zwaMCbSyOOfAWwtEhyluvgfz+ Zeav+o+SQ8W4Kv+wnpm/rXBgghgDT8J4yn0Wu2wDiA8wZOmuaeGkyS6wklVIipCuU8Hw8OPycI4 4apacf0cP8g== X-Received: from dybhg52.prod.google.com ([2002:a05:7301:2ab4:b0:30f:4402:de4f]) (user=irogers job=prod-delivery.src-stubby-dispatcher) by 2002:a05:6a21:1fc8:b0:3c4:397a:69ba with SMTP id adf61e73a8af0-3cb85ef8666mr24983360637.28.1786087119621; Fri, 07 Aug 2026 00:18:39 -0700 (PDT) Date: Fri, 7 Aug 2026 00:18:17 -0700 In-Reply-To: <20260807071818.718751-1-irogers@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20260807071818.718751-1-irogers@google.com> X-Mailer: git-send-email 2.55.0.679.g6767b8d81c-goog Message-ID: <20260807071818.718751-8-irogers@google.com> Subject: [RFC PATCH v1 7/8] perf record: Add --buildid-offset option From: Ian Rogers To: Steven Rostedt , Masami Hiramatsu , Alexei Starovoitov , Daniel Borkmann , John Fastabend , Andrii Nakryiko , Eduard Zingerman , Kumar Kartikeya Dwivedi , Martin KaFai Lau , Song Liu , Yonghong Song , Jiri Olsa , Emil Tsalapatis , Peter Zijlstra , Ingo Molnar , Arnaldo Carvalho de Melo , Namhyung Kim , Mark Rutland , Alexander Shishkin , Ian Rogers , Adrian Hunter , James Clark , Suzuki K Poulose , Mike Leach , Leo Yan , John Garry , Will Deacon , Thomas Gleixner , Dapeng Mi , Ravi Bangoria , Swapnil Sapkal , Thomas Falcon , Thomas Richter , Dmitrii Dolgov <9erthalion6@gmail.com>, Eric Biggers , Zecheng Li , Gabriel Marin , Tengda Wu , Derek Foreman , Tanushree Shah , Ankur Arora , Aaron Tomlin , tanze , Rui Qi , Howard Chu , Chuck Lever , Shimin Guo , Alessio Podda , 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 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" 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 --- 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[] =3D { "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 =3D true; } =20 + if (rec->opts.buildid_offset) { + /* Do not drop mmap events here so we can generate build ids later */ + /* rec->opts.synth &=3D ~PERF_SYNTH_MMAP; */ + } + if (rec->opts.record_cgroup && !perf_can_record_cgroup()) { pr_err("Kernel has no cgroup sampling support.\n"); err =3D -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); =20 + 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 |=3D 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; --=20 2.55.0.679.g6767b8d81c-goog From nobody Tue Sep 29 13:18:52 2026 Received: from mail-pj1-f70.google.com (mail-pj1-f70.google.com [209.85.216.70]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 2EBAF3C456F for ; Fri, 7 Aug 2026 07:18:42 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.216.70 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786087125; cv=none; b=QR0aad+2JDO8zteMofReUp3kiv3SYA7y2nqY4zTv/52+LyOQ4LdqbtLKWzY9hEU4XTlhHjKZM2uFCcBgbNKF1NnbC7vZhdw0UQ8haAiFM8zRwDoq2qnOydV5zw153pKkWxk/3hyNyFWOdsM6JGScr3Gi6Nq4gJXTRpq/AoBi9gY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786087125; c=relaxed/simple; bh=LXygP1WyK73KB6sA2epD5GuUK5f4Z9RkXx5rDK/h2YE=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Content-Type; b=UlZSyHvXJGx6V17fzv2RbHpiwnC5E7wzSosP4E3jzo9NCmP3I7e9eLlj3niNSEfCAsFNwe/CsjMWYEkvj4Skd6/bCCnsjEIVERAu/FpPharSQvO3SUazIoA8mNx5976mXbySB+Ihoj1n8dMiN55BKCKd7wgtd0uiEE0BajXo/Oo= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--irogers.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=ez2rKt4M; arc=none smtp.client-ip=209.85.216.70 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--irogers.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="ez2rKt4M" Received: by mail-pj1-f70.google.com with SMTP id 98e67ed59e1d1-38f5ac7416eso3791550a91.3 for ; Fri, 07 Aug 2026 00:18:42 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20251104; t=1786087122; x=1786691922; darn=vger.kernel.org; h=content-type:to:from:subject:message-id:references:mime-version :in-reply-to:date:from:to:cc:subject:date:message-id:reply-to :content-type; bh=D49SGCmwUv9DYtsvbQQXcm3d16lOMTvO3Tc7LhywDzU=; b=ez2rKt4MmwLFXA38N2A+VKKvVw1AVsAnK2aHq2unK7utoxTIo43y+Yxnh2lRcNIM8O su1w4TYoOpRTmkNPlEwLhX+WCpbpEhNHS34WPOehDhd4TFqEP+PvRwglzlXqYAqJ6eGw uCogzQsZ98z+hSvII7BGRRMpKK5ruXiLbU5wP4h7sVzAYJLLbZUXmj61HYcHyIbFV+fp mMjREMF0xxtrWUm2E0D4ddPJIbtc0x9BWOTLOhoqzdCX9BkfYp9McNi/952y8OgyZJDk u0aAgltZNhMkS4xZ/x8Ig33548MI9N2OTqAHvF+K3RXENV9kSFisOKUtb0vYV8aK8RlV H/cw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1786087122; x=1786691922; h=content-type:to:from:subject:message-id:references:mime-version :in-reply-to:date:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to:content-type; bh=D49SGCmwUv9DYtsvbQQXcm3d16lOMTvO3Tc7LhywDzU=; b=fHeTwAfeUWHJMYkom5dBUFyEPOW7EX8IsepcVzWYRs6XA5Jy06bjc+oVutadrFi2Sq mBVe0zhdA66LfIgUMQ3NmAtt+C5dp7j3qMkNjQUfMvUZwv+dU9HVcPAD19PIWe9GFT3b TNj30tVWyCQcPwwNmBgehVMlY9szeNxqM8H5q1ipE2wY8qBHcDUG6iM3SGoBQrsUH/rz r89HdHu6TahQJOcEdonfMxSpVT/obRBlit17GehaEF2CO09W1c54Csaz9sY7tHC9iamY oDHikKZIwfffebrMNk/lGMYePhpm5yGTdORyhQyhSjDcu0qWy/P6Hr2OA2KhZCw4chP7 MCAg== X-Forwarded-Encrypted: i=1; AHgh+RrbbphI31YKu65f80TIWPCicBuqGgRiQmz2Mw3hfi14XjJ5Kio1tO6ZDCAxM15G60cp+0QMQWOTQWM+AT8=@vger.kernel.org X-Gm-Message-State: AOJu0YwdCS6uHyDOaOWjOLhLLOMPFLxPLMCmpHyUiLC7AO0SD918CH+K /3YIeDR7QJpAyGauPGeajXAYpt8NwDxMgmMKnCnOnqFjr/bWEGznexK0GE3Aj5+CfxMc1YJQm7I ODI+xvD90uA== X-Received: from dlah26.prod.google.com ([2002:a05:701b:261a:b0:13d:2928:7996]) (user=irogers job=prod-delivery.src-stubby-dispatcher) by 2002:a17:90b:53cf:b0:37f:b0a9:1a68 with SMTP id 98e67ed59e1d1-3903c54b340mr21304002a91.7.1786087121801; Fri, 07 Aug 2026 00:18:41 -0700 (PDT) Date: Fri, 7 Aug 2026 00:18:18 -0700 In-Reply-To: <20260807071818.718751-1-irogers@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20260807071818.718751-1-irogers@google.com> X-Mailer: git-send-email 2.55.0.679.g6767b8d81c-goog Message-ID: <20260807071818.718751-9-irogers@google.com> Subject: [RFC PATCH v1 8/8] perf tests: Add build_id_offset test coverage From: Ian Rogers To: Steven Rostedt , Masami Hiramatsu , Alexei Starovoitov , Daniel Borkmann , John Fastabend , Andrii Nakryiko , Eduard Zingerman , Kumar Kartikeya Dwivedi , Martin KaFai Lau , Song Liu , Yonghong Song , Jiri Olsa , Emil Tsalapatis , Peter Zijlstra , Ingo Molnar , Arnaldo Carvalho de Melo , Namhyung Kim , Mark Rutland , Alexander Shishkin , Ian Rogers , Adrian Hunter , James Clark , Suzuki K Poulose , Mike Leach , Leo Yan , John Garry , Will Deacon , Thomas Gleixner , Dapeng Mi , Ravi Bangoria , Swapnil Sapkal , Thomas Falcon , Thomas Richter , Dmitrii Dolgov <9erthalion6@gmail.com>, Eric Biggers , Zecheng Li , Gabriel Marin , Tengda Wu , Derek Foreman , Tanushree Shah , Ankur Arora , Aaron Tomlin , tanze , Rui Qi , Howard Chu , Chuck Lever , Shimin Guo , Alessio Podda , 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 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Test the kernel interface using sys_perf_event_open, test perf inject --sample-buildids with pipe mode and callchains, and test perf record --buildid-offset across multiple sampling modes. Signed-off-by: Ian Rogers --- tools/perf/tests/Build | 1 + tools/perf/tests/bid-offset.c | 60 +++++++ tools/perf/tests/builtin-test.c | 1 + tools/perf/tests/mmap-thread-lookup.c | 36 +++++ tools/perf/tests/sample-parsing.c | 37 ++++- tools/perf/tests/shell/inject_bid_offset.sh | 170 ++++++++++++++++++++ tools/perf/tests/shell/record.sh | 69 ++++++++ tools/perf/tests/tests.h | 1 + 8 files changed, 374 insertions(+), 1 deletion(-) create mode 100644 tools/perf/tests/bid-offset.c create mode 100755 tools/perf/tests/shell/inject_bid_offset.sh diff --git a/tools/perf/tests/Build b/tools/perf/tests/Build index 66944a4f4968..f7f8c4deba30 100644 --- a/tools/perf/tests/Build +++ b/tools/perf/tests/Build @@ -64,6 +64,7 @@ perf-test-y +=3D expand-cgroup.o perf-test-y +=3D perf-time-to-tsc.o perf-test-y +=3D dlfilter-test.o perf-test-y +=3D sigtrap.o +perf-test-y +=3D bid-offset.o perf-test-y +=3D event_groups.o perf-test-y +=3D symbols.o perf-test-y +=3D util.o diff --git a/tools/perf/tests/bid-offset.c b/tools/perf/tests/bid-offset.c new file mode 100644 index 000000000000..f7d85491832f --- /dev/null +++ b/tools/perf/tests/bid-offset.c @@ -0,0 +1,60 @@ +// SPDX-License-Identifier: GPL-2.0 +#include "tests.h" +#include "debug.h" +#include "evlist.h" +#include "evsel.h" +#include +#include +#include +#include +#include +#include "../perf-sys.h" + +static int test__bid_offset(struct test_suite *test __maybe_unused, int su= btest __maybe_unused) +{ + struct perf_event_attr attr =3D { + .type =3D PERF_TYPE_SOFTWARE, + .config =3D PERF_COUNT_SW_DUMMY, + .size =3D sizeof(attr), + .sample_type =3D PERF_SAMPLE_BUILD_ID_OFFSET, + .exclude_kernel =3D 1, + .exclude_hv =3D 1, + }; + int fd; + + fd =3D sys_perf_event_open(&attr, /*pid=3D*/0, /*cpu=3D*/-1, /*group_fd= =3D*/-1, /*flags=3D*/0); + if (fd < 0) { + pr_debug("sys_perf_event_open failed with %d\n", errno); + if (errno =3D=3D EINVAL) { + pr_debug("Kernel does not support PERF_SAMPLE_BUILD_ID_OFFSET\n"); + return TEST_SKIP; + } + return TEST_FAIL; + } + close(fd); + + attr.sample_type =3D PERF_SAMPLE_CALLCHAIN_BUILD_ID_OFFSET; + fd =3D sys_perf_event_open(&attr, /*pid=3D*/0, /*cpu=3D*/-1, /*group_fd= =3D*/-1, /*flags=3D*/0); + if (fd < 0) { + pr_debug("sys_perf_event_open with callchain failed with %d\n", errno); + if (errno =3D=3D EINVAL) { + pr_debug("Kernel does not support PERF_SAMPLE_CALLCHAIN_BUILD_ID_OFFSET= \n"); + return TEST_SKIP; + } + return TEST_FAIL; + } + close(fd); + + return TEST_OK; +} + +static struct test_case bid_offset_tests[] =3D { + TEST_CASE_REASON("Test PERF_SAMPLE_BUILD_ID_OFFSET", bid_offset, + "not supported by kernel"), + { .name =3D NULL, } +}; + +struct test_suite suite__bid_offset =3D { + .desc =3D "Test PERF_SAMPLE_BUILD_ID_OFFSET", + .test_cases =3D bid_offset_tests, +}; diff --git a/tools/perf/tests/builtin-test.c b/tools/perf/tests/builtin-tes= t.c index 41dcfbf874f0..afc9c7efe009 100644 --- a/tools/perf/tests/builtin-test.c +++ b/tools/perf/tests/builtin-test.c @@ -148,6 +148,7 @@ static struct test_suite *generic_tests[] =3D { &suite__perf_time_to_tsc, &suite__dlfilter, &suite__sigtrap, + &suite__bid_offset, &suite__event_groups, &suite__symbols, &suite__util, diff --git a/tools/perf/tests/mmap-thread-lookup.c b/tools/perf/tests/mmap-= thread-lookup.c index dca8bbfe780a..65c72ed896ac 100644 --- a/tools/perf/tests/mmap-thread-lookup.c +++ b/tools/perf/tests/mmap-thread-lookup.c @@ -17,6 +17,8 @@ #include "symbol.h" #include "util/synthetic-events.h" #include "thread.h" +#include "dso.h" +#include "build-id.h" #include // page_size =20 #define THREADS 4 @@ -211,6 +213,40 @@ static int mmap_events(synth_cb synth) =20 pr_debug("map %p, addr %" PRIx64 "\n", al.map, map__start(al.map)); =20 + /* Verify lookup by build ID and offset */ + { + struct dso *dso =3D dso__get(map__dso(al.map)); + + if (dso) { + const struct build_id *bid =3D dso__bid(dso); + + if (bid && bid->size > 0) { + struct addr_location al2; + struct perf_build_id pbid =3D { .size =3D bid->size }; + u64 offset =3D map__dso_map_ip(al.map, + (unsigned long)(td->map + 1)); + + memcpy(pbid.data, bid->data, bid->size); + addr_location__init(&al2); + thread__find_map(thread, &(struct perf_sample){ + .cpumode =3D PERF_RECORD_MISC_USER, + .ip =3D 0, + .bid =3D { + .bid =3D &pbid, + .offset =3D offset, + }, + }, &al2); + + if (al2.map !=3D al.map) { + pr_debug("failed, couldn't find map by build id and offset\n"); + err =3D -1; + } + addr_location__exit(&al2); + } + dso__put(dso); + } + } + addr_location__exit(&al); if (err) break; diff --git a/tools/perf/tests/sample-parsing.c b/tools/perf/tests/sample-pa= rsing.c index 20cab91ceaeb..b49b6dcf10cd 100644 --- a/tools/perf/tests/sample-parsing.c +++ b/tools/perf/tests/sample-parsing.c @@ -229,6 +229,36 @@ static int do_test(u64 sample_type, u64 sample_regs, u= 64 read_format) const u32 raw_data[] =3D {0x12345678, 0x0a0b0c0d, 0x11020304, 0x05060708,= 0 }; const u64 data[] =3D {0x2211443366558877ULL, 0, 0xaabbccddeeff4321ULL}; const u64 aux_data[] =3D {0xa55a, 0, 0xeeddee, 0x0282028202820282}; + const struct perf_build_id bid =3D { + .size =3D 20, + .data =3D { + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', + } + }; + const struct perf_build_id callchain_bids[] =3D { + { + .size =3D 20, + .data =3D { + '9', '8', '7', '6', '5', '4', '3', '2', '1', '0', + '9', '8', '7', '6', '5', '4', '3', '2', '1', '0', + } + }, + { + .size =3D 20, + .data =3D { + 'a', 'b', 'c', 'd', 'e', 'f', 'a', 'b', 'c', 'd', + 'e', 'f', 'a', 'b', 'c', 'd', 'e', 'f', 'a', 'b', + } + }, + { + .size =3D 20, + .data =3D { + 'f', 'e', 'd', 'c', 'b', 'a', 'f', 'e', 'd', 'c', + 'b', 'a', 'f', 'e', 'd', 'c', 'b', 'a', 'f', 'e', + } + }, + }; struct regs_dump user_regs =3D { .abi =3D PERF_SAMPLE_REGS_ABI_64, .mask =3D sample_regs, @@ -277,6 +307,11 @@ static int do_test(u64 sample_type, u64 sample_regs, u= 64 read_format) .size =3D sizeof(aux_data), .data =3D (void *)aux_data, }, + .bid =3D { + .bid =3D (struct perf_build_id *)&bid, + .offset =3D 0, + }, + .callchain_bids =3D (struct perf_build_id *)callchain_bids, }; struct sample_read_value values[] =3D {{1, 5, 0}, {9, 3, 0}, {2, 7, 0}, {= 6, 4, 1},}; struct perf_sample sample_out, sample_out_endian; @@ -409,7 +444,7 @@ static int test__sample_parsing(struct test_suite *test= __maybe_unused, int subt * were added. Please actually update the test rather than just change * the condition below. */ - if (PERF_SAMPLE_MAX > PERF_SAMPLE_WEIGHT_STRUCT << 1) { + if (PERF_SAMPLE_WEIGHT_STRUCT << 3 < PERF_SAMPLE_MAX) { pr_debug("sample format has changed, some new PERF_SAMPLE_ bit was intro= duced - test needs updating\n"); return -1; } diff --git a/tools/perf/tests/shell/inject_bid_offset.sh b/tools/perf/tests= /shell/inject_bid_offset.sh new file mode 100755 index 000000000000..eac0a19f24e1 --- /dev/null +++ b/tools/perf/tests/shell/inject_bid_offset.sh @@ -0,0 +1,170 @@ +#!/bin/bash +# SPDX-License-Identifier: GPL-2.0 +# perf inject --sample-buildids test + +set -e +set -o pipefail + +shelldir=3D$(dirname "$0") +# shellcheck source=3Dlib/perf_has_symbol.sh +. "${shelldir}"/lib/perf_has_symbol.sh + +sym=3D"noploop" + +skip_test_missing_symbol ${sym} + +temp_dir=3D$(mktemp -d /tmp/perf-test-bid-offset.XXXXXXXXXX) + +prog=3D"perf test -w noploop" +[ "$(uname -m)" =3D "s390x" ] && prog=3D"$prog 3" +err=3D0 + +cleanup() { + local exit_code=3D${1:-$?} + trap - EXIT TERM INT + if [ "${exit_code}" -ne 0 ] || [ "${err}" -ne 0 ]; then + echo "Test failed! Preserving temp directory: ${temp_dir}" + exit 1 + fi + if [[ "${temp_dir}" =3D~ ^/tmp/perf-test-bid-offset\. ]]; then + rm -rf "${temp_dir}" + fi + exit 0 +} + +trap_cleanup() { + local exit_code=3D$? + echo "Unexpected signal in ${FUNCNAME[1]}" + cleanup ${exit_code} +} +trap trap_cleanup EXIT TERM INT + +compare_script() { + local orig=3D$1 + local bid=3D$2 + local msg=3D$3 + + perf script -F -ip -i "${orig}" > "${temp_dir}/script_orig.txt" + perf script -F -ip -i "${bid}" > "${temp_dir}/script_bid.txt" + + if ! diff -q "${temp_dir}/script_orig.txt" "${temp_dir}/script_bid.txt"; = then + echo "${msg} [Failed - perf script output differs]" + err=3D1 + else + echo "${msg} [Success]" + fi +} + +compare_report() { + local orig=3D$1 + local bid=3D$2 + local msg=3D$3 + + perf report -i "${orig}" --stdio | grep -v '^#' > "${temp_dir}/report_ori= g.txt" + perf report -i "${bid}" --stdio | grep -v '^#' > "${temp_dir}/report_bid.= txt" + + if ! diff -q "${temp_dir}/report_orig.txt" "${temp_dir}/report_bid.txt"; = then + echo "${msg} [Failed - perf report output differs]" + err=3D1 + else + echo "${msg} [Success]" + fi +} + +test_basic() { + echo "Test basic build id offset injection" + local data=3D"${temp_dir}/perf.data.basic" + local data2=3D"${temp_dir}/perf.data2.basic" + + perf record -e task-clock:u -o "${data}" ${prog} >/dev/null 2>&1 + perf inject --sample-buildids -i "${data}" -o "${data2}" >/dev/null 2>&1 + + compare_script "${data}" "${data2}" "Basic injection" +} + +test_callchain() { + echo "Test Callchain build id offset injection" + local data=3D"${temp_dir}/perf.data.callchain" + local data2=3D"${temp_dir}/perf.data2.callchain" + + perf record -g -e task-clock:u -o "${data}" ${prog} >/dev/null 2>&1 + perf inject --sample-buildids -i "${data}" -o "${data2}" >/dev/null 2>&1 + + compare_script "${data}" "${data2}" "Callchain injection" +} + +test_pipe() { + echo "Test pipe mode build id offset injection" + local data=3D"${temp_dir}/perf.data.pipe" + local data2=3D"${temp_dir}/perf.data2.pipe" + + perf record -e task-clock:u -o - ${prog} 2>/dev/null | tee "${data}" | \ + perf inject --sample-buildids -o "${data2}" >/dev/null 2>&1 + + compare_script "${data}" "${data2}" "Pipe mode injection" +} + +test_report() { + echo "Test perf report consistency" + local data=3D"${temp_dir}/perf.data.report" + local data2=3D"${temp_dir}/perf.data2.report" + + perf record -e task-clock:u -o "${data}" ${prog} >/dev/null 2>&1 + perf inject --sample-buildids -i "${data}" -o "${data2}" >/dev/null 2>&1 + + compare_report "${data}" "${data2}" "Report consistency" +} + +test_pipe_report() { + echo "Test pipe mode perf report consistency" + local data=3D"${temp_dir}/perf.data.pipe_report" + local data2=3D"${temp_dir}/perf.data2.pipe_report" + + perf record -e task-clock:u -o - ${prog} 2>/dev/null | tee "${data}" | \ + perf inject --sample-buildids -o "${data2}" >/dev/null 2>&1 + + compare_report "${data}" "${data2}" "Pipe Report consistency" +} + +test_kernel() { + echo "Test kernel build id offset injection" + local data=3D"${temp_dir}/perf.data.kernel" + local data2=3D"${temp_dir}/perf.data2.kernel" + + # Not all systems allow kernel profiling, so we check if it succeeds first + if ! perf record -e task-clock:k -o "${data}" ${prog} >/dev/null 2>&1; th= en + echo "Kernel injection [Skipped - permissions or support missing]" + return + fi + perf inject --sample-buildids -i "${data}" -o "${data2}" >/dev/null 2>&1 + + compare_script "${data}" "${data2}" "Kernel injection" +} + +test_record_buildid_offset() { + echo "Test perf record --buildid-offset consistency" + local data=3D"${temp_dir}/perf.data.record_orig" + local data2=3D"${temp_dir}/perf.data2.record_bid" + + perf record -e task-clock:u -o "${data}" ${prog} >/dev/null 2>&1 + # We must have the binaries in .build-id cache, which the first record do= es natively. + # Now record with --buildid-offset. + if ! perf record --buildid-offset -e task-clock:u -o "${data2}" \ + ${prog} >/dev/null 2>&1; then + echo "Record --buildid-offset consistency [Skipped - not supported by ke= rnel]" + return + fi + + # Compare symbolization + compare_report "${data}" "${data2}" "Record --buildid-offset consistency" +} + +test_basic +test_callchain +test_pipe +test_report +test_pipe_report +test_kernel +test_record_buildid_offset + +cleanup ${err} diff --git a/tools/perf/tests/shell/record.sh b/tools/perf/tests/shell/reco= rd.sh index 625240809fce..9346741b19c9 100755 --- a/tools/perf/tests/shell/record.sh +++ b/tools/perf/tests/shell/record.sh @@ -484,6 +484,74 @@ test_ratio_to_prev() { echo "Basic ratio-to-prev record test [Success]" } =20 +check_buildid_offset() { + perf report -D -i "${perfdata}" -q 2>/dev/null | grep -q "BUILD_ID_OFFSE= T" +} + +test_buildid_offset() { + echo "buildid-offset test" + local ret=3D0 + perf_record_with_retry "${perfdata}" "check_buildid_offset" "perf test -= w thloop" \ + --buildid-offset || ret=3D$? + if [ $ret -eq 2 ]; then + echo "buildid-offset test [Skipped not supported]" + return + elif [ $ret -eq 1 ]; then + echo "buildid-offset test [Failed missing output]" + err=3D1 + return + fi + + # Expand test coverage + perf_record_with_retry "${perfdata}" "check_per_thread" "perf test -w th= loop" \ + --buildid-offset --per-thread || ret=3D$? + if [ $ret -ne 0 ]; then + echo "buildid-offset test [Failed per-thread]" + err=3D1 + return + fi + + perf_record_with_retry "${perfdata}" "check_system_wide" "perf test -w t= hloop" \ + --buildid-offset -aB --synth=3Dno || ret=3D$? + if [ $ret -ne 0 ]; then + echo "buildid-offset test [Failed system-wide]" + err=3D1 + return + fi + + perf_record_with_retry "${perfdata}" "check_workload" "perf test -w thlo= op" \ + --buildid-offset || ret=3D$? + if [ $ret -ne 0 ]; then + echo "buildid-offset test [Failed workload]" + err=3D1 + return + fi + + case $(uname -m) + in s390x) + cmd_flags=3D"--call-graph dwarf -e cpu-clock";; + *) + cmd_flags=3D"-g";; + esac + + if ! perf record --buildid-offset -o "${perfdata}" $cmd_flags \ + perf test -w brstack > /dev/null 2>&1 + then + echo "buildid-offset test [Failed callgraph record]" + err=3D1 + return + fi + + if ! perf report -i "${perfdata}" 2>&1 | grep -q "${testsym2}" + then + echo "buildid-offset test [Failed callgraph missing symbol]" + err=3D1 + return + fi + + echo "buildid-offset test [Success]" +} + # raise the limit of file descriptors to minimum if [[ $default_fd_limit -lt $min_fd_limit ]]; then ulimit -Sn $min_fd_limit @@ -502,6 +570,7 @@ test_precise_max test_callgraph test_acr_sampling test_ratio_to_prev +test_buildid_offset =20 # restore the default value ulimit -Sn $default_fd_limit diff --git a/tools/perf/tests/tests.h b/tools/perf/tests/tests.h index cee9e6b62dcc..b718ae148245 100644 --- a/tools/perf/tests/tests.h +++ b/tools/perf/tests/tests.h @@ -176,6 +176,7 @@ DECLARE_SUITE(expand_cgroup_events); DECLARE_SUITE(perf_time_to_tsc); DECLARE_SUITE(dlfilter); DECLARE_SUITE(sigtrap); +DECLARE_SUITE(bid_offset); DECLARE_SUITE(event_groups); DECLARE_SUITE(symbols); DECLARE_SUITE(util); --=20 2.55.0.679.g6767b8d81c-goog