Port event_analyzing_sample.py to a standalone script in
tools/perf/python/ using the perf module and standard library sqlite3
module.
Improvements compared to the legacy script:
- Encapsulate database state in a _DB container instead of mutating
module-level globals, and ensure temporary SQLite database files are
cleaned up on exit.
- Add argparse CLI options (-i/--input and -d/--db) while preserving
PerfEvent, PebsEvent, and PebsNHM binary raw_buf unpacking and
symbol/DSO histogram reporting.
- Remove Python 2 compatibility code and add type annotations.
Add a shell test (test_event_analyzing_sample_python.sh) to verify the
standalone script.
Assisted-by: Antigravity:gemini-3.1-pro
Signed-off-by: Ian Rogers <irogers@google.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Port gecko.py to a standalone script in tools/perf/python/ that uses
the perf module directly to convert perf.data profiles into Firefox
Gecko profile format.
Improvements compared to the legacy script:
- Encapsulate profiler state in GeckoCLI and CategoryData classes with
full type annotations, removing global variables.
- Harden the local HTTP server in _write_and_launch(): write the
temporary profile to an isolated tempfile.TemporaryDirectory() with a
randomized UUID filename instead of the current working directory,
bind HTTPServer exclusively to 127.0.0.1 on an OS-assigned ephemeral
port (0), restrict CORS Access-Control-Allow-Origin to
'https://profiler.firefox.com' instead of '*', and restrict HTTP GET
requests exclusively to the randomized profile filename (returning
HTTP 403 for directory listings and any other path).
- Add -i/--input and -e/--event CLI options via argparse.
Add a shell test (test_gecko_python.sh) to verify the standalone script.
Assisted-by: Antigravity:gemini-3.1-pro
Signed-off-by: Ian Rogers <irogers@google.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Port flamegraph.py to a standalone script in tools/perf/python/ that
uses the perf module directly, avoiding intermediate dictionary
allocations for event fields.
Improvements compared to the legacy script:
- Add Subresource Integrity (integrity="sha256-...") and
crossorigin="anonymous" attributes to external CDN stylesheet and
script tags in MINIMAL_HTML.
- Upgrade CDN HTML template hash verification from weak MD5
(hashlib.md5) to cryptographic SHA-256 (hashlib.sha256).
- Escape '<', '>', and '&' ('\u003c', '\u003e', '\u0026') in embedded
JSON payloads (stacks_json and options_json) to prevent HTML script
injection / XSS when rendering untrusted symbol or command names.
- Skip invoking 'perf report --header-only' when the input is stdin
('-'), a FIFO pipe, or a character device (S_ISFIFO / S_ISCHR) so
non-seekable streams do not hang or fail.
Add a shell test (test_flamegraph_python.sh) to verify the standalone
script.
Assisted-by: Antigravity:gemini-3.1-pro
Signed-off-by: Ian Rogers <irogers@google.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Port stackcollapse.py from tools/perf/scripts/python/ to a standalone
script in tools/perf/python/ refactored into a StackCollapseAnalyzer
class.
Improvements compared to the legacy script:
- Traverse sample.callchain directly from perf.session without
allocating per-event dictionaries, and fall back to sample.symbol when
a sample has no callchain.
- Replace deprecated optparse with argparse, adding -i/--input alongside
--include-tid, --include-pid, --no-comm, --tidy-java, and --kernel.
- Handle BrokenPipeError cleanly when output is piped into downstream
tools (such as head or flamegraph.pl).
Add a shell test (test_stackcollapse_python.sh) using a CPU workload
(perf test -w noploop) to verify the standalone script.
Assisted-by: Antigravity:gemini-3.1-pro
Signed-off-by: Ian Rogers <irogers@google.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Port mem-phys-addr.py to a standalone script in tools/perf/python/
using the perf.session API to read perf.data files and profile physical
memory access types against /proc/iomem.
Improvements compared to the legacy script:
- Parse the full indentation hierarchy of /proc/iomem into a parent-child
tree of frozen IomemEntry dataclasses (instead of only top-level
indent-0 ranges), resolving physical addresses to the most specific
sub-range (such as Kernel code/data/bss inside System RAM) and rolling
child counts up into parent totals.
- Support profiling multiple memory events in a single perf.data session
(keyed by evsel name) instead of assuming a single global event.
- Add argparse CLI options (-i/--input and --iomem to allow supplying an
offline /proc/iomem snapshot from a target system).
Add a shell test (test_mem_phys_addr_python.sh) to verify the standalone
script.
Assisted-by: Antigravity:gemini-3.1-pro
Signed-off-by: Ian Rogers <irogers@google.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Port stat-cpi.py from the legacy embedded scripting framework to a
standalone Python script in tools/perf/python/ to calculate Cycles Per
Instruction (CPI) per interval per CPU or thread.
Improvements compared to the legacy script:
- Support both perf.data file mode (via perf.session stat callbacks)
and live counter collection mode (using perf.parse_events,
evlist.open, and evsel.read across intervals), with automatic fallback
to user-space (:u) and self-process monitoring when perf_event_paranoid
restricts system-wide events (EACCES).
- Compute per-interval counter deltas (val, ena, run) keyed by raw event
name so cumulative PERF_RECORD_STAT snapshots and hybrid PMU events
(e.g. cpu_core/cycles/, cpu_atom/cycles/) are accumulated accurately,
and scale counts by time_enabled / time_running when multiplexed.
- Replace hard-coded CPU ([0, 1]) and thread ([0]) arrays with dynamic
CPU and thread discovery so arbitrary system topologies work
automatically.
- Add CLI option handling (-i, -I, -p) via argparse and type annotations
passing mypy and pylint.
Add a shell test (test_stat_cpi_python.sh) to verify the standalone
script.
Assisted-by: Antigravity:gemini-3.1-pro
Signed-off-by: Ian Rogers <irogers@google.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Install the newly ported standalone Python scripts (python/*.py), type
stubs (python/perf.pyi), and compiled perf Python extension module
(python/perf*.so, when built) into $(perfexec_instdir_SQ)/python
alongside the legacy scripts during the transition phase so that newly
ported scripts can import perf directly from the installation directory
before legacy support is removed.
Assisted-by: Antigravity:gemini-3.1-pro
Signed-off-by: Ian Rogers <irogers@google.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Commit 8a54784e70 ("perf build: Add pylint build tests") added a
compile-time pylint check for Python files in tools/perf, but left it
opt-in via PYLINT=1.
Now that pylint issues across tools/perf/python, tools/perf/pmu-events,
and tools/perf/tests/shell/lib have been cleaned up, enable the pylint
check by default when pylint is installed on the system, with an opt-out
via NO_PYLINT=1 (matching NO_SHELLCHECK=1, NO_MYPY=1, and other perf
build feature flags).
Configure PYTHONPATH in Makefile.perf so pylint resolves perf.pyi type
stubs and pmu-events modules, enable error and warning categories
(--disable=all --enable=E,W --disable=W0123,W0311,W0511,W0603,W0622,W0718
--ignored-modules=textual,setproctitle) appropriate for perf's standalone
CLI and test scripts, and require pylint >= 2.16.0 (skipping with a
warning if an older version is installed).
Assisted-by: Antigravity:gemini-3.1-pro
Signed-off-by: Ian Rogers <irogers@google.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Commit 168910d0f9 ("perf build: Add mypy build tests") added a
compile-time mypy type check for Python files in tools/perf, but left it
opt-in via MYPY=1.
Now that mypy issues across tools/perf/python, tools/perf/pmu-events,
and tools/perf/tests/shell/lib have been cleaned up, enable the mypy
check by default when mypy is installed on the system, with an opt-out
via NO_MYPY=1 (matching NO_SHELLCHECK=1 and other perf build feature
flags). Also configure MYPYPATH in Makefile.perf so scripts can resolve
perf.pyi type stubs and local modules, pass --ignore-missing-imports so
optional third-party packages do not fail default builds, and remove
*.mypy_log files during `make clean`.
Assisted-by: Antigravity:gemini-3.1-pro
Signed-off-by: Ian Rogers <irogers@google.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Clean up mypy type errors and pylint errors/warnings in
tools/perf/tests/shell/lib/ (attr.py, perf_json_output_lint.py, and
perf_metric_validation.py):
- Fix E0606 (possibly-used-before-assignment) in perf_metric_validation.py
by importing sys at module level.
- Add type annotations for stack, second_results, collectlist,
get_bounds(), and main() in perf_metric_validation.py.
- Avoid assigning -1 to list[int] expected_items in
perf_json_output_lint.py, rename shadowing variables, and remove
redundant lambdas.
- Remove unnecessary semicolons, use lazy logging arguments, specify
exception types and file encodings, and initialize module-level logger
in attr.py.
Also update tools/perf/tests/shell/lib/setup_python.sh to:
- Avoid x-prefix string comparisons.
- Export PYTHON and resolve PYTHONPATH and PERF_EXEC_PATH from
BASH_SOURCE[0], ../../../python (for nested test directories such as
coresight/), and the directory containing the perf binary so out-of-tree
builds and standalone perf python scripts work seamlessly.
Assisted-by: Antigravity:gemini-3.1-pro
Signed-off-by: Ian Rogers <irogers@google.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Clean up mypy type errors and pylint warnings across the pmu-events Python
scripts (amd_metrics.py, intel_metrics.py, jevents.py,
make_legacy_cache.py,
and metric.py) in preparation for making MYPY and PYLINT build tests
opt-out.
In addition to type annotations and unused import/variable cleanups, fix
three bugs in intel_metrics.py exposed by static analysis:
- Fix references to undefined 'args.model' (instead of '_args.model')
inside
try/except blocks in IntelL2() and UncoreMemBw(), which previously threw
NameError and silently disabled Skylake/CascadeLake L2 silent eviction
adjustments and uncore memory bandwidth JSON loading.
- Define DC_WB_U and DC_WB_D before their first use in IntelL2(), fixing
an UnboundLocalError that silently dropped the l2_out_rate, wbn, and isd
metrics.
- Fix Event-to-string comparison and addition in IntelFp() by comparing
and modifying 'f_assist.name' instead of the Event object 'f_assist'.
Assisted-by: Antigravity:gemini-3.1-pro
Signed-off-by: Ian Rogers <irogers@google.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
LiveSession.run() synchronously blocks while polling evlist for events.
When running interactive tools or scripts from the terminal,
KeyboardInterrupt exceptions raised via Ctrl-C must propagate so the
caller can break out of the polling loop.
Previously, LiveSession caught KeyboardInterrupt with an empty pass
statement, swallowing the exception and preventing calling scripts from
detecting the interrupt cleanly. Remove the empty handler so calling
scripts receive KeyboardInterrupt and can perform clean teardown.
Assisted-by: Antigravity:gemini-3.1-pro
Signed-off-by: Ian Rogers <irogers@google.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Add support for Intel PT call_return events and itrace options to the
perf Python extension so standalone Python scripts can decode and
inspect low-level instruction traces.
Specifically:
- Add a call_return callback parameter and itrace option string to
perf.session, treating explicit None (Py_None) callbacks as omitted.
- Expose the perf.call_return object with db_id, parent_id, insn_count,
cyc_count, comm, pid, tid, call_time, return_time, branch_count,
call_ref, return_ref, flags, and call_path (resolved as a
perf.callchain ordered from outermost caller to callee, populating
frame->map and frame->sym so call_path entries expose resolved symbol
and DSO names).
- Export perf.CALL_RETURN_NO_CALL, perf.CALL_RETURN_NO_RETURN, and
perf.CALL_RETURN_NON_CALL flag constants.
- Expose session.e_machine and session.is_64_bit properties, preferring
recorded thread ELF machines (perf_session__e_machine) over perf_env
so pipe-mode traces do not prematurely cache host bitness.
- Support optional vmlinux, kallsyms, and symfs symbol configuration
parameters (and PERF_SYMBOL_VMLINUX, PERF_SYMBOL_KALLSYMS,
PERF_SYMBOL_SYMFS environment fallbacks) in perf.session, resetting
symbol_conf pointers and freeing vm_tm_corr_args, cpu_bitmap, and
ptime_range in pyrf_session__delete().
Assisted-by: Antigravity:gemini-3.1-pro
Signed-off-by: Ian Rogers <irogers@google.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Expose destination address location components (addr_dso, addr_symbol,
addr_sym_offset), branch/transaction metrics (branch_type, in_tx,
flags, transaction), machine_pid, vcpu, sym_offset, and context_switch
callbacks directly to the Python extension.
Also include supporting fixes and infrastructure updates in
util/python.c and perf.pyi:
- Support fetching sym_offset on resolved sample symbols.
- Populate sample machine_pid and vcpu from evlist__id2sid() when
perf_guest is enabled, and resolve samples against the matching guest
or host machine.
- Expose next_prev_pid and next_prev_tid on switch_event only for
PERF_RECORD_SWITCH_CPU_WIDE records (returning None otherwise).
- Wire up tracing_data in pyrf_session__new() and update perf.pyi type
stubs (including srccode() and insn() return types).
Assisted-by: Antigravity:gemini-3.1-pro
Signed-off-by: Ian Rogers <irogers@google.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Add module docstrings to counting.py, tracepoint.py, and twatch.py. This
satisfies pylint's missing-module-docstring check and prepares these
existing standalone scripts in tools/perf/python/ for the later commit
in this series ("perf script: Support standalone scripts and remove
embedded scripting"), which updates 'perf script -l' to scan
tools/perf/python/ and display each script's module docstring:
```
$ perf script -l
List of available scripts:
...
counting
Example for counting perf events.
...
tracepoint
Example showing how to enable a tracepoint and access its fields.
twatch
Example to show how to enable a software event and track
context switches.
...
```
Assisted-by: Antigravity:gemini-3.1-pro
Signed-off-by: Ian Rogers <irogers@google.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Clean up pylint warnings in tracepoint.py so that it passes pylint
without warning suppression comments:
- Catch ImportError instead of bare 'except:' (W0702: bare-except) when
importing setproctitle.
- Remove unnecessary trailing semicolon (W0301: unnecessary-semicolon)
after evlist.enable().
Assisted-by: Antigravity:gemini-3.1-pro
Signed-off-by: Ian Rogers <irogers@google.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Clean up pylint warnings in treport.py so that it passes pylint without
warning suppression comments:
- Replace broad 'except Exception:' clauses (W0718:
broad-exception-caught) with specific exception tuples.
- Pass both pid and sample_tid to session.find_thread() so guest and
process threads are resolved accurately.
- Rename parameter 'args' to 'pos_args' in FlameGraph.__init__() to
avoid shadowing the outer scope variable 'args' (W0621:
redefined-outer-name).
- Clear session = None in a finally block after session.process_events()
to break the C perf_session reference cycle before launching the TUI.
Assisted-by: Antigravity:gemini-3.1-pro
Signed-off-by: Ian Rogers <irogers@google.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Replace bare 'except:' clauses (pylint W0702: bare-except) in ilist.py
with specific exception tuples (OSError, ValueError, RuntimeError,
TypeError, KeyError) and use a safe '.get("name", "")' sort key in
IListApp.compose() so that ilist.py passes pylint without warning
suppression comments and handles unnamed PMU events gracefully.
Assisted-by: Antigravity:gemini-3.1-pro
Signed-off-by: Ian Rogers <irogers@google.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Update pyrf_session__find_thread() in util/python.c to accept an
optional tid parameter (defaulting to pid) and return None instead of
raising TypeError when a thread is not found in the session machines.
Update perf.pyi to match:
- Set session.find_thread() signature to (pid: int, tid: int = -1) ->
Optional[thread].
- Update callchain_node.symbol and callchain_node.dso to str (the C
getters return "[unknown]" fallback strings rather than None) and add
__iter__() to callchain.
Also update treport.py to handle Optional[thread] returned by
session.find_thread().
Assisted-by: Antigravity:gemini-3.1-pro
Signed-off-by: Ian Rogers <irogers@google.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Update the PyArg_ParseTupleAndKeywords format string for
pyrf__syscall_name() and pyrf__syscall_id() from "i|$i" to "i|i" (and
"s|$i" to "s|i"), allowing elf_machine to be passed as an optional
positional argument as well as a keyword argument. Update syscall_id()
and syscall_name() in perf.pyi to match, and set the return type of
syscall_name() to Optional[str] as unknown syscall numbers return None.
Also expose perf_env__arch_strerrno() as perf.arch_strerrno(err,
elf_machine=None) so standalone Python scripts can resolve
architecture-specific errno names directly from the auto-generated
trace beauty tables instead of maintaining duplicate errno dictionaries
in Python. Tighten the macro pattern in arch_errno_names.sh to
E[A-Z0-9]+ so compiler -D flags containing underscores (such as LLVM's
-DEXPERIMENTAL_KEY_INSTRUCTIONS=1) do not shadow EPERM (1), and add
EM_SPARC32PLUS alongside EM_SPARC and EM_SPARCV9.
Assisted-by: Antigravity:gemini-3.1-pro
Signed-off-by: Ian Rogers <irogers@google.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
__synthesize_schedstat_domain() uses event after zalloc() without
checking for allocation failure, unlike __synthesize_schedstat_cpu().
If zalloc() fails and returns NULL, dereferencing ds->header.type
immediately crashes with a segmentation fault:
Program received signal SIGSEGV, Segmentation fault.
0x00005555558aed8a in __synthesize_schedstat_domain ()
#0 0x00005555558aed8a in __synthesize_schedstat_domain ()
#1 0x00005555558b889a in perf_event__synthesize_schedstat ()
#2 0x000055555563c397 in cmd_sched ()
#3 0x00005555556583a1 in handle_internal_command ()
#4 0x00005555555bf739 in main ()
perf_event__synthesize_schedstat() already treats a NULL event as an
error and cleans up, so return NULL when the allocation fails.
After this fix, an allocation failure returns NULL safely, allowing the
caller to exit gracefully without crashing:
[ perf sched stats: Failed !! ]
Fixes: c3030995f2 ("perf sched stats: Add record and rawdump support")
Signed-off-by: Hui Su <sh_def@163.com>
Cc: Swapnil Sapkal <swapnil.sapkal@amd.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
perf's build only refused interpreters older than 3.6, the check added
when jevents.py started using f-strings, and jevents.py carried a
removesuffix() shim to stay usable on them.
The kernel itself requires Python 3.9.x since 5e25b972a2 ("docs:
changes: update Python minimal version"), so tools in the tree are
expected to work with it, and staying compatible with older
interpreters stopped paying off:
- the PEP 585 generics, list[...], used by the type annotations in
jevents.py and util/setup.py are only subscriptable from Python 3.9
and, being evaluated at import or definition time, they break the
build on RHEL 8's python3.6.8 with:
TypeError: 'type' object is not subscriptable
- ProcessPoolExecutor(initializer=, initargs=) requires Python 3.7, so
generating pmu-events.c fails there as well.
Rather than spreading version guards and typing.List() workarounds for
interpreters that cannot be supported anyway, make 3.9 the floor: ask
for it once in Makefile.config and use the result in both places that
run python while building, jevents generation and the python binding,
as the binding is still built when NO_JEVENTS=1 skips the generation
check, and drop the removesuffix() shim, since str.removesuffix() was
added in 3.9.
RHEL 8 is in feature freeze, so those wanting a new perf and its python
features have to vendor a newer interpreter, just as
Documentation/process/changes.rst already asks for the kernel itself.
Tested with Python 3.9.22: perf builds, generating pmu-events.c and the
python binding, with byte for byte identical output to the build made
with the shim, while Python 3.8.20 and 3.6.15 are rejected with the
"older than 3.9" error, by the jevents check in a regular build and by
the binding check when NO_JEVENTS=1 makes them sail past it, where they
used to die on the TypeError from util/setup.py. With NO_JEVENTS=1 and
NO_LIBPYTHON=1 no interpreter runs while building, so neither check
applies. vermin reports no perf build file as requiring more than 3.9,
the only offender being the runtime script
scripts/python/mem-phys-addr.py, which the build doesn't run.
Suggested-by: Ian Rogers <irogers@google.com>
Reviewed-by: Ian Rogers <irogers@google.com>
Reviewed-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
Cc: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
Assisted-by: LLM
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
IBS events with exclude_{user,kernel} bits, as used for per-thread
recording when kernel samples are not allowed, are rejected on hardware
without the privilege filter, so per-thread 'perf mem record' fails on
AMD:
$ perf mem record -o /dev/null -- true
Failure to open event 'ibs_op/ldlat=0/u' on PMU 'ibs_op' which will be removed.
Kernel v6.14 added swfilt, a software privilege filter exposed as the
'swfilt' format term, making those events usable per-thread. Give the
ibs_op memory events extra tables with the term, selected in
perf_pmu__arch_init() when the PMU exposes it, keeping the names that
need system wide mode otherwise; the knowledge that IBS needs this
stays in the arch code.
Suggested-by: Namhyung Kim <namhyung@kernel.org>
Suggested-by: Ravi Bangoria <ravi.bangoria@amd.com>
Reviewed-by: Namhyung Kim <namhyung@kernel.org>
Reviewed-by: Ravi Bangoria <ravi.bangoria@amd.com>
Assisted-by: LLM
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
The data type profiling per-sample stream keys cross-CPU contention on
sample->cpu, which without PERF_SAMPLE_CPU is the "no CPU info"
sentinel, making same-instance accesses from different cores
indistinguishable from same-CPU traffic. 'perf mem record' already
passes -d and -W to the record parser, add --sample-cpu and document it
in perf-mem(1).
Also grow rec_argv: the new entry overflows it on PMUs with separate
load and store events, as the space for the fixed arguments was not
reserved.
Reviewed-by: Ian Rogers <irogers@google.com>
Reviewed-by: Namhyung Kim <namhyung@kernel.org>
Assisted-by: LLM
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Members are added recursively, and a broken DIE can make a member's
type point back at one of its own ancestors, recursing until the stack
is gone; nothing usable comes out of nesting members 32 deep anyway, so
stop there, marking the member as truncated and giving up on member
types that don't resolve.
The check is where the children of an aggregate would be expanded, so
only struct/union members are marked as truncated.
Reviewed-by: Ian Rogers <irogers@google.com>
Reviewed-by: Namhyung Kim <namhyung@kernel.org>
Assisted-by: LLM
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
'perf report -s type' hangs burning CPU on the dwz compressed debug
info of libz.so.1 (zlib-ng): die_collect_vars() saves the
dwarf_dieoffset() of the type DIE, which is relative to the file it
lives in - the dwz alt file for the types shared by more than one CU -
and update_var_state() resolves that offset in the main debug file,
parsing whatever is at it, here a typedef whose DW_AT_type refers to
itself.
Record whether the type DIE came from the alt file and resolve the
offset with die_get_type_die() in that file, with no fallback.
Fixes: 06b2ce7538 ("perf annotate-data: Maintain variable type info")
Fixes: 55ee3d005d ("perf annotate-data: Add a cache for global variable types")
Reviewed-by: Ian Rogers <irogers@google.com>
Reviewed-by: Namhyung Kim <namhyung@kernel.org>
Assisted-by: LLM
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
dwarf_dieoffset() is relative to the file the DIE is in, so an offset
saved by die_collect_vars()/die_collect_global_vars() is only
meaningful in that file: add die_same_file(), comparing the Dwarf each
DIE's CU belongs to, and die_get_type_die(), resolving the offset in it
with the saved tag as a sanity check. Resolving the offset in the main
file instead parses whatever is at it when it came from the dwz common
file.
dwarf_cu_getdwarf() is new in elfutils 0.160, so the libdw feature test
probes for it and Makefile.config says 0.160.
Reviewed-by: Ian Rogers <irogers@google.com>
Reviewed-by: Namhyung Kim <namhyung@kernel.org>
Cc: Masami Hiramatsu <mhiramat@kernel.org>
Assisted-by: LLM
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
A DIE parsed at an offset that is not the start of a DIE can have a
DW_AT_type that refers back to itself, making the typedef/qualifier
chases in die_get_real_type(), die_get_pointer_type() and
die_get_typename_from_type() spin forever; 'perf report -s type' did
that on the dwz compressed debug info of zlib-ng (libz.so.1).
No sane typedef/qualifier chain is 32 DIEs long, so give up on the type
with a pr_debug instead of hanging.
Reviewed-by: Ian Rogers <irogers@google.com>
Reviewed-by: Namhyung Kim <namhyung@kernel.org>
Cc: Masami Hiramatsu <mhiramat@kernel.org>
Assisted-by: LLM
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
The grep to match cgroup name in metric output assumes no leading / on
the cgroup name, however, cgroups in /proc/self/cgroup may have a
leading /. Strip the / if it exists to avoid failures to match the
cgroup name in the perf stat output.
Signed-off-by: Ian Rogers <irogers@google.com>
Acked-by: Namhyung Kim <namhyung@kernel.org>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
The declaration of the Rust helper test_rs() uses "uint", a BSD-ism
that lives in <sys/types.h>, so on glibc it is only visible by
accident: glibc's <stdlib.h> includes <sys/types.h>, where uint is
exposed under __USE_MISC, which is on by default.
musl does none of that: its <stdlib.h> doesn't include <sys/types.h>
and it typedefs uint there only when _GNU_SOURCE/_BSD_SOURCE is
defined, while nothing else in this translation unit includes
<sys/types.h>. Building it on Alpine therefore fails with:
tests/workloads/code_with_type.c:9:21: error: unknown type name 'uint'; did you mean 'int'?
tests/workloads/code_with_type.c:39:17: error: implicit declaration of function 'test_rs' [-Wimplicit-function-declaration]
The second error is a consequence of the first one: with the
declaration at line 9 rejected, the call at line 39 has no prototype,
which is an error since gcc 14.
The breakage is only visible when rustc is present, because
tests/workloads/Build adds code_with_type.o when CONFIG_RUST_SUPPORT
is detected, and tools/build/feature only checks for "rustc
--version". That is why alpine:3.23 and alpine:3.24 fail while
alpine:3.22 and alpine:edge, lacking rustc, build fine and hide it.
Use unsigned int, which needs no header at all.
Fixes: 2e05bb52a1 ("perf test workload: Add code_with_type test workload")
Reviewed-by: Ian Rogers <irogers@google.com>
Acked-by: Namhyung Kim <namhyung@kernel.org>
Cc: Dmitrii Dolgov <9erthalion6@gmail.com>
Assisted-by: LLM
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Two calloc() calls in the numa benchmark lack NULL return checks,
leading to potential NULL pointer dereferences on allocation failure:
1. worker_process(): the allocated `pthreads` array is used in the
following for-loop via pthreads[t] without checking for NULL.
2. __bench_numa(): the allocated `pids` array is used in the following
for-loop via pids[i] without checking for NULL.
Add BUG_ON() checks after each calloc(), consistent with the existing
NULL check style used elsewhere in the same file (e.g., node_present
and nodes allocations).
Signed-off-by: longlong yan <yanlonglong@kylinos.cn>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
The PMU CPU map has different semantics for core and uncore PMUs.
For core PMUs, pmu_cpus contains the CPUs on which the event can be
opened. Intersect the user-requested CPU map with the PMU CPU map to
reject CPUs unsupported by the PMU.
For uncore PMUs, pmu_cpus is read from the PMU's cpumask sysfs attribute,
which lists the default CPU to open the event on per socket/die, not the
set of CPUs it can only be opened on. The user-requested CPU may override
these defaults, and the driver can redirect the event to the appropriate
control CPU.
Currently, __perf_evlist__propagate_maps() intersects the user-requested
CPU map with pmu_cpus for all PMUs. If the user-requested CPU is not in
pmu_cpus, the intersection becomes empty and the evsel is removed before
perf_event_open() is called.
Add evsel->is_pmu_uncore, set once from pmu->is_uncore at parse time,
to skip the intersection for uncore PMUs. Core PMUs, and other
non-core PMUs such as software events, breakpoints, or tracepoints,
continue to be restricted to their PMU CPU map.
Fixes: 811082e4b6 ("perf parse-events: Support user CPUs mixed with threads/processes")
Reviewed-by: Ian Rogers <irogers@google.com>
Assisted-by: Claude:claude-sonnet-5
Signed-off-by: Nia Su <nia.su@sifive.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Exercise the function view without driving a terminal now that it has
a stdio path. Keep the existing datasym record/report coverage and make a
separate recording of the contended locks used by the futex hash benchmark.
Always check the function table headers, table replacement, missing-iaddr
diagnostic, and conflicting options. A machine can support c2c recording
without capturing a contended sample, so report a skip when the hierarchy
is empty rather than treating hardware sampling variance as a failure.
When samples are available, check generic row shapes for all three
hierarchy levels, their expanded fold signs, cacheline addresses, and the
absence of trailing whitespace in the table body.
Reviewed-by: Tianyou Li <tianyou.li@intel.com>
Reviewed-by: Wangyang Guo <wangyang.guo@intel.com>
Signed-off-by: Jiebin Sun <jiebin.sun@intel.com>
Acked-by: Namhyung Kim <namhyung@kernel.org>
Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Dapeng Mi <dapeng1.mi@linux.intel.com>
Cc: Ian Rogers <irogers@google.com>
Cc: James Clark <james.clark@linaro.org>
Cc: Thomas Falcon <thomas.falcon@intel.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
The function view is currently TUI-only, so it cannot be used by builds
without SLANG support, when output is piped, or from a script. Add a
--function option that prints the fully expanded three-level hierarchy to
stdout.
Keep the stdio renderer in builtin-c2c.c and reuse the common function-view
model introduced by the merged series. Export only the coalescing-field
capability check from the model, preserving the util/UI boundary and
leaving the TUI object in libperf-ui.a.
Stop padding the final identity column in symbol_view_entry(). The generic
formatter pads non-final columns but deliberately leaves the final column
unpadded, avoiding trailing whitespace in function-view table rows. The TUI
remains unchanged because its browser clears the rest of each rendered row.
--function implies --stdio and is rejected together with --stats. Validate
the iaddr requirement before processing events. Return function-view build
failures from the report command, and preserve TUI browser errors when
converting the display helpers to return a status.
Committer notes:
root@x2:~# uname -r
7.2.5-200.fc44.x86_64
root@x2:~# rpm -q kernel-debuginfo
kernel-debuginfo-7.2.5-200.fc44.x86_64
root@x2:~# perf c2c record perf bench futex hash -t 4 -r 1 -s > /dev/null 2>&1
root@x2:~# perf c2c report --stdio --function | grep "Functions Table" -A25
Shared Data Functions Table
=================================================
#
# Cycles Store
# % count Function / Contending function / Cacheline
# ......... ....... ..............................
#
- 47.89% 703 - [k] _raw_spin_lock
322 - [k] _raw_spin_lock
24 0xffff8b6dcbadf040
23 0xffff8b6dcbadf2c0
23 0xffff8b6dcbadf080
23 0xffff8b6dcbadf380
22 0xffff8b6dcbadf280
22 0xffff8b6dcbadf140
22 0xffff8b6dcbadf340
21 0xffff8b6dcbadf300
21 0xffff8b6dcbadf400
20 0xffff8b6dcbadf1c0
19 0xffff8b6dcbadf3c0
19 0xffff8b6dcbadf180
19 0xffff8b6dcbadf0c0
17 0xffff8b6dcbadf100
16 0xffff8b6dcbadf240
11 0xffff8b6dcbadf200
205 - [k] futex_q_unlock
root@x2:~#
Reviewed-by: Tianyou Li <tianyou.li@intel.com>
Reviewed-by: Wangyang Guo <wangyang.guo@intel.com>
Signed-off-by: Jiebin Sun <jiebin.sun@intel.com>
Acked-by: Namhyung Kim <namhyung@kernel.org>
Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Dapeng Mi <dapeng1.mi@linux.intel.com>
Cc: Ian Rogers <irogers@google.com>
Cc: James Clark <james.clark@linaro.org>
Cc: Thomas Falcon <thomas.falcon@intel.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
The workload path leaves err at 0 and returns, so the test exits 0 and is
reported as a pass even though nothing was recorded and neither report
invocation ran. The check_c2c_support() path above it already sets err=2.
Set err=2 there as well so a failing workload is reported as a skip.
Fixes: ac881007c4 ("perf tests c2c: Add a basic c2c")
Reviewed-by: Tianyou Li <tianyou.li@intel.com>
Reviewed-by: Wangyang Guo <wangyang.guo@intel.com>
Signed-off-by: Jiebin Sun <jiebin.sun@intel.com>
Acked-by: Namhyung Kim <namhyung@kernel.org>
Cc: Dapeng Mi <dapeng1.mi@linux.intel.com>
Cc: Ian Rogers <irogers@google.com>
Cc: James Clark <james.clark@linaro.org>
Cc: Thomas Falcon <thomas.falcon@intel.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
The default coalesce fields dropped pid in favor of iaddr, but the man
page still documents the old pid,iaddr default. Update it to match the
command.
Fixes: 423701a0c8 ("perf c2c: Change the default coalesce setup")
Reviewed-by: Tianyou Li <tianyou.li@intel.com>
Reviewed-by: Wangyang Guo <wangyang.guo@intel.com>
Signed-off-by: Jiebin Sun <jiebin.sun@intel.com>
Acked-by: Namhyung Kim <namhyung@kernel.org>
Cc: Dapeng Mi <dapeng1.mi@linux.intel.com>
Cc: Ian Rogers <irogers@google.com>
Cc: James Clark <james.clark@linaro.org>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Thomas Falcon <thomas.falcon@intel.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
The output_name variable is only used within builtin-sched.c for the
stats subcommand, so declare it static. This fixes a sparse warning:
builtin-sched.c:4140:12: warning: symbol 'output_name' was not
declared. Should it be static?
Reviewed-by: Ian Rogers <irogers@google.com>
Signed-off-by: nanshuaibo <nanshuaibo811@163.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Fix typos in comments, reported by scripts/checkpatch.pl using the
misspelling list in scripts/spelling.txt. Only touches comments, no
code changes.
Assisted-by: Cursor:claude-opus-5
Signed-off-by: Hemanth Selam <hemanth.selam@gmail.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Drop the word written twice, reported by checkpatch.pl as a possible
repeated word.
Only the message text changes, no code changes.
Assisted-by: Cursor:claude-opus-5
Signed-off-by: Hemanth Selam <hemanth.selam@gmail.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
procfs__read_str() allocates the buffer it hands back and
thread__set_comm() only stores an interned copy of the string, so the
caller owns the buffer. thread__set_comm_from_proc() freed it when the
read came back empty but not once it had been used, leaking it on
every successful call.
Free it on both paths. The empty read still returns -1, err being
untouched in that case.
Found with leak sanitizer while running 'perf trace':
Direct leak of 7 byte(s) in 1 object(s) allocated from:
#1 io__getdelim fs/../io.h:179
#2 filename__read_str fs/fs.c:365
#3 procfs__read_str fs/fs.c:402
#4 thread__set_comm_from_proc util/thread.c:297
#5 syscall_arg__scnprintf_pid trace/beauty/pid.c:15
Assisted-by: Antigravity:gemini-3.1-pro
Signed-off-by: Ian Rogers <irogers@google.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
trace__symbols_init() creates the host machine with machine__new_host(),
which allocates a struct machine, but trace__symbols__exit() released it
with machine__exit(). That tears down the contents of the machine and
leaves the allocation itself behind, so use machine__delete(), which
does both. The replay path points trace->host at the machine embedded in
the session and never reaches here, so nothing else is affected.
The leak was hidden from leak sanitizer because trace__symbols_init()
passes the machine to trace_event__register_resolver(), which stores it
as the private pointer of the global tep handle. The handle kept the
machine reachable for as long as the process lived, so it was only once
the handle started being freed that this was reported:
Direct leak of 1256 byte(s) in 1 object(s) allocated from:
#1 __machine__new_host util/machine.c:135
#2 machine__new_host util/machine.c:155
#3 trace__symbols_init builtin-trace.c:2105
#4 trace__run builtin-trace.c:4759
#5 cmd_trace builtin-trace.c:6091
Assisted-by: Antigravity:gemini-3.1-pro
Signed-off-by: Ian Rogers <irogers@google.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
The tep handle behind trace_event__tp_format() is a process wide cache
of the running kernel's tracepoint formats and nothing ever released
it, as the comment above it had noted since the code was added.
Add trace_event__exit() and call it from run_builtin() next to the
existing perf_config__exit(). By then the builtin has returned, so the
tep_event pointers it handed out, such as the ones cached in
evsel->tp_format, are no longer reachable.
Note that this does not silence every libtraceevent report under
leak sanitizer. Parsing a print fmt drops a token inside the library
itself, and as those allocations are not linked into the handle,
freeing the handle cannot reclaim them.
Assisted-by: Antigravity:gemini-3.1-pro
Signed-off-by: Ian Rogers <irogers@google.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
tp_format() read and parsed the format file on every call. Each parse
registers another tep_event with the global tep handle, and
libtraceevent has no way to free an individual event, only the whole
handle, so a repeated lookup of the same tracepoint both redoes the
work of reading and parsing the file and leaves a duplicate behind for
the rest of the session.
Ask the handle for the event first with tep_find_event_by_name() and
only fall back to reading the format file when it has not been parsed
yet. The handle holds formats for the running kernel alone, so a name
that is found is the same format that would have been read.
Assisted-by: Antigravity:gemini-3.1-pro
Signed-off-by: Ian Rogers <irogers@google.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
trace_event__tp_format() encoded failure with ERR_PTR() while
trace_event__tp_format_id() returned a plain NULL when tep_find_event()
found nothing, and tp_format() itself returned NULL when
tep_parse_format() failed, as its return value was discarded. Callers
test with IS_ERR(), which NULL does not satisfy, so those two failures
were taken for success. In syscall__read_info() that leads straight to:
if (IS_ERR(sc->tp_format)) {
...
return err;
}
if (syscall__alloc_arg_fmts(sc, sc->tp_format->format.nr_fields - 1))
which dereferences NULL when a format file fails to parse.
Mixing encoded error pointers with pointers that are compared against
NULL is what allows that to happen, so drop ERR_PTR() here and report
failures the way the rest of these paths already expect, by returning
NULL with errno set. evsel__tp_format() no longer has to translate the
error back into errno before printing it with %m, and the remaining
callers become NULL tests.
syscall__scnprintf_args() gains back its fallback of printing raw
arguments: it asked for IS_ERR(sc->tp_format), but syscall__read_info()
had already replaced the error pointer with NULL, so the branch could
never be taken.
Assisted-by: Antigravity:gemini-3.1-pro
Signed-off-by: Ian Rogers <irogers@google.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
thread__e_machine_endian() decides whether a thread is live, and so
whether to read /proc/pid/exe rather than fall back to the perf.data
environment, by recovering the session from the machine:
session = container_of(machine->machines, struct perf_session,
machines);
is_live = !session->data;
That only holds when the struct machines is the one embedded in a struct
perf_session. It is not the only one. aslr_tool keeps its own in struct
aslr_tool, and hists_cumulate, hists_filter, hists_link, hists_output
and thread-maps-share each put one on the stack. For those the
container_of subtracts offsetof(struct perf_session, machines) from an
address that was never inside a session, and the following load of
session->data reads outside the object, which is what ASan reports.
Replace the derivation with an explicit link. machines__init() takes the
owning session, or NULL when the machines is standalone, and
thread__e_machine_endian() reads it back through machines__session().
A NULL session is treated as live. The tests use synthetic pids that
have no /proc entry, so the read fails there and the e_machine falls
back to EM_HOST as before, rather than being decided by whatever the
out of bounds read happened to return. perf inject registers its
session with the aslr tool once the session exists, before any event is
processed, so that tool keeps reporting file based threads as not live.
Fixes: 70351029b5 ("perf thread: Add support for reading the e_machine type for a thread")
Assisted-by: Antigravity:gemini-3.1-pro
Signed-off-by: Ian Rogers <irogers@google.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
--symfs=<dir>,flat documents itself as matching only the base name, so a
debuginfo lookup for /usr/lib/x86_64-linux-gnu/libc.so.6 should land on
<dir>/libc.so.6.debug. It lands on
<dir>/debug/usr/lib/x86_64-linux-gnu/libc.so.6.debug instead, because the
layout is applied to a fixed prefix and the file name arrives afterwards:
len = __symbol__join_symfs(filename, size, "/usr/lib/debug");
snprintf(filename + len, size - len, "%s.debug", dso__long_name(dso));
perf_basename() only ever sees "/usr/lib/debug", so neither layout comes
out of it.
Compose the path as it would appear on the profiled system and join it
once, which puts the layout on the whole name. That covers
FEDORA_DEBUGINFO, UBUNTU_DEBUGINFO, MIXEDUP_UBUNTU_DEBUGINFO,
OPENEMBEDDED_DEBUGINFO and BUILDID_DEBUGINFO, plus the same composition in
build_id_cache__find_debug().
BUILDID_DEBUGINFO needs one more step: the build id cache splits the first
two characters of the build id off into a directory name, so the basename
of the hierarchy path is only part of the build id. Name the flat file
after the whole build id.
dso__disassemble_filename() passes a path from perf's own build id cache
rather than one on the profiled system, and every entry there is named
"elf" or "debug". Use path__join() so the layout does not apply.
With --symfs /s,flat the lookups are now /s/libc.so.6, /s/libc.so.6.debug,
/s/sleep and /s/<build id>.debug. hierarchy is unchanged.
Reviewed-by: Namhyung Kim <namhyung@kernel.org>
Signed-off-by: Zhan Xusheng <zhanxusheng@xiaomi.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
tools/perf/util/help-unknown-cmd.h has been empty and unused ever since
it was added to the kernel in commit 5feaac248a ("perf tools: Move
help_unknown_cmd() to its own file") to its own file"). Remove it.
Signed-off-by: Ethan Nelson-Moore <enelsonmoore@gmail.com>
Reviewed-by: Ian Rogers <irogers@google.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
On ARM the #slots literal may or may not be present, it won't be present
on x86. As it is missing it causes the ampereone and ampereonex PMU
metric tests to fail when run say on x86.
Extend the fake_pmu logic so that in these test cases we fake the
unknown literals like #slots as 1.0.
When building with JEVENTS_ARCH=all the ampere metric tests no longer
fail.
Signed-off-by: Ian Rogers <irogers@google.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>