[PATCH] perf buildid-list: Fix empty output for AUX data

From: James Clark

Date: Tue Sep 22 2026 - 10:55:56 EST


perf record enables buildid_all for AUX trace because buildid-list does
not decode AUX data to identify hit DSOs. Historically those build IDs
were available in HEADER_BUILD_ID, and buildid-list disabled hit
filtering when HEADER_AUXTRACE was present.

Build IDs are now carried by MMAP2 records by default and the build-ID
header is omitted. perf_session__list_build_ids() forces with_hits when
the header is absent so that it processes the event stream. That also
filters the result to DSOs referenced by ordinary samples. AUX data has
no such samples unless the trace is decoded, so every DSO is dropped and
perf archive reports that no build IDs were found.

Process the event stream whenever the build-ID header is absent,
allowing MMAP2 build IDs to be read, but do not enable hit filtering for
AUX data, this ensures that all build-IDs are included for AUX data.

Fixes: 6bd89ae7d147 ("perf record: Make sure to update build-ID cache")
Assisted-by: Codex:GPT-5.6-Sol
Signed-off-by: James Clark <james.clark@xxxxxxxxxx>
---
tools/perf/builtin-buildid-list.c | 17 +++++++++++++----
1 file changed, 13 insertions(+), 4 deletions(-)

diff --git a/tools/perf/builtin-buildid-list.c b/tools/perf/builtin-buildid-list.c
index e0881b0ac38f..5555f5dcefe4 100644
--- a/tools/perf/builtin-buildid-list.c
+++ b/tools/perf/builtin-buildid-list.c
@@ -87,6 +87,7 @@ static bool dso__skip_buildid(struct dso *dso, int with_hits)
static int perf_session__list_build_ids(bool force, bool with_hits)
{
struct perf_session *session;
+ bool has_auxtrace, has_build_id;
struct perf_data data = {
.path = input_name,
.mode = PERF_DATA_MODE_READ,
@@ -118,11 +119,19 @@ static int perf_session__list_build_ids(bool force, bool with_hits)
* We take all buildids when the file contains AUX area tracing data
* because we do not decode the trace because it would take too long.
*/
- if (!perf_data__is_pipe(&data) &&
- perf_header__has_feat(&session->header, HEADER_AUXTRACE))
+ has_auxtrace = !perf_data__is_pipe(&data) &&
+ perf_header__has_feat(&session->header, HEADER_AUXTRACE);
+ has_build_id = perf_header__has_feat(&session->header, HEADER_BUILD_ID);
+
+ if (has_auxtrace)
with_hits = false;

- if (!perf_header__has_feat(&session->header, HEADER_BUILD_ID))
+ /*
+ * Without a build-ID header, the event stream is processed below to find
+ * build IDs in MMAP2 records. For AUX data keep all DSOs because the trace
+ * is not decoded and consequently none of them can be marked as hit.
+ */
+ if (!has_build_id && !has_auxtrace)
with_hits = true;

if (zstd_init(&(session->zstd_data), 0) < 0)
@@ -132,7 +141,7 @@ static int perf_session__list_build_ids(bool force, bool with_hits)
* in pipe-mode, the only way to get the buildids is to parse
* the record stream. Buildids are stored as RECORD_HEADER_BUILD_ID
*/
- if (with_hits || perf_data__is_pipe(&data))
+ if (with_hits || perf_data__is_pipe(&data) || !has_build_id)
perf_session__process_events(session);

perf_session__fprintf_dsos_buildid(session, stdout, dso__skip_buildid, with_hits);

---
base-commit: edd8a9fe2eca009599e013a29c421c7a6b5ad1b9
change-id: 20260922-james-perf-aux-archive-4c00c7943487

Best regards,
--
James Clark <james.clark@xxxxxxxxxx>