From: Ian Rogers <irogers@google.com>
To: Peter Zijlstra <peterz@infradead.org>,
Ingo Molnar <mingo@redhat.com>,
Arnaldo Carvalho de Melo <acme@kernel.org>,
Namhyung Kim <namhyung@kernel.org>
Cc: Jiri Olsa <jolsa@kernel.org>, Ian Rogers <irogers@google.com>,
Adrian Hunter <adrian.hunter@intel.com>,
James Clark <james.clark@linaro.org>,
linux-perf-users@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: [PATCH v1 00/26] perf hashmap: Fix undefined behavior, remove ERR_PTR, and add type-safe generic hashmaps
Date: Fri, 13 Nov 2026 13:48:24 -0800 [thread overview]
Message-ID: <20261113214850.3329699-1-irogers@google.com> (raw)
Currently tools/perf/util/hashmap.{c,h} is a copy of libbpf's internal
untyped struct hashmap (only compiled when libbpf is disabled or
dynamically linked, and otherwise resolved against static libbpf.a).
Using that implementation in perf has several longstanding problems:
1. Strict-aliasing undefined behavior: hashmap_cast_ptr(p) casts caller
output pointers (such as void **, struct foo **, or long *) to long *
and dereferences them in hashmap_insert(), hashmap_find(), and
hashmap_delete(), violating C11 6.5/7 strict-aliasing rules [1] and
preventing perf from dropping -fno-strict-aliasing [2].
2. Non-standard ERR_PTR() returns: hashmap__new() returns
ERR_PTR(-ENOMEM) rather than NULL with errno, which differs from the
rest of user-space perf and has repeatedly caused NULL vs IS_ERR()
bugs (e.g. commits d05073adda0f, 96f202eab813, 9f3c16a430e8, and [3],
plus missing error checks in fncache and pmu fixed here).
3. No compile-time type safety and error-prone iteration/deletion: keys
and values are untyped long / void * unions requiring manual casts,
sub-long types (such as bool, int, or pid_t) cannot be passed safely
as output pointers, hashmap__for_each_entry() uses nested loops where
'break' only exits a single bucket chain rather than the whole
iteration, and hashmap__delete() leaves old_key/old_value untouched
on a miss (unlike hashmap__insert()).
This series fixes three bugs in existing hashmap callers, decouples
perf's hashmap from libbpf so strict-aliasing and ERR_PTR issues can be
fixed cleanly, introduces a zero-overhead type-safe DECLARE_HASHMAP()
generic hashmap API, migrates all 17 hashmaps across tools/perf one at a
time while keeping every commit bisectable, and removes the untyped
struct hashmap API at the end:
- Standalone bug fixes in existing callers (Patches 1-3):
- Patch 1 fixes an uninitialized pointer passed to thread__put() in
util/threads.c when hashmap__delete() misses (Fixes: 412a2ff473ac).
- Patch 2 fixes a sym_hist_entry memory leak in
symbol__annotate_zero_histograms() when clearing notes->src->samples
(Fixes: d3e7cad6f36d).
- Patch 3 fixes a per_pkg_mask key leak in check_per_pkg() when
hashmap__add() fails (Fixes: 034f7ee130c1).
- Decoupling from libbpf, strict-aliasing fix, and ERR_PTR removal
(Patches 4-7):
- Patches 4-5 drop the check-headers.sh diff check against
tools/lib/bpf/hashmap.{c,h}, always build util/hashmap.o, and move
the backing C functions to __hashmap__* so static libbpf.a builds do
not collide on global hashmap* symbols (and without perf_-specific
naming so other tools/ users can share the implementation).
- Patch 6 fixes strict-aliasing violations by passing void * output
parameters to __hashmap__insert(), __hashmap__find(), and
__hashmap__delete(), accessing them via memcpy()/memset(), and
zeroing old_key/old_value on miss in __hashmap__delete().
- Patch 7 replaces ERR_PTR(-ENOMEM) in hashmap__new() with NULL and
errno = ENOMEM, updating callers to standard NULL checks.
- Type-safe generic hashmap API and per-caller migrations (Patches 8-26):
- Patch 8 introduces DECLARE_HASHMAP(name, key_type, value_type) and
type-checked hashmap__* macros around struct __hashmap:
* Phantom pointer members (__key, __value) in a union with struct
__hashmap encode key and value types at zero runtime space cost
and without altering struct size or alignment.
* Output parameters (value_ptr, old_key, old_value) are marshaled
through long temporaries and assigned via the declared types so
sub-long types (bool, int, pid_t, etc.) are safe from stack
overflows, endianness bugs, and strict-aliasing violations, while
accepting NULL output pointers and const-qualified lookup keys.
* Single-loop hashmap__for_each{,_safe}() and
hashmap__for_each_key{,_safe}() iterators hide bucket cursors,
make in-loop deletion safe, and allow 'break' to exit the entire
iteration.
* Adds kernel-doc comments and a 'Generic hashmap' perf test suite
in tests/hashmap.c.
- Patches 9-25 migrate all 17 hashmaps in tools/perf (fncache, ftrace,
trace syscall_stats, bpf-trace-summary, bpf_lock_contention, stat
per_pkg_mask, expr_ids, pmu aliases, hwmon_pmu, s390-sample-raw,
threads, annotate sym_samples and type_hash, annotate-data, and
inject --aslr maps) one hashmap per commit.
- Patch 26 removes the transitional untyped struct hashmap wrapper and
unused hashmap__for_each_entry* macros.
[1] https://lore.kernel.org/lkml/20260321024446.692008-1-irogers@google.com/
[2] https://lore.kernel.org/lkml/20260320224248.536449-1-irogers@google.com/
[3] https://lore.kernel.org/lkml/20250805063209.3678359-1-linmq006@gmail.com/
AI Assistance Disclosure (per Documentation/process/coding-assistants.rst
and Documentation/process/generated-content.rst):
- Tools used: Google Antigravity / Jetski coding assistant.
- Summary of prompts and assistance: Interactive design, rebasing, and
refinement of the __hashmap__* backing separation, strict-aliasing and
ERR_PTR fixes, caller bug fixes, DECLARE_HASHMAP() type-safe macros,
kernel-doc comments, unit tests, and per-hashmap caller conversions.
- Testing performed: Verified all 26 commits build cleanly at every step
under both GCC (-O2 -fstrict-aliasing -Wstrict-aliasing=3) and Clang
(BUILD_NONDISTRO=1), plus NO_LIBBPF=1, DEBUG=1 (REFCNT_CHECKING=1),
and build-test targets; ran perf test (including Generic hashmap,
Simple expression parser, Sysfs/JSON PMU, Hwmon PMU, Symbols, data
type profiling, inject --aslr, stat, ftrace, and trace suites),
scripts/kernel-doc -Werror, and scripts/checkpatch.pl.
Ian Rogers (26):
perf threads: Fix uninitialized pointer put when thread removal misses
perf annotate: Fix sym_hist_entry memory leak when zeroing histograms
perf stat: Fix per_pkg_mask key leak on hashmap__add failure
perf build: Don't check difference of perf and libbpf hashmap
perf hashmap: Always build perf's hashmap and avoid libbpf symbol
conflict
perf hashmap: Fix strict aliasing violations in hashmap
perf hashmap: Remove errptr usage from hashmap
perf hashmap: Introduce generic types and macros
perf fncache: Use generic hashmap for fncache
perf ftrace: Use generic hashmap for profile_hash
perf trace: Use generic hashmap for syscall_stats
perf trace: Use generic hashmap for bpf-trace-summary
perf lock: Use generic hashmap for slab_hash
perf stat: Use generic hashmap for per_pkg_mask
perf expr: Use generic hashmap for expr_ids
perf pmu: Use generic hashmap for pmu aliases
perf hwmon_pmu: Use generic hashmap for hwmon events
perf s390: Use generic hashmap for counter name cache
perf threads: Use generic hashmap for thread shards
perf annotate: Use generic hashmap for sym_samples
perf annotate: Use generic hashmap for browser type_hash
perf annotate-data: Use generic hashmap for type_hist samples
perf inject: Use generic hashmap for aslr remap_addresses
perf inject: Use generic hashmap for aslr top_addresses
perf inject: Use generic hashmap for aslr evsel_orig_attrs
perf hashmap: Remove untyped struct hashmap API
tools/perf/builtin-ftrace.c | 52 ++-
tools/perf/builtin-trace.c | 45 +-
tools/perf/check-headers.sh | 4 -
tools/perf/tests/Build | 1 +
tools/perf/tests/builtin-test.c | 1 +
tools/perf/tests/expr.c | 2 +-
tools/perf/tests/hashmap.c | 192 ++++++++
tools/perf/tests/pmu-events.c | 16 +-
tools/perf/tests/tests.h | 1 +
tools/perf/ui/browsers/annotate.c | 22 +-
tools/perf/util/Build | 9 -
tools/perf/util/annotate-data.c | 10 +-
tools/perf/util/annotate-data.h | 5 +-
tools/perf/util/annotate.c | 30 +-
tools/perf/util/annotate.h | 13 +-
tools/perf/util/aslr.c | 48 +-
tools/perf/util/bpf-trace-summary.c | 18 +-
tools/perf/util/bpf_lock_contention.c | 12 +-
tools/perf/util/evsel.c | 10 +-
tools/perf/util/evsel.h | 6 +-
tools/perf/util/expr.c | 106 ++---
tools/perf/util/expr.h | 18 +-
tools/perf/util/expr.y | 2 +-
tools/perf/util/fncache.c | 23 +-
tools/perf/util/ftrace.h | 7 +-
tools/perf/util/hashmap.c | 136 +++---
tools/perf/util/hashmap.h | 627 ++++++++++++++++++++------
tools/perf/util/hwmon_pmu.c | 57 ++-
tools/perf/util/metricgroup.c | 28 +-
tools/perf/util/pmu.c | 36 +-
tools/perf/util/pmu.h | 7 +-
tools/perf/util/s390-sample-raw.c | 9 +-
tools/perf/util/stat.c | 13 +-
tools/perf/util/threads.c | 26 +-
tools/perf/util/threads.h | 4 +-
35 files changed, 1092 insertions(+), 504 deletions(-)
create mode 100644 tools/perf/tests/hashmap.c
base-commit: 4af65363b11fc4fe65fcb497f68bbe4f3e3a4d2c
--
2.56.1.703.gf848ed807c-goog
next reply other threads:[~2026-11-13 21:49 UTC|newest]
Thread overview: 53+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-11-13 21:48 Ian Rogers [this message]
2026-11-13 21:48 ` [PATCH v1 01/26] perf threads: Fix uninitialized pointer put when thread removal misses Ian Rogers
2026-11-13 21:56 ` sashiko-bot
2026-11-13 21:48 ` [PATCH v1 02/26] perf annotate: Fix sym_hist_entry memory leak when zeroing histograms Ian Rogers
2026-11-13 21:59 ` sashiko-bot
2026-11-13 21:48 ` [PATCH v1 03/26] perf stat: Fix per_pkg_mask key leak on hashmap__add failure Ian Rogers
2026-11-13 21:55 ` sashiko-bot
2026-11-13 21:48 ` [PATCH v1 04/26] perf build: Don't check difference of perf and libbpf hashmap Ian Rogers
2026-11-13 21:54 ` sashiko-bot
2026-11-13 21:48 ` [PATCH v1 05/26] perf hashmap: Always build perf's hashmap and avoid libbpf symbol conflict Ian Rogers
2026-11-13 21:55 ` sashiko-bot
2026-11-13 21:48 ` [PATCH v1 06/26] perf hashmap: Fix strict aliasing violations in hashmap Ian Rogers
2026-11-13 21:56 ` sashiko-bot
2026-11-13 21:48 ` [PATCH v1 07/26] perf hashmap: Remove errptr usage from hashmap Ian Rogers
2026-11-13 22:01 ` sashiko-bot
2026-11-13 21:48 ` [PATCH v1 08/26] perf hashmap: Introduce generic types and macros Ian Rogers
2026-11-13 22:01 ` sashiko-bot
2026-11-13 21:48 ` [PATCH v1 09/26] perf fncache: Use generic hashmap for fncache Ian Rogers
2026-11-13 21:56 ` sashiko-bot
2026-11-13 21:48 ` [PATCH v1 10/26] perf ftrace: Use generic hashmap for profile_hash Ian Rogers
2026-11-13 21:57 ` sashiko-bot
2026-11-13 21:48 ` [PATCH v1 11/26] perf trace: Use generic hashmap for syscall_stats Ian Rogers
2026-11-13 22:04 ` sashiko-bot
2026-11-13 21:48 ` [PATCH v1 12/26] perf trace: Use generic hashmap for bpf-trace-summary Ian Rogers
2026-11-13 21:58 ` sashiko-bot
2026-11-13 21:48 ` [PATCH v1 13/26] perf lock: Use generic hashmap for slab_hash Ian Rogers
2026-11-13 21:57 ` sashiko-bot
2026-11-13 21:48 ` [PATCH v1 14/26] perf stat: Use generic hashmap for per_pkg_mask Ian Rogers
2026-11-13 21:57 ` sashiko-bot
2026-11-13 21:48 ` [PATCH v1 15/26] perf expr: Use generic hashmap for expr_ids Ian Rogers
2026-11-13 22:02 ` sashiko-bot
2026-11-13 21:48 ` [PATCH v1 16/26] perf pmu: Use generic hashmap for pmu aliases Ian Rogers
2026-11-13 22:04 ` sashiko-bot
2026-11-13 21:48 ` [PATCH v1 17/26] perf hwmon_pmu: Use generic hashmap for hwmon events Ian Rogers
2026-11-13 21:58 ` sashiko-bot
2026-11-13 21:48 ` [PATCH v1 18/26] perf s390: Use generic hashmap for counter name cache Ian Rogers
2026-11-13 21:59 ` sashiko-bot
2026-11-13 21:48 ` [PATCH v1 19/26] perf threads: Use generic hashmap for thread shards Ian Rogers
2026-11-13 22:01 ` sashiko-bot
2026-11-13 21:48 ` [PATCH v1 20/26] perf annotate: Use generic hashmap for sym_samples Ian Rogers
2026-11-13 22:08 ` sashiko-bot
2026-11-13 21:48 ` [PATCH v1 21/26] perf annotate: Use generic hashmap for browser type_hash Ian Rogers
2026-11-13 21:59 ` sashiko-bot
2026-11-13 21:48 ` [PATCH v1 22/26] perf annotate-data: Use generic hashmap for type_hist samples Ian Rogers
2026-11-13 22:00 ` sashiko-bot
2026-11-13 21:48 ` [PATCH v1 23/26] perf inject: Use generic hashmap for aslr remap_addresses Ian Rogers
2026-11-13 21:59 ` sashiko-bot
2026-11-13 21:48 ` [PATCH v1 24/26] perf inject: Use generic hashmap for aslr top_addresses Ian Rogers
2026-11-13 21:59 ` sashiko-bot
2026-11-13 21:48 ` [PATCH v1 25/26] perf inject: Use generic hashmap for aslr evsel_orig_attrs Ian Rogers
2026-11-13 22:00 ` sashiko-bot
2026-11-13 21:48 ` [PATCH v1 26/26] perf hashmap: Remove untyped struct hashmap API Ian Rogers
2026-11-13 22:01 ` sashiko-bot
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20261113214850.3329699-1-irogers@google.com \
--to=irogers@google.com \
--cc=acme@kernel.org \
--cc=adrian.hunter@intel.com \
--cc=james.clark@linaro.org \
--cc=jolsa@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-perf-users@vger.kernel.org \
--cc=mingo@redhat.com \
--cc=namhyung@kernel.org \
--cc=peterz@infradead.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox