Merge tag 'perf-tools-for-v7.2-1-2026-06-22' of git://git.kernel.org/pub/scm/linux/kernel/git/perf/perf-tools

Pull perf tools updates from Arnaldo Carvalho de Melo:

 - Introduce 'perf inject --aslr' to remap ASLR-randomized addresses in
   perf.data files, enabling reproducible analysis across runs with
   different address space layouts

 - Refactor evsel out of sample processing paths: store evsel in struct
   perf_sample and remove the redundant evsel parameter from tool APIs,
   tracepoint handlers, hist entry iterators, and db-export, simplifying
   the entire tool callback chain

 - Switch architecture detection from string-based perf_env__arch()
   comparisons to the numeric ELF e_machine field across the codebase
   (capstone, print_insn, c2c, lock-contention, sort, sample-raw,
   machine, header), making cross-analysis more robust

 - Overhaul ARM CoreSight ETM tests: add deterministic and named_threads
   workloads, speed up basic and disassembly tests, add process
   attribution and concurrent threads tests, remove unused workloads and
   duplicate tests, queue context packets for the frontend decoder

 - Add ARM SPE IMPDEF event decoding for Arm Neoverse N1, store MIDR in
   arm_spe_pkt for per-CPU event mapping, handle missing CPU IDs
   gracefully

 - Refactor libunwind support: remove the libunwind-local backend, make
   register reading cross-platform, add RISC-V libunwind support, allow
   dynamic selection between libdw and libunwind unwinding at runtime

 - Extensive hardening of perf.data parsing against crafted files: add
   bounds checks and byte-swap validation for session records, feature
   sections, header attributes, BPF metadata, auxtrace errors,
   compressed events, CPU maps, build ID notes, and ELF program headers.
   Add minimum event size validation and file offset diagnostics

 - Fix libdw API contract violations across dwarf-aux, libdw,
   probe-finder, annotate-data, and debuginfo subsystems. Fix callchain
   parent update in ORDER_CALLER mode, support DWARF line 0 in inline
   lists, handle multiple address spaces in callchains

 - Fix numerous 'perf sched' bugs: thread reference leaks, memory leaks,
   heap overflows with cross-machine recordings, NULL dereferences,
   replace BUG_ON assertions with graceful error handling, bounds-check
   CPU indices, fix SIGCHLD vs pause() races in sched stats

 - Overhaul the build system: move BPF skeleton generation out of
   Makefile.perf into bpf_skel.mak, decouple pmu-events from the prepare
   target, make beauty generated C code standalone .o files, compile BPF
   skeletons with -mcpu=v3, fix continuous rebuilds, various cleanups

 - Add 'perf test' JUnit XML reporting with -j/--junit option, split
   monolithic test suites into sub-tests, add summary reporting,
   refactor parallel poll loop, fix test failures on musl-based systems

 - Fix 'perf c2c' memory leaks in hist entry and format list handling,
   use-after-free in error paths, bounds-check CPU and node IDs

 - Fix 'perf bpf' metadata leaks on duplicate insert and alloc failure,
   bounds-check array offsets, validate event sizes and func_info
   fields, add NULL checks

 - Fix hwmon PMU: off-by-one null termination on sysfs reads, strlcpy
   buffer overflow in parse_hwmon_filename(), fd 0 check, empty label
   reads, scnprintf usage

 - Fix symbols subsystem: bounds-check ELF and sysfs build ID note
   iteration, validate p_filesz, fix 32-bit ELF bswap error, fix signed
   overflow in size checks, bounds-check .gnu_debuglink section

 - Fix tools lib api: null termination in filename__read_int/ull(),
   uninitialized stack data in filename__write_int(), snprintf
   truncation in mount_overload()

 - Replace libbabeltrace with babeltrace2-ctf-writer for CTF conversion
   in 'perf data'

 - Add RISC-V SDT argument parsing for static tracepoints

 - Add 'perf trace --show-cpu' option to display CPU id

 - Add 'perf bench sched pipe --write-size' option

 - Add a perf-specific .clang-format that overrides some kernel style
   behaviors

 - Update Intel vendor events for Alder Lake, Arrow Lake, Clearwater
   Forest, Emerald Rapids, Granite Rapids, Grand Ridge, Lunar Lake,
   Meteor Lake, Panther Lake, Sapphire Rapids, Sierra Forest

 - Add IOMMU metrics for AMD and Intel

 - Fix AMD event: switch l2_itlb_misses to
   bp_l1_tlb_miss_l2_tlb_miss.all

 - Add AMD IBS improvements: decode Streaming-store and Remote-Socket
   flags, suppress bogus fields on Zen4+, skip privilege test on Zen6+

 - Fix 'perf lock contention' SIGCHLD vs pause() race, allow 'mmap_lock'
   in -L filter, enable end-timestamp for cgroup aggregation, fix
   non-atomic data updates

 - Fix 'perf stat' false NMI watchdog warning in aggregation modes,
   bounds-check CPU index in topology callbacks, add aggr_nr metric
   parser support for uncore scaling

 - Fix 'perf timechart' memory leaks, CPU bounds checking,
   use-after-free on corrupted callchains

 - Fix 'perf inject' itrace branch stack synthesis, fix synthesized
   sample size with branch stacks

 - Fix DSO heap overflow on decompressed paths, uninitialized pathname
   on fallback, set proper error codes

 - Fix various snprintf/scnprintf usages to prevent buffer overflows and
   truncation across the codebase

 - Fix off-by-one stack buffer overflow in kallsyms__parse()

 - Fix 'perf kwork' memory management, address sanitizer issues, bounds
   check work->cpu

 - Fix 'perf tpebs' concurrent stop races and PID reuse hazards

 - Add O_CLOEXEC to open() calls and use mkostemp() for temporary files
   to prevent file descriptor leaks to child processes

 - Fix s390 Python extension TEXTREL by compiling as PIC

 - Fix build with ASAN for jitdump

 - Fix build failure due to btf_vlen() return type change

* tag 'perf-tools-for-v7.2-1-2026-06-22' of git://git.kernel.org/pub/scm/linux/kernel/git/perf/perf-tools: (343 commits)
  perf bpf: Fix up build failure due to change of btf_vlen() return type
  perf dso: Set standard errno on decompression failure
  perf bpf: Validate array presence before casting BPF prog info pointers
  perf c2c: Fix hist entry and format list leaks in c2c_he_free()
  perf c2c: Free format list entries when c2c_hists__init() fails
  perf cs-etm: Bounds-check CPU in cs_etm__get_queue()
  perf cs-etm: Require full global header in auxtrace_info size check
  perf cs-etm: Validate num_cpu before metadata allocation
  perf machine: Use snprintf() for guestmount path construction
  perf machine: Propagate machine__init() error to callers
  perf trace: Guard __probe_ip suppression with evsel__is_probe()
  perf evsel: Add lazy-initialized probe type detection helpers
  perf evsel: Add no-libtraceevent stubs for evsel__field() and evsel__common_field()
  perf cs-etm: Reject CPU IDs that would overflow signed comparison
  perf c2c: Free format list entries when releasing c2c hist entries
  perf bpf: Bounds-check array offsets in bpil_offs_to_addr()
  perf bpf: Reject oversized BPF metadata events that truncate header.size
  perf bpf: Validate func_info_rec_size and sub_id in synthesize_bpf_prog_name()
  perf sched: Replace (void*)1 sentinel with proper runtime allocation
  perf hwmon: Fix fd check to accept fd 0 in hwmon_pmu__describe_items()
  ...
This commit is contained in:
Linus Torvalds
2026-06-23 11:34:49 -07:00
392 changed files with 36566 additions and 9648 deletions
@@ -112,78 +112,6 @@ Example for triggering AUX pause and resume with PMU event::
Perf test - Verify kernel and userspace perf CoreSight work
-----------------------------------------------------------
When you run perf test, it will do a lot of self tests. Some of those
tests will cover CoreSight (only if enabled and on ARM64). You
generally would run perf test from the tools/perf directory in the
kernel tree. Some tests will check some internal perf support like:
There are a set of Perf tests for CoreSight which can be run with::
Check Arm CoreSight trace data recording and synthesized samples
Check Arm SPE trace data recording and synthesized samples
Some others will actually use perf record and some test binaries that
are in tests/shell/coresight and will collect traces to ensure a
minimum level of functionality is met. The scripts that launch these
tests are in the same directory. These will all look like:
CoreSight / ASM Pure Loop
CoreSight / Memcpy 16k 10 Threads
CoreSight / Thread Loop 10 Threads - Check TID
etc.
These perf record tests will not run if the tool binaries do not exist
in tests/shell/coresight/\*/ and will be skipped. If you do not have
CoreSight support in hardware then either do not build perf with
CoreSight support or remove these binaries in order to not have these
tests fail and have them skip instead.
These tests will log historical results in the current working
directory (e.g. tools/perf) and will be named stats-\*.csv like:
stats-asm_pure_loop-out.csv
stats-memcpy_thread-16k_10.csv
...
These statistic files log some aspects of the AUX data sections in
the perf data output counting some numbers of certain encodings (a
good way to know that it's working in a very simple way). One problem
with CoreSight is that given a large enough amount of data needing to
be logged, some of it can be lost due to the processor not waking up
in time to read out all the data from buffers etc.. You will notice
that the amount of data collected can vary a lot per run of perf test.
If you wish to see how this changes over time, simply run perf test
multiple times and all these csv files will have more and more data
appended to it that you can later examine, graph and otherwise use to
figure out if things have become worse or better.
This means sometimes these tests fail as they don't capture all the
data needed. This is about tracking quality and amount of data
produced over time and to see when changes to the Linux kernel improve
quality of traces.
Be aware that some of these tests take quite a while to run, specifically
in processing the perf data file and dumping contents to then examine what
is inside.
You can change where these csv logs are stored by setting the
PERF_TEST_CORESIGHT_STATDIR environment variable before running perf
test like::
export PERF_TEST_CORESIGHT_STATDIR=/var/tmp
perf test
They will also store resulting perf output data in the current
directory for later inspection like::
perf-asm_pure_loop-out.data
perf-memcpy_thread-16k_10.data
...
You can alter where the perf data files are stored by setting the
PERF_TEST_CORESIGHT_DATADIR environment variable such as::
PERF_TEST_CORESIGHT_DATADIR=/var/tmp
perf test
You may wish to set these above environment variables if you wish to
keep the output of tests outside of the current working directory for
longer term storage and examination.
sudo perf test coresight
-2
View File
@@ -2817,9 +2817,7 @@ F: tools/perf/arch/arm/util/auxtrace.c
F: tools/perf/arch/arm/util/cs-etm.c
F: tools/perf/arch/arm/util/cs-etm.h
F: tools/perf/arch/arm/util/pmu.c
F: tools/perf/tests/shell/*coresight*
F: tools/perf/tests/shell/coresight/*
F: tools/perf/tests/shell/lib/*coresight*
F: tools/perf/util/cs-etm-decoder/*
F: tools/perf/util/cs-etm.*
+3 -1
View File
@@ -99,7 +99,9 @@ union ibs_op_data2 {
rmt_node:1, /* 4: destination node */
cache_hit_st:1, /* 5: cache hit state */
data_src_hi:2, /* 6-7: data source high */
reserved1:56; /* 8-63: reserved */
strm_st:1, /* 8: streaming store */
rmt_socket:1, /* 9: remote socket */
reserved1:54; /* 10-63: reserved */
};
};
+14 -3
View File
@@ -104,6 +104,9 @@ FEATURE_TESTS_BASIC := \
# FEATURE_TESTS_BASIC + FEATURE_TESTS_EXTRA is the complete list
# of all feature tests
LIBUNWIND_ARCHS:=aarch64 arm loongarch64 mips ppc32 ppc64 riscv s390x x86 x86_64
FEATURE_TESTS_EXTRA := \
bionic \
compile-32 \
@@ -113,7 +116,7 @@ FEATURE_TESTS_EXTRA := \
gtk2 \
gtk2-infobar \
hello \
libbabeltrace \
babeltrace2-ctf-writer \
libcapstone \
libcheck \
libbfd-liberty \
@@ -127,7 +130,10 @@ FEATURE_TESTS_EXTRA := \
libpfm4 \
libdebuginfod \
clang-bpf-co-re \
bpftool-skeletons
bpftool-skeletons \
libunwind \
libunwind-debug-frame \
$(foreach arch,$(LIBUNWIND_ARCHS),libunwind-$(arch) libunwind-debug-frame-$(arch))
FEATURE_TESTS ?= $(FEATURE_TESTS_BASIC)
@@ -163,6 +169,7 @@ FEATURE_GROUP_MEMBERS-libbfd = libbfd-liberty libbfd-liberty-z
# Declare list of feature dependency packages that provide pkg-config files.
#
FEATURE_PKG_CONFIG ?= \
babeltrace2-ctf-writer \
libtraceevent \
libtracefs
@@ -211,7 +218,11 @@ ifeq ($(feature-all), 1)
$(call feature_check,compile-32)
$(call feature_check,compile-x32)
$(call feature_check,bionic)
$(call feature_check,libbabeltrace)
$(call feature_check,babeltrace2-ctf-writer)
$(call feature_check,libunwind)
$(call feature_check,libunwind-debug-frame)
$(foreach arch,$(LIBUNWIND_ARCHS),$(call feature_check,libunwind-$(arch)))
$(foreach arch,$(LIBUNWIND_ARCHS),$(call feature_check,libunwind-debug-frame-$(arch)))
else
$(foreach feat,$(FEATURE_TESTS),$(call feature_check,$(feat)))
endif
+28 -31
View File
@@ -1,6 +1,8 @@
# SPDX-License-Identifier: GPL-2.0
include ../../scripts/Makefile.include
LIBUNWIND_ARCHS:=aarch64 arm loongarch64 mips ppc32 ppc64 riscv s390x x86 x86_64
FILES= \
test-all.bin \
test-backtrace.bin \
@@ -38,17 +40,12 @@ FILES= \
test-libtracefs.bin \
test-libunwind.bin \
test-libunwind-debug-frame.bin \
test-libunwind-x86.bin \
test-libunwind-x86_64.bin \
test-libunwind-arm.bin \
test-libunwind-aarch64.bin \
test-libunwind-debug-frame-arm.bin \
test-libunwind-debug-frame-aarch64.bin \
$(foreach arch,$(LIBUNWIND_ARCHS),test-libunwind-$(arch).bin test-libunwind-debug-frame-$(arch).bin) \
test-pthread-attr-setaffinity-np.bin \
test-pthread-barrier.bin \
test-stackprotector-all.bin \
test-timerfd.bin \
test-libbabeltrace.bin \
test-babeltrace2-ctf-writer.bin \
test-libcapstone.bin \
test-libcheck.bin \
test-compile-32.bin \
@@ -75,7 +72,8 @@ FILES= \
test-file-handle.bin \
test-libpfm4.bin \
test-rust.bin \
test-libopenssl.bin
test-libopenssl.bin \
test-bpftool-skeletons.bin
FILES := $(addprefix $(OUTPUT),$(FILES))
@@ -211,27 +209,26 @@ $(OUTPUT)test-numa_num_possible_cpus.bin:
$(BUILD) -lnuma
$(OUTPUT)test-libunwind.bin:
$(BUILD) -lelf -llzma
$(BUILD) -include libunwind.h -lelf -llzma -lunwind
$(OUTPUT)test-libunwind-debug-frame.bin:
$(BUILD) -lelf -llzma
$(OUTPUT)test-libunwind-x86.bin:
$(BUILD) -lelf -llzma -lunwind-x86
$(BUILD) -include libunwind.h -lelf -llzma -lunwind
$(OUTPUT)test-libunwind-x86_64.bin:
$(BUILD) -lelf -llzma -lunwind-x86_64
define LIBUNWIND_RULE
$$(OUTPUT)test-libunwind-$(1).bin:
$$(CC) $$(CFLAGS) -MD -Wall -Werror -include libunwind-$(1).h -o $$@ \
test-libunwind.c $$(LDFLAGS) -lelf -llzma -lunwind-$(1) \
> $$(@:.bin=.make.output) 2>&1
$(OUTPUT)test-libunwind-arm.bin:
$(BUILD) -lelf -llzma -lunwind-arm
$$(OUTPUT)test-libunwind-debug-frame-$(1).bin:
$$(CC) $$(CFLAGS) -MD -Wall -Werror -include libunwind-$(1).h -o $$@ \
test-libunwind-debug-frame.c $$(LDFLAGS) -lelf -llzma -lunwind-$(1) \
> $$(@:.bin=.make.output) 2>&1
$(OUTPUT)test-libunwind-aarch64.bin:
$(BUILD) -lelf -llzma -lunwind-aarch64
$(OUTPUT)test-libunwind-debug-frame-arm.bin:
$(BUILD) -lelf -llzma -lunwind-arm
$(OUTPUT)test-libunwind-debug-frame-aarch64.bin:
$(BUILD) -lelf -llzma -lunwind-aarch64
endef
$(foreach arch,$(LIBUNWIND_ARCHS), \
$(eval $(call LIBUNWIND_RULE,$(arch))) \
)
$(OUTPUT)test-libslang.bin:
$(BUILD) -lslang
@@ -308,8 +305,8 @@ $(OUTPUT)test-backtrace.bin:
$(OUTPUT)test-timerfd.bin:
$(BUILD)
$(OUTPUT)test-libbabeltrace.bin:
$(BUILD) # -lbabeltrace provided by $(FEATURE_CHECK_LDFLAGS-libbabeltrace)
$(OUTPUT)test-babeltrace2-ctf-writer.bin:
$(BUILD) # -lbabeltrace2-ctf-writer provided by $(FEATURE_CHECK_LDFLAGS-babeltrace2-ctf-writer)
$(OUTPUT)test-libcapstone.bin:
$(BUILD) # -lcapstone provided by $(FEATURE_CHECK_LDFLAGS-libcapstone)
@@ -383,9 +380,9 @@ $(OUTPUT)test-libaio.bin:
$(OUTPUT)test-libzstd.bin:
$(BUILD) -lzstd
$(OUTPUT)test-clang-bpf-co-re.bin:
$(CLANG) -S -g --target=bpf -o - $(patsubst %.bin,%.c,$(@F)) | \
grep BTF_KIND_VAR
$(OUTPUT)test-clang-bpf-co-re.bin: test-clang-bpf-co-re.c
{ $(CLANG) -S -g --target=bpf -o - $< | \
grep BTF_KIND_VAR; } > $(@:.bin=.make.output) 2>&1 && touch $@
$(OUTPUT)test-file-handle.bin:
$(BUILD)
@@ -397,8 +394,8 @@ $(OUTPUT)test-libopenssl.bin:
$(BUILD) $(shell $(PKG_CONFIG) --libs --cflags openssl 2>/dev/null)
$(OUTPUT)test-bpftool-skeletons.bin:
$(SYSTEM_BPFTOOL) version | grep '^features:.*skeletons' \
> $(@:.bin=.make.output) 2>&1
{ $(SYSTEM_BPFTOOL) version | grep '^features:.*skeletons'; } \
> $(@:.bin=.make.output) 2>&1 && touch $@
# Testing Rust is special: we don't compile anything, it's enough to check the
# compiler presence. Compiling a test code for this purposes is problematic,
+3 -3
View File
@@ -100,13 +100,13 @@
# if 0
/*
* Disable libbabeltrace check for test-all, because the requested
* Disable babeltrace2-ctf-writer check for test-all, because the requested
* library version is not released yet in most distributions. Will
* reenable later.
*/
#define main main_test_libbabeltrace
# include "test-libbabeltrace.c"
#define main main_test_babeltrace2_ctf_writer
# include "test-babeltrace2-ctf-writer.c"
#undef main
#endif
@@ -1,7 +1,6 @@
// SPDX-License-Identifier: GPL-2.0
#include <babeltrace/ctf-writer/writer.h>
#include <babeltrace/ctf-ir/stream-class.h>
#include <babeltrace2-ctf-writer/writer.h>
int main(void)
{
@@ -1,27 +0,0 @@
// SPDX-License-Identifier: GPL-2.0
#include <libunwind-aarch64.h>
#include <stdlib.h>
extern int UNW_OBJ(dwarf_search_unwind_table) (unw_addr_space_t as,
unw_word_t ip,
unw_dyn_info_t *di,
unw_proc_info_t *pi,
int need_unwind_info, void *arg);
#define dwarf_search_unwind_table UNW_OBJ(dwarf_search_unwind_table)
static unw_accessors_t accessors;
int main(void)
{
unw_addr_space_t addr_space;
addr_space = unw_create_addr_space(&accessors, 0);
if (addr_space)
return 0;
unw_init_remote(NULL, addr_space, NULL);
dwarf_search_unwind_table(addr_space, 0, NULL, NULL, 0, NULL);
return 0;
}
-28
View File
@@ -1,28 +0,0 @@
// SPDX-License-Identifier: GPL-2.0
#include <libunwind-arm.h>
#include <stdlib.h>
extern int UNW_OBJ(dwarf_search_unwind_table) (unw_addr_space_t as,
unw_word_t ip,
unw_dyn_info_t *di,
unw_proc_info_t *pi,
int need_unwind_info, void *arg);
#define dwarf_search_unwind_table UNW_OBJ(dwarf_search_unwind_table)
static unw_accessors_t accessors;
int main(void)
{
unw_addr_space_t addr_space;
addr_space = unw_create_addr_space(&accessors, 0);
if (addr_space)
return 0;
unw_init_remote(NULL, addr_space, NULL);
dwarf_search_unwind_table(addr_space, 0, NULL, NULL, 0, NULL);
return 0;
}
@@ -1,17 +0,0 @@
// SPDX-License-Identifier: GPL-2.0
#include <libunwind-aarch64.h>
#include <stdlib.h>
extern int
UNW_OBJ(dwarf_find_debug_frame) (int found, unw_dyn_info_t *di_debug,
unw_word_t ip, unw_word_t segbase,
const char *obj_name, unw_word_t start,
unw_word_t end);
#define dwarf_find_debug_frame UNW_OBJ(dwarf_find_debug_frame)
int main(void)
{
dwarf_find_debug_frame(0, NULL, 0, 0, NULL, 0, 0);
return 0;
}
@@ -1,17 +0,0 @@
// SPDX-License-Identifier: GPL-2.0
#include <libunwind-arm.h>
#include <stdlib.h>
extern int
UNW_OBJ(dwarf_find_debug_frame) (int found, unw_dyn_info_t *di_debug,
unw_word_t ip, unw_word_t segbase,
const char *obj_name, unw_word_t start,
unw_word_t end);
#define dwarf_find_debug_frame UNW_OBJ(dwarf_find_debug_frame)
int main(void)
{
dwarf_find_debug_frame(0, NULL, 0, 0, NULL, 0, 0);
return 0;
}
@@ -1,5 +1,4 @@
// SPDX-License-Identifier: GPL-2.0
#include <libunwind.h>
#include <stdlib.h>
extern int
-28
View File
@@ -1,28 +0,0 @@
// SPDX-License-Identifier: GPL-2.0
#include <libunwind-x86.h>
#include <stdlib.h>
extern int UNW_OBJ(dwarf_search_unwind_table) (unw_addr_space_t as,
unw_word_t ip,
unw_dyn_info_t *di,
unw_proc_info_t *pi,
int need_unwind_info, void *arg);
#define dwarf_search_unwind_table UNW_OBJ(dwarf_search_unwind_table)
static unw_accessors_t accessors;
int main(void)
{
unw_addr_space_t addr_space;
addr_space = unw_create_addr_space(&accessors, 0);
if (addr_space)
return 0;
unw_init_remote(NULL, addr_space, NULL);
dwarf_search_unwind_table(addr_space, 0, NULL, NULL, 0, NULL);
return 0;
}
@@ -1,28 +0,0 @@
// SPDX-License-Identifier: GPL-2.0
#include <libunwind-x86_64.h>
#include <stdlib.h>
extern int UNW_OBJ(dwarf_search_unwind_table) (unw_addr_space_t as,
unw_word_t ip,
unw_dyn_info_t *di,
unw_proc_info_t *pi,
int need_unwind_info, void *arg);
#define dwarf_search_unwind_table UNW_OBJ(dwarf_search_unwind_table)
static unw_accessors_t accessors;
int main(void)
{
unw_addr_space_t addr_space;
addr_space = unw_create_addr_space(&accessors, 0);
if (addr_space)
return 0;
unw_init_remote(NULL, addr_space, NULL);
dwarf_search_unwind_table(addr_space, 0, NULL, NULL, 0, NULL);
return 0;
}
-1
View File
@@ -1,5 +1,4 @@
// SPDX-License-Identifier: GPL-2.0
#include <libunwind.h>
#include <stdlib.h>
extern int UNW_OBJ(dwarf_search_unwind_table) (unw_addr_space_t as,
+13 -6
View File
@@ -261,8 +261,8 @@ static const char *mount_overload(struct fs *fs)
/* "PERF_" + name + "_ENVIRONMENT" + '\0' */
char upper_name[5 + name_len + 12 + 1];
snprintf(upper_name, name_len, "PERF_%s_ENVIRONMENT", fs->name);
mem_toupper(upper_name, name_len);
snprintf(upper_name, sizeof(upper_name), "PERF_%s_ENVIRONMENT", fs->name);
mem_toupper(upper_name, strlen(upper_name));
return getenv(upper_name) ?: *fs->mounts;
}
@@ -294,11 +294,14 @@ int filename__read_int(const char *filename, int *value)
{
char line[64];
int fd = open(filename, O_RDONLY), err = -1;
ssize_t n;
if (fd < 0)
return -errno;
if (read(fd, line, sizeof(line)) > 0) {
n = read(fd, line, sizeof(line) - 1);
if (n > 0) {
line[n] = '\0';
*value = atoi(line);
err = 0;
}
@@ -312,11 +315,14 @@ static int filename__read_ull_base(const char *filename,
{
char line[64];
int fd = open(filename, O_RDONLY), err = -1;
ssize_t n;
if (fd < 0)
return -errno;
if (read(fd, line, sizeof(line)) > 0) {
n = read(fd, line, sizeof(line) - 1);
if (n > 0) {
line[n] = '\0';
*value = strtoull(line, NULL, base);
if (*value != ULLONG_MAX)
err = 0;
@@ -370,12 +376,13 @@ int filename__write_int(const char *filename, int value)
{
int fd = open(filename, O_WRONLY), err = -1;
char buf[64];
int len;
if (fd < 0)
return -errno;
sprintf(buf, "%d", value);
if (write(fd, buf, sizeof(buf)) == sizeof(buf))
len = sprintf(buf, "%d", value);
if (write(fd, buf, len) == len)
err = 0;
close(fd);
+30
View File
@@ -0,0 +1,30 @@
Future ABI changes
==================
This file collects items that require a libperf ABI bump. Each entry
should describe the current limitation, the desired end state, and the
scope of the change so that a future ABI revision can batch them
together.
1. Widen struct perf_cpu.cpu from int16_t to int
- Current limit: 32767 CPUs. No architecture exceeds this today
(x86_64 max is 8192, arm64 is 4096), but NR_CPUS limits keep
growing. perf clamps to INT16_MAX in set_max_cpu_num() as a
safety net.
- Code simplification: the int16_t forces defensive truncation
checks at every boundary where a wider CPU index (int from
sample->cpu, al->cpu, etc.) is narrowed into struct perf_cpu.
Without these checks, values > 32767 silently wrap to negative
numbers (two's complement), bypassing bounds validation.
Widening to int eliminates this entire class of silent
truncation bugs and removes the need for the INT16_MAX clamp
in set_max_cpu_num().
- Scope: struct perf_cpu is embedded everywhere — perf_cpu_map__cpu(),
perf_cpu_map__min(), perf_cpu_map__max(), perf_cpu_map__has(), the
for_each_cpu macros, and all internal callers. The perf_cpu_map
internal array (RC_CHK_ACCESS(map)->map[]) stores struct perf_cpu
directly. Widening changes the struct layout and every function
that returns or accepts struct perf_cpu by value.
- Migration: bump LIBPERF version in libperf.map, audit all
sizeof(struct perf_cpu) assumptions, update perf.data
serialization if needed.
+7 -1
View File
@@ -6,7 +6,13 @@
#include <stdbool.h>
#include <stdint.h>
/** A wrapper around a CPU to avoid confusion with the perf_cpu_map's map's indices. */
/**
* struct perf_cpu - wrapper around a CPU number.
* @cpu: CPU number, -1 for the "any CPU"/dummy value.
*
* int16_t limits this to 32767 CPUs. Widening to int requires a libperf
* ABI bump see tools/lib/perf/TODO for the full scope.
*/
struct perf_cpu {
int16_t cpu;
};
+8 -1
View File
@@ -8,7 +8,14 @@
#include <linux/bpf.h>
#include <sys/types.h> /* pid_t */
#define event_contains(obj, mem) ((obj).header.size > offsetof(typeof(obj), mem))
/*
* Verify the full field fits within the event, not just its start offset.
* Only valid for fixed-size scalar fields for trailing arrays like
* filename[PATH_MAX], sizeof() evaluates to the declared maximum, not
* the actual string length, so this would spuriously return false.
*/
#define event_contains(obj, mem) \
((obj).header.size >= offsetof(typeof(obj), mem) + sizeof((obj).mem))
struct perf_record_mmap {
struct perf_event_header header;
+65 -4
View File
@@ -169,8 +169,18 @@ int start_command(struct child_process *cmd)
static int wait_or_whine(struct child_process *cmd, bool block)
{
bool finished = cmd->finished;
int result = cmd->finish_result;
bool finished;
int result;
if (cmd->pid <= 0) {
cmd->finished = 1;
if (cmd->pid < 0 && cmd->finish_result == 0)
cmd->finish_result = -ERR_RUN_COMMAND_FORK;
return cmd->finish_result;
}
finished = cmd->finished;
result = cmd->finish_result;
while (!finished) {
int status, code;
@@ -233,7 +243,18 @@ int check_if_command_finished(struct child_process *cmd)
char filename[6 + MAX_STRLEN_TYPE(typeof(cmd->pid)) + 7 + 1];
char status_line[256];
FILE *status_file;
#endif
if (cmd->finished)
return 1;
if (cmd->pid <= 0) {
cmd->finished = 1;
if (cmd->pid < 0 && cmd->finish_result == 0)
cmd->finish_result = -ERR_RUN_COMMAND_FORK;
return 1;
}
#ifdef __linux__
/*
* Check by reading /proc/<pid>/status as calling waitpid causes
* stdout/stderr to be closed and data lost.
@@ -241,8 +262,48 @@ int check_if_command_finished(struct child_process *cmd)
sprintf(filename, "/proc/%u/status", cmd->pid);
status_file = fopen(filename, "r");
if (status_file == NULL) {
/* Open failed assume finish_command was called. */
return true;
int status;
pid_t waiting;
/*
* fopen() can fail with ENOENT if the process has been reaped.
* It can also fail with EMFILE/ENFILE if RLIMIT_NOFILE is reached.
* In those cases, use waitpid(..., WNOHANG) to robustly check
* and reap the process if it has exited.
*/
if (errno == ENOENT)
return 1;
waiting = waitpid(cmd->pid, &status, WNOHANG);
if (waiting == cmd->pid) {
int result;
int code;
cmd->finished = 1;
if (WIFSIGNALED(status)) {
result = -ERR_RUN_COMMAND_WAITPID_SIGNAL;
} else if (!WIFEXITED(status)) {
result = -ERR_RUN_COMMAND_WAITPID_NOEXIT;
} else {
code = WEXITSTATUS(status);
switch (code) {
case 127:
result = -ERR_RUN_COMMAND_EXEC;
break;
case 0:
result = 0;
break;
default:
result = -code;
break;
}
}
cmd->finish_result = result;
return 1;
}
if (waiting < 0 && (errno == ECHILD || errno == ESRCH))
return 1;
return 0;
}
while (fgets(status_line, sizeof(status_line), status_file) != NULL) {
char *p;

Some files were not shown because too many files have changed in this diff Show More