mirror of
https://github.com/linux-msm/laptops-kernel.git
synced 2026-08-13 14:19:53 -07:00
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:
@@ -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
|
||||
|
||||
@@ -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.*
|
||||
|
||||
|
||||
@@ -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 */
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
-2
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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,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
@@ -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);
|
||||
|
||||
@@ -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.
|
||||
@@ -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,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;
|
||||
|
||||
@@ -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
Reference in New Issue
Block a user