summaryrefslogtreecommitdiff
path: root/tools/perf/util
AgeCommit message (Collapse)Author
2 daysMerge branch 'modules-next' of ↵Mark Brown
https://git.kernel.org/pub/scm/linux/kernel/git/modules/linux.git
4 daysmodule/kallsyms: Rename is_mapping_symbol() to is_ignored_kernel_symbol()Tiezhu Yang
The helper function is_mapping_symbol() historically checks for both local labels prefixed with ".L" or "L0" and mapping symbols prefixed with "$". Rename it to is_ignored_kernel_symbol() to better reflect this actual behavior and scope, preventing conceptual confusion. While at it, update the related non-module files, no functional changes. Suggested-by: Petr Pavlu <petr.pavlu@suse.com> Signed-off-by: Tiezhu Yang <yangtiezhu@loongson.cn> Reviewed-by: Huacai Chen <chenhuacai@loongson.cn> Reviewed-by: Petr Pavlu <petr.pavlu@suse.com> Signed-off-by: Petr Pavlu <petr.pavlu@suse.com>
5 daysperf unwind: Handle allocation failure in libdw__get_entries()Triet Hoang
Check the return value of zalloc() before dereferencing the allocated dwfl_ui_ti structure. Return -ENOMEM when the allocation fails to avoid a NULL pointer dereference. Signed-off-by: Triet Hoang <triet.hoang.dev@gmail.com> Acked-by: Namhyung Kim <namhyung@kernel.org> Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
5 daysperf annotate: add Alpha instruction supportMatt Turner
Teach perf annotate about the Alpha control-transfer instructions, so that an Alpha perf.data gets call and jump arrows and resolved call targets, whether it is read on Alpha or on another host. Add tools/perf/util/annotate-arch/annotate-alpha.c with arch__new_alpha() and an associate_instruction_ops() that classifies: call: bsr, plus jsr and jcr as indirect calls ret: ret jump: br, the conditional branches beq/bne/blt/ble/bgt/bge/blbc/blbs and fbeq/fbne/fblt/fble/fbgt/fbge, plus jmp as an indirect jump mov: mov, fmov (objdump pseudos) That is every mnemonic binutils can print for the branch and JSR formats. jcr rather than jsr_coroutine, because both name the same MBR(0x1a,3) encoding and print_insn_alpha() takes the first match in the table, where the jcr alias has come first since the sources were imported in 1999. bsr needs an Alpha-specific parse routine. The generic call__parse() expects the operand string to begin with the target address, but a bsr prints its return-address register first: bsr t0,fffffc0001031dc0 <cserve_ena> strtoull() then stops on the leading register name, leaving the target address as 0, which makes call__scnprintf() fall back to printing the raw operands and leaves target.sym unresolved so the browser cannot follow the call. alpha_call__parse() takes the address from after the comma instead, as s390_call__parse() does for the same reason. The PC-relative branches need no such handling, as jump__parse() already skips up to two operands. jsr and jmp get ins_ops that resolve no target at all. They transfer control to a register, and their trailing operand is only a branch prediction hint: jsr ra,(t12),fffffc0001014ee8 <_printk> binutils extracts that hint as a 14-bit signed field scaled by four and prints it relative to the next instruction (extract_jhint() in alpha-opc.c, print_insn_alpha() in alpha-dis.c), so it can name the callee only when the callee lies within the resulting +-32KB. It also defaults to zero, which prints as the next instruction. Of the 213750 jsr in a vmlinux built from this tree, only 23093 hints land on a symbol; 157204 point into the middle of an unrelated function and 33453 are that default. Parsing the hint would therefore invent a call target for the majority of calls, so these keep their operands, as an indirect call does elsewhere. EM_ALPHA is 0x9026, far too large to index the e_machine-keyed arch_new_fn[] table in arch__find(), so select arch__new_alpha explicitly before the table lookup. Declare it in disasm.h and add the object to the annotate-arch Build. Disassembly itself comes from objdump/binutils, which already supports Alpha; this provides perf's instruction-class metadata for annotation. Tested on an EV7 Marvel, both natively and by annotating its perf.data on an x86_64 host, over bsr to a local function, jsr through the PLT and kernel-mode jsr; the two hosts produce identical output. Reviewed-by: Ian Rogers <irogers@google.com> Signed-off-by: Matt Turner <mattst88@gmail.com> Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
5 daysperf thread: Fix live-session detection in thread__e_machine()Matt Turner
When the per-thread e_machine cannot be determined from the DSOs in the thread's maps, thread__e_machine_endian() decides between reading /proc/<pid>/exe and falling back to the recorded session environment: bool is_live = machine->machines == NULL; if (!is_live) { /* Check if the session has a data file. */ struct perf_session *session = container_of(...); is_live = !!session->data; } Neither half of that works. The back pointer added by commit a088031c4998 ("perf tools: Add machine to machines back pointer") is set by machines__add(), which only ever adds guests; the host machine never gets one. Host-machine threads, which is to say almost all of them, therefore see machine->machines == NULL and are declared live before the session is consulted at all. The session test is also inverted. A session with a perf_data attached is one being read from a perf.data file, i.e. exactly the case that is not live, while a live session such as 'perf top' passes data=NULL to __perf_session__new(). So a file-based session takes the live path and reads /proc/<pid>/exe on the analysing host, which at best describes an unrelated process that has since been given the recorded pid, and normally just fails, leaving e_machine as EM_NONE. The perf_env fallback that would have supplied the recorded architecture is never reached, and thread__e_machine() returns EM_HOST. For a same-architecture recording this is invisible, since EM_HOST is the right answer anyway. Cross-architecture it is not: annotating an Alpha perf.data on an x86_64 host selects the x86 struct arch, so the Alpha disassembly is matched against the x86 instruction table. Alpha's 'ret' collides with x86's and gets ret_ops, while its calls and branches match nothing and are left unparsed, so no call target is resolved and no jump arrows are drawn. Set the back pointer for the host machine and correct the session test. The new back pointer does not disturb the other reader of the field, machine__findnew_guest_code(), which machine__resolve() only calls when !machine__is_host(machine). Fixes: 70351029b55677eb ("perf thread: Add support for reading the e_machine type for a thread") Reviewed-by: Ian Rogers <irogers@google.com> Signed-off-by: Matt Turner <mattst88@gmail.com> Cc: Namhyung Kim <namhyung@kernel.org> Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
5 daysperf python: Fix redundant self-assignment in get_argument_count()Liu Jing
In get_argument_count(), the variable code_obj is assigned to itself before being assigned the result of PyObject_GetAttrString(). This is a redundant self-assignment that appears to be a typo. Fix it by removing the redundant self-assignment. Signed-off-by: Liu Jing <liujing@cmss.chinamobile.com> Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
5 daysperf powerpc-vpadtl: Fix off-by-one in auxtrace_info minimum size checkWang Yan
min_sz is set to sizeof(u64) * POWERPC_VPADTL_TYPE, but the code reads auxtrace_info->priv[POWERPC_VPADTL_TYPE], which needs at least POWERPC_VPADTL_TYPE + 1 elements. POWERPC_VPADTL_TYPE is the first enumerator of the priv index enum (0), so min_sz evaluates to 0 and the check validates only the perf_record_auxtrace_info header itself. A PERF_RECORD_AUXTRACE_INFO event carrying a zero-length priv array then passes the size check, and the subsequent priv[POWERPC_VPADTL_TYPE] read runs one u64 past the validated region. This is the same off-by-one fixed for Intel PT by commit c4362d5e1a5e ("perf intel-pt: Fix off-by-one in auxtrace_info minimum size check") and for Intel BTS by commit b9fb8225951c ("perf intel-bts: Fix off-by-one in auxtrace_info minimum size check"). Use sizeof(u64) * (POWERPC_VPADTL_TYPE + 1) so the highest accessed priv index is covered by the minimum-size validation. Fixes: c4bbd4ec2e50a9ed ("perf powerpc: Process auxtrace events and display in 'perf report -D'") Reviewed-by: Adrian Hunter <adrian.hunter@intel.com> Signed-off-by: Wang Yan <wangyan01@kylinos.cn> Cc: Athira Rajeev <atrajeev@linux.ibm.com> Cc: stable@vger.kernel.org Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
5 daysperf hist: Remove keysym.h include from hist.hIan Rogers
hist.h isn't related to UI and so remove the UI inclusion. Fix the transitive dependency issues this exposes. Signed-off-by: Ian Rogers <irogers@google.com> Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
5 daysperf tool: Move usage strings and functions to perf.cIan Rogers
The code is mostly used by perf.c with additional unused functionality such as function pointers derived from early git code. Moving it into perf.c directly reduces the code footprint, drops the util/util.h dependence from perf.c, and allows us to remove util/usage.c entirely. The string constants are exposed in builtin.h, as they are used in builtin-help.c. Signed-off-by: Ian Rogers <irogers@google.com> Assisted-by: Antigravity:gemini-3.1-pro Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
5 daysperf tool: Tidy up util/cache.h header file usersIan Rogers
Use git clang-format to sort header files. Review header file includes removing those that were unnecessary or adding explicit includes in cases where transitive dependencies were be using. Signed-off-by: Ian Rogers <irogers@google.com> Assisted-by: Antigravity:gemini-3.1-pro Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
5 daysperf tool: Remove util/cache.hIan Rogers
Move definitions to places they are used, or path.h in the case of path.c's mkpath function. Remove unused definitions. Fix transitive include dependencies. Signed-off-by: Ian Rogers <irogers@google.com> Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
5 daysMerge remote-tracking branch 'torvalds/master' into perf-tools-nextArnaldo Carvalho de Melo
To pick the first perf-tools-fixes-for-v7.3 from Namhyung. Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
9 daysperf evsel: Validate RAW sample before byte swappingMark Amirkan
For an opposite-endian RAW sample, __evsel__parse_sample() passes the input-controlled size to mem_bswap_64() before checking whether the payload fits in the event. A truncated record can therefore make the helper read and write past the event boundary. A crafted perf.data file makes perf report crash with SIGSEGV. ASan reports the out-of-bounds access. A regression test puts backed data past the declared end and shows that it is changed before the parser returns -EFAULT. Move the bounds checks before mem_bswap_64(). Check the rounded length too, because the helper accesses complete 64-bit words. Complete records are handled as before. Fixes: f9d8adb345d7adbb ("perf evsel: Fix swap for samples with raw data") Reviewed-by: Ian Rogers <irogers@google.com> Assisted-by: Symbolic Signed-off-by: Mark Amirkan <markdamirkan@gmail.com> Cc: Jiri Olsa <jolsa@kernel.org> Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
9 daysperf evsel: Validate branch stack before byte swappingMark Amirkan
When perf reads an opposite-endian branch stack, __evsel__parse_sample() swaps each entry before checking whether all entries fit in the event. A truncated sample can therefore make the swap loop read and write past the event boundary. A truncated perf.data file makes perf report crash with SIGSEGV. ASan reports an out-of-bounds read. A regression test puts an entry just past the declared end and shows that its flags are changed before the parser returns -EFAULT. Move the bounds check before the byte-swap loop. Valid samples are handled as before. Fixes: 63c12ae2f246dcdc ("perf evsel: Add bitfield_swap() to handle branch_stack endian issue") Reviewed-by: Ian Rogers <irogers@google.com> Assisted-by: Symbolic Signed-off-by: Mark Amirkan <markdamirkan@gmail.com> Cc: Madhavan Srinivasan <maddy@linux.ibm.com> Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
9 daysperf tools: Add support for displaying weights in annotateAndi Kleen
Add support for showing all the three possible per IP weights in annotate. The weights are shown by defaults if any are non zero. This is useful, especially with the new insn lat statistics, but also for all the existing weights. Add a hotkey to the interactive browser to turn them off (w), as well as a perf annotate command line option. The weights are stored unconditionally in the sym_hist_entry, which will increase memory consumption somewhat. Reviewed-by: Namhyung Kim <namhyung@kernel.org> Assisted-by: omp:GPT-5.6-Luna Signed-off-by: Andi Kleen <ak@linux.intel.com> Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
10 daysperf jitdump: Size code_move event allocation with idr_sizeArnaldo Carvalho de Melo
jit_repipe_code_move() allocated the mmap2 event with a hardcoded +16, but computes event->mmap2.header.size as sizeof(event->mmap2) minus unused filename bytes plus idr_size. When idr_size is larger than 16, header.size exceeds the allocation, so perf_data__write() reads past the heap allocation, leaking adjacent heap memory into the generated perf.data file. Size the allocation with idr_size like jit_repipe_code_load() does. Reported-by: sashiko-bot <sashiko-bot@kernel.org> Cc: Stephane Eranian <eranian@google.com> Assisted-by: Opencode:DeepSeek-V4-Flash-free Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
10 daysperf jitdump: Write sample id fields in the order used by evsel__id_hdr_size()Arnaldo Carvalho de Melo
jit_repipe_code_load() and jit_repipe_code_move() cast the sample id area appended to the synthesized mmap2 record to a fixed: struct { u32 pid, tid; u64 time; }; and store the timestamp at offset 8 whenever PERF_SAMPLE_TIME is set. That matches what evsel__id_hdr_size() accounts for only when PERF_SAMPLE_TID is set as well: the fields are appended in a fixed order, skipping the ones not requested by sample_type, so with PERF_SAMPLE_TID unset PERF_SAMPLE_TIME starts at offset 0 and idr_size is 8. Storing the timestamp at offset 8 then lands 8 bytes past the end of the id area, which for an event allocated as sizeof(*event) + idr_size is past the end of the heap allocation, besides corrupting the record the tooling reading it back expects. Walk the id area in the order used by evsel__id_hdr_size(), advancing past each field only when its sample_type bit is set, and keep the computed timestamp in a local variable instead of reading it back from the event buffer. Reported-by: sashiko-bot <sashiko-bot@kernel.org> Cc: Stephane Eranian <eranian@google.com> Assisted-by: LLM Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
10 daysperf jitdump: Free unwinding data even when eh_frame_hdr_size is zeroArnaldo Carvalho de Melo
jit_repipe_code_load() only cleared the unwinding state when both unwinding_data and eh_frame_hdr_size were set. When a record carries unwinding data but eh_frame_hdr_size is 0, the cleanup condition fails and the unwinding state persists in jd, being applied to all subsequent JIT_CODE_LOAD and JIT_CODE_MOVE records, duplicating unwinding sections in the generated ELF files and inflating their event->mmap2.len. The record is validated upstream so eh_frame_hdr_size <= unwinding_size always holds. Free the unwinding data based on the data pointer alone. Reported-by: sashiko-bot <sashiko-bot@kernel.org> Reviewed-by: Ian Rogers <irogers@google.com> Cc: Stephane Eranian <eranian@google.com> Assisted-by: Opencode:DeepSeek-V4-Flash-free Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
10 daysperf genelf: Use unaligned-safe accessors for debug entriesArnaldo Carvalho de Melo
debug_entry records are packed with a variable-length name[] field, so entries after the first may start at addresses that are not naturally aligned. jit_process_debug_info(), get_special_opcode() and emit_lineno_info() read and write the u64 addr and int lineno fields through struct member access, which is undefined behavior on strict-alignment architectures. Use get_unaligned()/put_unaligned() to read and update each field, matching the layout the jitdump writers (LLVM, JVM agents) emit, which packs entries without padding. struct debug_entry.lineno is signed and emit_advance_lineno() takes a long line delta that relies on sign extension, so the field is read into an int: reading it into an unsigned int would turn a backward line jump into a huge forward one and corrupt the line number program. Reported-by: sashiko-bot <sashiko-bot@kernel.org> Cc: Stephane Eranian <eranian@google.com> Assisted-by: Opencode:DeepSeek-V4-Flash-free Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
10 daysperf jitdump: Byte-swap debug entries via unaligned-safe accessorsArnaldo Carvalho de Melo
debug_entry records are packed with a variable-length name[] field, so entries after the first may start at addresses that are not naturally aligned for their u64 addr and int lineno/discrim fields. On strict alignment architectures the byte-swap loop in jit_get_next_entry() performed misaligned 64-bit loads and stores through struct member access, which is undefined behavior. Use get_unaligned()/put_unaligned() for the byte-swap of each field. Reported-by: sashiko-bot <sashiko-bot@kernel.org> Cc: Stephane Eranian <eranian@google.com> Assisted-by: Opencode:DeepSeek-V4-Flash-free Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
13 daysperf jitdump: Validate unwinding sizes against record payloadArnaldo Carvalho de Melo
jit_repipe_unwinding_info() copies unwinding_size and eh_frame_hdr_size from the jitdump record into jd-> fields without checking them against the actual payload size. Downstream, jit_add_eh_frame_info() in genelf.c computes unwinding_table_size = unwinding_size - eh_frame_hdr_size, which underflows when eh_frame_hdr_size > unwinding_size. The result is passed as d->d_size to libelf, causing an OOB heap read into the output ELF file. Validate that unwinding_size fits within the record payload and that eh_frame_hdr_size does not exceed unwinding_size before allocating or storing the values, so a bogus record cannot force a large allocation that is then discarded. mapped_size is likewise taken from the record and was narrowed into an int for the mmap2 len computation in jit_repipe_code_load() and jit_repipe_code_move(); values above INT_MAX would turn negative, producing a wrong mmap2 length. Use uint64_t for usize so the value cannot truncate. Fixes: 0284fecd13b6db3e ("perf jit: Add unwinding support") Reported-by: sashiko-bot <sashiko-bot@kernel.org> Reviewed-by: Ian Rogers <irogers@google.com> Cc: Stefano Sanfilippo <ssanfilippo@chromium.org> Cc: Stephane Eranian <eranian@google.com> Assisted-by: LLM Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
13 daysperf jitdump: Validate sym string NUL-termination in code loadArnaldo Carvalho de Melo
jit_repipe_code_load() computes sym = (void *)jr + sizeof(jr->load) and passes it to jit_emit_elf() which calls strlen(sym) via jit_write_elf(). If code_size equals total_size - sizeof(jr->load), the sym pointer aliases the code blob with no NUL terminator, and strlen() scans past the buffer into adjacent heap memory. Add a memchr() check to verify the symbol name is NUL-terminated within the region between the load header and the code blob before use. Fixes: 598b7c6919c7bbcc ("perf jit: add source line info support") Reported-by: sashiko-bot <sashiko-bot@kernel.org> Reviewed-by: Ian Rogers <irogers@google.com> Cc: Stephane Eranian <eranian@google.com> Assisted-by: LLM Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
13 daysperf jitdump: Validate debug entries on native (non-swap) pathArnaldo Carvalho de Melo
The bounds-checking and nr_entry clamping added for the byte-swap path only runs when jd->needs_bswap is true. On native-endian files, nr_entry passes through unvalidated to jit_repipe_debug_info(), which stores it as jd->nr_debug_entries. Downstream, jit_process_debug_info() in genelf_debug.c iterates nr_debug_entries times via debug_entry_next(), which calls strlen() on each entry's name field — a crafted nr_entry causes OOB reads and writes. Add bounds-checked iteration in jit_repipe_debug_info() that validates each debug_entry fits in the payload and its name is NUL-terminated before calling debug_entry_next(). Clamp nr_debug_entries to the count of valid entries. Fixes: 598b7c6919c7bbcc ("perf jit: add source line info support") Reported-by: sashiko-bot <sashiko-bot@kernel.org> Reviewed-by: Ian Rogers <irogers@google.com> Cc: Stephane Eranian <eranian@google.com> Assisted-by: LLM Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
13 daysperf jitdump: Use dirname() return value in jit_open()Arnaldo Carvalho de Melo
jit_open() calls dirname(jd->dir) but ignores the return value. POSIX says dirname() may return a pointer to internal static storage — glibc does this when the path has no '/', returning "." from a static buffer and leaving jd->dir unchanged with the original filename. Capture the return value and copy it back to jd->dir when dirname() returns a different pointer. Fixes: 9b07e27f88b9 ("perf inject: Add jitdump mmap injection support") Reported-by: sashiko-bot <sashiko-bot@kernel.org> Reviewed-by: Ian Rogers <irogers@google.com> Cc: Stephane Eranian <eranian@google.com> Assisted-by: LLM Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
13 daysperf jitdump: Free event in jit_repipe_code_move()Arnaldo Carvalho de Melo
jit_repipe_code_move() allocates a perf_event with calloc but never frees it — the 'out' label exits with only perf_sample__exit(). The sibling function jit_repipe_code_load() correctly calls free(event) at its out label. Add the same free(event) to jit_repipe_code_move(). Fixes: 9b07e27f88b9 ("perf inject: Add jitdump mmap injection support") Reported-by: sashiko-bot <sashiko-bot@kernel.org> Reviewed-by: Ian Rogers <irogers@google.com> Cc: Stephane Eranian <eranian@google.com> Assisted-by: LLM Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
13 daysperf jitdump: Fix funlockfile on unlocked stream in jit_open() error pathArnaldo Carvalho de Melo
If the malloc() for the initial read buffer fails, jit_open() jumps to the error label which calls funlockfile(jd->in). However, flockfile() is called later in the function, so at this point the stream was never locked. Calling funlockfile() on an unlocked stream is undefined behavior per POSIX. Split the error path into two labels: 'error' (after flockfile) calls funlockfile before cleanup, 'error_noflock' (before flockfile) skips the unlock. Fixes: 9b07e27f88b9 ("perf inject: Add jitdump mmap injection support") Reported-by: sashiko-bot <sashiko-bot@kernel.org> Reviewed-by: Ian Rogers <irogers@google.com> Cc: Stephane Eranian <eranian@google.com> Assisted-by: LLM Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
13 daysperf jitdump: Check snprintf return before computing header sizeArnaldo Carvalho de Melo
snprintf() returns the would-have-been length on truncation. When the jitted filename exceeds PATH_MAX, the unclamped 'size' value inflates sizeof(event->mmap2.filename) - size into a massive underflow, causing the header.size computation to write an oversized header. The subsequent write to 'id = event + header.size - idr_size' then corrupts the heap. Clamp size to PATH_MAX - 1 after snprintf in both jit_repipe_code_load() and jit_repipe_code_move(). Fixes: 9b07e27f88b9 ("perf inject: Add jitdump mmap injection support") Reported-by: sashiko-bot <sashiko-bot@kernel.org> Reviewed-by: Ian Rogers <irogers@google.com> Cc: Stephane Eranian <eranian@google.com> Assisted-by: LLM Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
13 daysperf jitdump: Bounds-check debug entry byte-swap loopArnaldo Carvalho de Melo
The byte-swap loop for JIT_CODE_DEBUG_INFO uses array indexing (jr->info.entries[n]) to iterate debug entries. struct debug_entry has a flexible array member name[], so each entry has a different size. Array indexing computes offsets assuming fixed-size elements, landing inside variable-length name strings after the first entry and byte-swapping garbage. Additionally, nr_entry is read from untrusted jitdump input without validation against total_size, so a crafted value causes OOB reads. Replace the array indexing with debug_entry_next() pointer arithmetic (which correctly accounts for the variable-length name) and bounds-check each entry against the record's total_size before byte-swapping. Fixes: 9b07e27f88b9 ("perf inject: Add jitdump mmap injection support") Reported-by: sashiko-bot <sashiko-bot@kernel.org> Reviewed-by: Ian Rogers <irogers@google.com> Cc: Stephane Eranian <eranian@google.com> Assisted-by: LLM Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
13 daysperf jitdump: Prevent integer underflow in debug info size calculationArnaldo Carvalho de Melo
jit_repipe_debug_info() and jit_repipe_unwinding_info() compute payload sizes by subtracting the fixed header size from total_size: sz = jr->prefix.total_size - sizeof(jr->info); When total_size is smaller than the header struct (from a truncated or corrupted jitdump record), the subtraction underflows to a massive value, causing an oversized allocation followed by an OOB memcpy. Validate that total_size covers at least the fixed header before the subtraction in both functions. Fixes: 598b7c6919c7 ("perf jit: add source line info support") Fixes: 0284fecd13b6 ("perf jit: Add unwinding support") Reported-by: sashiko-bot <sashiko-bot@kernel.org> Reviewed-by: Ian Rogers <irogers@google.com> Cc: Stephane Eranian <eranian@google.com> Cc: Stefano Sanfilippo <ssanfilippo@chromium.org> Assisted-by: LLM Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
13 daysperf jitdump: Validate code_size against total_size in code loadArnaldo Carvalho de Melo
jit_repipe_code_load() reads code_size from the jitdump record and uses it to compute a pointer to the code blob: code = (unsigned long)jr + jr->load.p.total_size - csize; An oversized code_size underflows the pointer arithmetic, causing OOB reads into earlier heap memory. Validate that code_size fits within the record (total_size - sizeof(jr->load)) before the pointer computation. code_size is uint64_t but csize is int; values above INT_MAX wrap negative when narrowed into csize, which defeats the bounds check and sends the code pointer past the end of the record. Reject those too. Fixes: 9b07e27f88b9 ("perf inject: Add jitdump mmap injection support") Reported-by: sashiko-bot <sashiko-bot@kernel.org> Reviewed-by: Ian Rogers <irogers@google.com> Cc: Stephane Eranian <eranian@google.com> Assisted-by: LLM Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
13 daysperf jitdump: Fix debug_data and unwinding_data leaksArnaldo Carvalho de Melo
jit_repipe_debug_info() overwrites jd->debug_data without freeing the previous allocation. If two consecutive JIT_CODE_DEBUG_INFO records appear without an intervening LOAD record consuming the data, the first allocation leaks. The sibling jit_repipe_unwinding_info() already frees the old jd->unwinding_data before reassignment — add the same pattern to jit_repipe_debug_info() using zfree(). Also add cleanup of both buffers in jit_close() so they are freed when the jitdump session ends, even if no LOAD record consumed them. Fixes: 9b07e27f88b9 ("perf inject: Add jitdump mmap injection support") Reported-by: sashiko-bot <sashiko-bot@kernel.org> Reviewed-by: Ian Rogers <irogers@google.com> Cc: Stephane Eranian <eranian@google.com> Assisted-by: LLM Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
13 daysperf jitdump: Fix extended header read that always failsArnaldo Carvalho de Melo
jit_open() sets bsz = bs before the fread() that uses bs - bsz as the read size, making the expression always evaluate to zero. fread() with size 0 returns 0, which triggers the ret != 1 error path — so extended jitdump headers (total_size > sizeof(header)) have been silently broken since the original implementation. Additionally, when 0 < bs <= bsz the if (bs > bsz) block is skipped entirely, leaving extended header bytes unread in the stream. Subsequent jit_get_next_entry() calls then parse those leftover bytes as a jr_prefix, corrupting the record stream. Fix by separating the buffer growth from the read: realloc only when bs > bsz, then unconditionally fread bs bytes when bs > 0. Fixes: 9b07e27f88b9cd78 ("perf inject: Add jitdump mmap injection support") Reported-by: sashiko-bot <sashiko-bot@kernel.org> Reviewed-by: Ian Rogers <irogers@google.com> Cc: Stephane Eranian <eranian@google.com> Cc: Ian Rogers <irogers@google.com> Cc: Namhyung Kim <namhyung@kernel.org> Assisted-by: LLM Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
14 daysperf powerpc-vpadtl: Fix raw_size of DTL samplesWang Yan
In powerpc_vpadtl_sample(), raw_data of the synthetic sample points to a struct powerpc_vpadtl_entry (48 bytes), but raw_size is set to sizeof(record). record is a struct powerpc_vpadtl_entry pointer, so sizeof(record) is the size of the pointer (8 bytes on 64-bit) rather than the size of the record itself. As a result, consumers that bound their access to raw_data by raw_size only see or copy the first 8 bytes of each DTL entry instead of the full record. Use sizeof(*record) so that raw_size reflects the actual length of the raw data. Fixes: 8644834a482a ("perf powerpc: Process the DTL entries in queue and deliver samples") Signed-off-by: Wang Yan <wangyan01@kylinos.cn> Reviewed-by: Athira Rajeev <atrajeev@linux.ibm.com> Reviewed-by: Arnaldo Carvalho de Melo <acme@redhat.com> Signed-off-by: Namhyung Kim <namhyung@kernel.org>
14 daysperf symbol: Do not use debug file as the binary typeAdrian Hunter
dso__load() sets the binary type of a DSO to the type of the first symbol source found. For a DSO with a separate debug file linked via .gnu-debuglink, that is DSO_BINARY_TYPE__DEBUGLINK, which makes dso__get_filename() return the name of the debug file instead of the file that was actually executed. Consumers that need to read instruction bytes, such as Intel PT decoding in 'perf script', then read from the debug file and produce wrong instructions. Prefer DSO_BINARY_TYPE__BUILD_ID_CACHE, and otherwise DSO_BINARY_TYPE__SYSTEM_PATH_DSO, over debug-only types, which restores the behaviour of using a file that contains the executed instructions. This is a workaround. Properly separating the binary file used for instructions from the file used for debug symbols is left for later. Example: Create a shared object with a separate .gnu_debuglink debug file. Note that 'objcopy --only-keep-debug' leaves .text as NOBITS, so instructions read from the debug file are zeros: # cat > foo.c << EOF unsigned long foo_work(unsigned long n) { unsigned long s = 0; for (unsigned long i = 0; i < n; i++) s = s * 31 + i; return s; } EOF # cat > main.c << EOF #include <stdio.h> unsigned long foo_work(unsigned long n); int main(void) { printf("%lu\n", foo_work(1000)); return 0; } EOF # gcc -g -O2 -shared -fPIC -o libfoo.so foo.c # gcc -g -O2 -o main main.c -L. -lfoo -Wl,-rpath,'$ORIGIN' # objcopy --only-keep-debug libfoo.so libfoo.so.debug # objcopy --strip-debug libfoo.so # objcopy --add-gnu-debuglink=libfoo.so.debug libfoo.so # perf record -e intel_pt//u ./main Note that branch samples must be requested, because it is the resolving of the branch target symbol that causes dso__load() to be called, and hence the binary type to be set, before the decoder walks the code. With '--itrace=e' alone, nothing loads symbols for libfoo.so, the binary type is left as DSO_BINARY_TYPE__NOT_FOUND, the correct file is read anyway, and no errors are reported either way. Before: # perf.before script --itrace=be 2>&1 | grep "instruction trace error" instruction trace error type 1 time 2350.467489498 cpu 9 pid 75634 tid 75634 ip 0x77d48480718f code 6: Trace doesn't match instruction instruction trace error type 1 time 2350.467489832 cpu 9 pid 75634 tid 75634 ip 0x77d484807341 code 6: Trace doesn't match instruction instruction trace error type 1 time 2350.467496412 cpu 9 pid 75634 tid 75634 ip 0x5b4de37a8074 code 6: Trace doesn't match instruction instruction trace error type 1 time 2350.467593393 cpu 9 pid 75634 tid 75634 ip 0x77d4848070d0 code 6: Trace doesn't match instruction instruction trace error type 1 time 2350.467593954 cpu 9 pid 75634 tid 75634 ip 0x77d4848075a8 code 6: Trace doesn't match instruction instruction trace error type 1 time 2350.467595728 cpu 9 pid 75634 tid 75634 ip 0x77d4848324de code 6: Trace doesn't match instruction 6 instruction trace errors After: # perf script --itrace=be 2>&1 | grep "instruction trace error" # Fixes: 5363c306787c8 ("perf symbol: Set binary_type of dso when loading") Reported-by: Todd Lipcon <tlipcon@google.com> Closes: https://lore.kernel.org/all/CAGH6UiG=RJLqBU3kLu9XJciPyPO1HZkbAPERguVUMRuWQgqf=A@mail.gmail.com/ Signed-off-by: Adrian Hunter <adrian.hunter@intel.com> Signed-off-by: Namhyung Kim <namhyung@kernel.org>
2026-08-17perf evlist: Warn when 'sleep' workload is used without system-wide (-a) optionIan Rogers
A common mistake when trying to record system-wide profiles for a given duration is running commands like 'perf record sleep 1' or 'perf stat sleep 1' without passing '-a' / '--all-cpus'. When '-a' is omitted, perf defaults to per-process monitoring of the sleep process itself, which does not collect system-wide activity and records very few events. Add a warning in evlist__prepare_workload() when the workload executable is 'sleep' and system-wide mode is not enabled. Assisted-by: Antigravity:gemini-3.6-flash Signed-off-by: Ian Rogers <irogers@google.com> Signed-off-by: Namhyung Kim <namhyung@kernel.org>
2026-08-17perf c2c: add function view browser UI and cacheline detailJiebin Sun
Add the browser front end: create/run/delete the hist_browser and add the title. The d shortcut opens the existing per-cacheline detail view for the selected level-3 cacheline. Level-3 entries retain the source cacheline index, so the shortcut can locate the original entry without relying on a potentially ambiguous virtual address. Report a warning when the common model rejects a cacheline coalescing field list without `iaddr`. Without it, the detail histograms may already have merged samples from different functions and cannot support reliable function attribution. Keep visible-row accounting local to the function view by wrapping the generic browser refresh callback and recounting the currently reachable hierarchy before each redraw. This keeps navigation correct when a level-1 row is collapsed while level-3 descendants remain expanded, without adding C2C-specific hooks to the shared hist_browser. Also handle Ctrl-C like the other function-view exit keys. Keep callchains hidden while the function browser runs, restoring the user's setting while opening the cacheline detail view. Wire the builder into perf_c2c__browse_function_view(). Signed-off-by: Jiebin Sun <jiebin.sun@intel.com> Reviewed-by: Tianyou Li <tianyou.li@intel.com> Reviewed-by: Wangyang Guo <wangyang.guo@intel.com> Reviewed-by: Ian Rogers <irogers@google.com> Cc: Dapeng Mi <dapeng1.mi@linux.intel.com> Cc: James Clark <james.clark@linaro.org> Cc: Thomas Falcon <thomas.falcon@intel.com> Signed-off-by: Namhyung Kim <namhyung@kernel.org>
2026-08-17perf c2c: build and finalize the function view hierarchyJiebin Sun
Add the builder that walks the top-level cacheline entries and, for each read-side function, correlates the functions that write the same lines (level 2) and the specific cachelines they contend over (level 3) within each retained detail histogram. Aggregate the write traffic per contending function, resort by store count, and prune writers/functions with no contention. The finalize pass then computes the Cycles % denominator from the surviving level-1 entries after pruning, so the column shows each function's share of the functions retained in the table rather than of the whole recording -- the semantics documented for Cycles % in perf-c2c.txt. Expose c2c_function__build() and c2c_function__reset() for the TUI front end added by the next patch. The builder requires iaddr in the cacheline coalescing fields and returns the completed hists through an output argument. Validate the inputs before replacing an existing model. Function-view entries do not carry callchains. Suppress callchain handling while building and tearing down the model so the common API does not depend on the caller's current callchain setting. Signed-off-by: Jiebin Sun <jiebin.sun@intel.com> Reviewed-by: Tianyou Li <tianyou.li@intel.com> Reviewed-by: Wangyang Guo <wangyang.guo@intel.com> Reviewed-by: Ian Rogers <irogers@google.com> Cc: Dapeng Mi <dapeng1.mi@linux.intel.com> Cc: James Clark <james.clark@linaro.org> Cc: Thomas Falcon <thomas.falcon@intel.com> Signed-off-by: Namhyung Kim <namhyung@kernel.org>
2026-08-17perf c2c: add function view hierarchy entry creationJiebin Sun
Add the entry-creation layer: owned-reference child allocation and insertion, and the level-1/2/3 lookup-or-create functions keyed by function symbol (level 1 read-side, level 2 writer) and by the source cacheline's existing index (level 3). Give synthetic children normal entry operations and acquire their thread and map-symbol references. This lets the hierarchy teardown use hist_entry__delete() for the common fields while the function-view free callback handles the private child tree and containing allocation. Reuse cacheline_idx to preserve the source entry identity without adding function-view-only state. Add c2c_function__find_cacheline() to locate the original cacheline entry by the same index. These are driven by the hierarchy builder in the next patch and are __maybe_unused until then. Signed-off-by: Jiebin Sun <jiebin.sun@intel.com> Reviewed-by: Tianyou Li <tianyou.li@intel.com> Reviewed-by: Wangyang Guo <wangyang.guo@intel.com> Reviewed-by: Ian Rogers <irogers@google.com> Cc: Dapeng Mi <dapeng1.mi@linux.intel.com> Cc: James Clark <james.clark@linaro.org> Cc: Thomas Falcon <thomas.falcon@intel.com> Signed-off-by: Namhyung Kim <namhyung@kernel.org>
2026-08-17perf c2c: add function view stats merge and memory managementJiebin Sun
Add the per-entry stats/cstats aggregation helpers and hierarchy teardown. Child common fields are released through hist_entry__delete(), while the function-view free callback handles the private child tree and containing allocation. Also add a helper for pruning writer entries with no stores or cacheline children. These are used by the entry-creation and builder patches that follow and are __maybe_unused until then. Signed-off-by: Jiebin Sun <jiebin.sun@intel.com> Reviewed-by: Tianyou Li <tianyou.li@intel.com> Reviewed-by: Wangyang Guo <wangyang.guo@intel.com> Reviewed-by: Ian Rogers <irogers@google.com> Cc: Dapeng Mi <dapeng1.mi@linux.intel.com> Cc: James Clark <james.clark@linaro.org> Cc: Thomas Falcon <thomas.falcon@intel.com> Signed-off-by: Namhyung Kim <namhyung@kernel.org>
2026-08-17perf c2c: add HPP list parsing for function view columnsJiebin Sun
Add the parser that builds the function view's local HPP output and sort lists from field strings. This includes dimension lookup, comparator wrappers, c2c_fmt allocation, and the initialization entry points used by the hierarchy builder. The generic perf_hpp__setup_output_field() registers formats on the global perf_hpp_list. Using it here would leave the function view's local list without output columns and modify the cacheline view's list instead. Add c2c_function_hists__setup_output_field() to append sort keys to the local output list. Signed-off-by: Jiebin Sun <jiebin.sun@intel.com> Reviewed-by: Tianyou Li <tianyou.li@intel.com> Reviewed-by: Wangyang Guo <wangyang.guo@intel.com> Reviewed-by: Ian Rogers <irogers@google.com> Cc: Dapeng Mi <dapeng1.mi@linux.intel.com> Cc: James Clark <james.clark@linaro.org> Cc: Thomas Falcon <thomas.falcon@intel.com> Signed-off-by: Namhyung Kim <namhyung@kernel.org>
2026-08-17perf c2c: add column rendering for function viewJiebin Sun
Add renderers for the function view's Cycles %, Store count, and hierarchy identity columns. The identity column renders the read-side function, contending writer, or cacheline, with indentation for the hierarchy level. Also add width and header helpers, estimated-cycle calculation, comparators, and the dimension table that ties them together. Clamp the identity renderer's returned length to its local buffer before using it for pointer and padding calculations. This handles snprintf-style would-have-been lengths without changing normal output. The next patch connects these dimensions to the view's HPP lists, so the symbols used only there are temporarily marked __maybe_unused. Signed-off-by: Jiebin Sun <jiebin.sun@intel.com> Reviewed-by: Tianyou Li <tianyou.li@intel.com> Reviewed-by: Wangyang Guo <wangyang.guo@intel.com> Reviewed-by: Ian Rogers <irogers@google.com> Cc: Dapeng Mi <dapeng1.mi@linux.intel.com> Cc: James Clark <james.clark@linaro.org> Cc: Thomas Falcon <thomas.falcon@intel.com> Signed-off-by: Namhyung Kim <namhyung@kernel.org>
2026-08-17perf c2c: add function view model skeletonJiebin Sun
Add the initial common model for the c2c function view: model state and small helpers shared by the hierarchy construction and formatting added in later patches. Build the model from util/ so it remains independent of the TUI and command-private symbols. Signed-off-by: Jiebin Sun <jiebin.sun@intel.com> Reviewed-by: Tianyou Li <tianyou.li@intel.com> Reviewed-by: Wangyang Guo <wangyang.guo@intel.com> Reviewed-by: Ian Rogers <irogers@google.com> Cc: Dapeng Mi <dapeng1.mi@linux.intel.com> Cc: James Clark <james.clark@linaro.org> Cc: Thomas Falcon <thomas.falcon@intel.com> Signed-off-by: Namhyung Kim <namhyung@kernel.org>
2026-08-17perf c2c: extract shared data structures into util/c2c.hJiebin Sun
The function browser belongs in libperf-ui.a, but that archive is also linked into python/perf.so, where builtin command objects are unavailable. The browser therefore cannot depend on types or callbacks owned by builtin-c2c.c. Move c2c_hists, compute_stats, c2c_hist_entry, and the shared column formatting definitions from builtin-c2c.c to a new util/c2c.h. Move c2c_fmt_free() and c2c_fmt_equal() to a new util/c2c.c. Keep struct perf_c2c, the command instance, and perf_c2c__browse_cacheline() private to builtin-c2c.c. No functional change. Signed-off-by: Jiebin Sun <jiebin.sun@intel.com> Reviewed-by: Tianyou Li <tianyou.li@intel.com> Reviewed-by: Wangyang Guo <wangyang.guo@intel.com> Reviewed-by: Ian Rogers <irogers@google.com> Cc: Dapeng Mi <dapeng1.mi@linux.intel.com> Cc: James Clark <james.clark@linaro.org> Cc: Thomas Falcon <thomas.falcon@intel.com> Signed-off-by: Namhyung Kim <namhyung@kernel.org>
2026-08-15perf dso: Replace assert with runtime check in dso__read_symbol()Arnaldo Carvalho de Melo
dso__read_symbol() asserts that len <= jited_prog_len, where len comes from sym->end - sym->start (parsed from PERF_RECORD_KSYMBOL in perf.data). Both values originate from untrusted file input. With NDEBUG (production builds), the assert is compiled out, allowing an out-of-bounds heap read when the BPF program buffer is accessed. Without NDEBUG, a crafted perf.data crashes perf with an assertion failure. Replace the assert with a runtime bounds check that returns NULL with an appropriate error code, matching the existing error handling pattern in this function. Fixes: aa04707f507e ("perf dso: Support BPF programs in dso__read_symbol()") Reported-by: sashiko-bot <sashiko-bot@kernel.org> Reviewed-by: Ian Rogers <irogers@google.com> Cc: Song Liu <song@kernel.org> Assisted-by: Claude:claude-opus-4.6 Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com> Signed-off-by: Namhyung Kim <namhyung@kernel.org>
2026-08-15perf dso: Guard against cache underflow on short reads in dso_cache__memcpy()Arnaldo Carvalho de Melo
dso_cache__memcpy() computes cache_offset = offset - cache->offset, then cache_size = min(cache->size - cache_offset, size). The RB tree lookup in __dso_cache__find() matches using the full DSO__DATA_CACHE_SIZE window, but cache->size reflects the actual pread return value from dso_cache__populate(). A short pread (e.g. near end-of-file) makes cache->size smaller than DSO__DATA_CACHE_SIZE. If a subsequent access targets an offset past cache->offset + cache->size but within the DSO__DATA_CACHE_SIZE window, the cache entry is found but cache_offset exceeds cache->size. Since both are u64, the subtraction cache->size - cache_offset wraps to a large value, min() selects the caller's size, and memcpy reads out of bounds. Return 0 for an offset past the valid cached data. For a regular file a short pread only happens at end-of-file, so 0 is what a direct pread() at that offset would return: cached_io() stops its read loop as on EOF. Re-reading from the backing file would not help — a second pread at the same offset returns the same short count. Fixes: 366df72657e0 ("perf dso: Refactor dso_cache__read()") Reported-by: sashiko-bot <sashiko-bot@kernel.org> Reviewed-by: Ian Rogers <irogers@google.com> Assisted-by: Claude:claude-opus-4.6 Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com> Signed-off-by: Namhyung Kim <namhyung@kernel.org>
2026-08-15perf dso: Use stored fd error instead of stale errno in file_read() and ↵Arnaldo Carvalho de Melo
file_size() file_read() and file_size() use ret = -errno when dso__data(dso)->fd is negative after try_to_open_dso() fails. By this point errno has been through mutex_lock(), nsinfo__mountns_enter(), and multiple open() attempts inside try_to_open_dso() — it no longer reflects the actual open failure. If errno happens to be 0, ret = 0 looks like EOF rather than an error, and file_size() callers like dso__data_size() would then report a zero-sized file instead of failing. dso__data(dso)->fd is always negative on failure — -errno from __open_dso() when no filename could be built (e.g. -EINVAL, -ENOENT), or -1 when do_open() itself failed — and never 0, so use it directly instead of reading the stale global errno. No assert() or comment is needed after the assignment: the enclosing if (dso__data(dso)->fd < 0) already guarantees ret < 0 [Namhyung Kim review]. Fixes: 33bdedcea2d7 ("perf tools: Protect dso cache fd with a mutex") Reported-by: sashiko-bot <sashiko-bot@kernel.org> Reviewed-by: Ian Rogers <irogers@google.com> Assisted-by: Claude:claude-opus-4.6 Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com> Signed-off-by: Namhyung Kim <namhyung@kernel.org>
2026-08-15perf dso: Guard close() against invalid fd in dso__decompress_kmodule_path()Arnaldo Carvalho de Melo
dso__decompress_kmodule_path() unconditionally calls close(fd) on the return value of decompress_kmodule(). When decompression fails or the DSO is not compressed, decompress_kmodule() returns -1. close(-1) fails with EBADF and clobbers errno, which callers up the chain (dso__get_filename → __open_dso) depend on for error propagation. Guard the close() call with fd >= 0 so only valid file descriptors are closed. Fixes: 42b3fa670825 ("perf tools: Introduce dso__decompress_kmodule_{fd,path}") Reported-by: sashiko-bot <sashiko-bot@kernel.org> Reviewed-by: Ian Rogers <irogers@google.com> Assisted-by: Claude:claude-opus-4.6 Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com> Signed-off-by: Namhyung Kim <namhyung@kernel.org>
2026-08-15perf dso: Guard against errno==0 when dso__get_filename() returns NULLArnaldo Carvalho de Melo
__open_dso() computes fd = -errno when dso__get_filename() returns NULL. Some failure paths in dso__get_filename() (e.g. binary type mismatch) return NULL without making a syscall, leaving errno at 0 from a prior successful call. fd = -0 = 0, which is stdin — subsequent code treats it as a valid file descriptor. Fall back to ENOENT when errno is 0, ensuring fd is always negative on failure. The forced ENOENT stays in errno for the callers that check it after a negative fd. It must not misdirect the try_to_open_dso() fallback loop, though: dso__get_filename()'s chroot fallback used to accept a stale ENOENT even when stat() succeeded on a non-regular file (e.g. a directory). Re-stat() there and only take the chroot path when stat() actually failed with ENOENT [sashiko-bot review of PATCH 1/5]. Fixes: eba5102d2f0b ("perf tools: Add global list of opened dso objects") Reported-by: sashiko-bot <sashiko-bot@kernel.org> Reviewed-by: Ian Rogers <irogers@google.com> Assisted-by: Claude:claude-opus-4.6 Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com> Signed-off-by: Namhyung Kim <namhyung@kernel.org>
2026-08-09perf synthetic-events: Fix divide by zero in perf_event__synthesize_threadsIan Rogers
If scandir() finds no matching tasks in /proc, n is 0. If thread_nr is > 1, we bypass the single-thread fast path and then clamp thread_nr to n, making it 0. This results in a divide by zero when calculating num_per_thread. Handle n <= 1 early to use the single-thread fast path and prevent the crash. Fixes: 340b47f510bb ("perf top: Implement multithreading for perf_event__synthesize_threads") Signed-off-by: Ian Rogers <irogers@google.com> Signed-off-by: Namhyung Kim <namhyung@kernel.org>
2026-08-09perf python: Fix memory leak in pyrf__metrics_cbIan Rogers
In pyrf__metrics_cb, PyDict_SetItem does not steal the reference of the key and value, so they need to be decref'ed after successful insertion to avoid memory leaks. Fixes: 47b3e95728eb ("perf python: Add metrics function") Signed-off-by: Ian Rogers <irogers@google.com> Signed-off-by: Namhyung Kim <namhyung@kernel.org>