summaryrefslogtreecommitdiff
path: root/tools/perf/python
diff options
context:
space:
mode:
authorIan Rogers <irogers@google.com>2026-09-25 23:19:36 -0700
committerArnaldo Carvalho de Melo <acme@redhat.com>2026-09-26 20:49:27 +0200
commitf66944587d18a84504d9c9782295944fbd29036f (patch)
tree2df07c701afbaf0f25d7d8b9065dbef5a9c4788e /tools/perf/python
parent7a481f6c712a1505f67b97add508bb9d393c9d22 (diff)
perf python: Add Intel PT call_return and itrace capability
Add support for Intel PT call_return events and itrace options to the perf Python extension so standalone Python scripts can decode and inspect low-level instruction traces. Specifically: - Add a call_return callback parameter and itrace option string to perf.session, treating explicit None (Py_None) callbacks as omitted. - Expose the perf.call_return object with db_id, parent_id, insn_count, cyc_count, comm, pid, tid, call_time, return_time, branch_count, call_ref, return_ref, flags, and call_path (resolved as a perf.callchain ordered from outermost caller to callee, populating frame->map and frame->sym so call_path entries expose resolved symbol and DSO names). - Export perf.CALL_RETURN_NO_CALL, perf.CALL_RETURN_NO_RETURN, and perf.CALL_RETURN_NON_CALL flag constants. - Expose session.e_machine and session.is_64_bit properties, preferring recorded thread ELF machines (perf_session__e_machine) over perf_env so pipe-mode traces do not prematurely cache host bitness. - Support optional vmlinux, kallsyms, and symfs symbol configuration parameters (and PERF_SYMBOL_VMLINUX, PERF_SYMBOL_KALLSYMS, PERF_SYMBOL_SYMFS environment fallbacks) in perf.session, resetting symbol_conf pointers and freeing vm_tm_corr_args, cpu_bitmap, and ptime_range in pyrf_session__delete(). Assisted-by: Antigravity:gemini-3.1-pro Signed-off-by: Ian Rogers <irogers@google.com> Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools/perf/python')
-rw-r--r--tools/perf/python/perf.pyi78
1 files changed, 61 insertions, 17 deletions
diff --git a/tools/perf/python/perf.pyi b/tools/perf/python/perf.pyi
index 44c693761838..087da00728fd 100644
--- a/tools/perf/python/perf.pyi
+++ b/tools/perf/python/perf.pyi
@@ -96,7 +96,7 @@ class data:
class thread:
"""Represents a thread in the system."""
- def comm(self) -> str:
+ def comm(self) -> Optional[str]:
"""Get the command name of the thread."""
...
pid: int
@@ -165,7 +165,13 @@ class evsel:
def __str__(self) -> str:
"""Return string representation of the event."""
...
- def open(self) -> None:
+ def open(
+ self,
+ cpus: Optional['cpu_map'] = None,
+ threads: Optional[thread_map] = None,
+ group: bool = False,
+ inherit: bool = False,
+ ) -> None:
"""Open the event selector file descriptor table."""
...
def read(self, cpu: int, thread: int) -> counts_values:
@@ -211,15 +217,15 @@ class sample_event(_sample_members):
sample_cyc_count: int
type: int
raw_buf: bytes
- dso: str
- dso_long_name: str
- dso_bid: Optional[bytes]
- map_start: int
- map_end: int
- map_pgoff: int
- symbol: str
- sym_start: int
- sym_end: int
+ dso: Optional[str]
+ dso_long_name: Optional[str]
+ dso_bid: Optional[str]
+ map_start: Optional[int]
+ map_end: Optional[int]
+ map_pgoff: Optional[int]
+ symbol: Optional[str]
+ sym_start: Optional[int]
+ sym_end: Optional[int]
sym_offset: Optional[int]
addr_dso: Optional[str]
addr_symbol: Optional[str]
@@ -230,7 +236,7 @@ class sample_event(_sample_members):
transaction: int
brstack: Optional['branch_stack']
callchain: Optional['callchain']
- def srccode(self) -> Optional[tuple[Optional[str], int, Optional[str]]]: ...
+ def srccode(self, addr: int = ..., /) -> Optional[tuple[Optional[str], int, Optional[str]]]: ...
def insn(self) -> Optional[bytes]: ...
def __getattr__(self, name: str) -> Any: ...
@@ -339,6 +345,7 @@ class branch_stack:
"""Sequence of branch entries in the branch stack."""
def __len__(self) -> int: ...
def __getitem__(self, index: int) -> branch_entry: ...
+ def __iter__(self) -> Iterator[branch_entry]: ...
class callchain_node:
"""Represents a frame in the callchain."""
@@ -387,10 +394,10 @@ class evlist:
def close(self) -> None:
"""Close the events in the list."""
...
- def mmap(self) -> None:
+ def mmap(self, pages: int = 128, overwrite: bool = False) -> None:
"""Memory map the event buffers."""
...
- def poll(self, timeout: int) -> int:
+ def poll(self, timeout: int = -1) -> int:
"""Poll for events.
Args:
@@ -400,7 +407,7 @@ class evlist:
Number of events ready.
"""
...
- def read_on_cpu(self, cpu: int) -> Optional[Any]:
+ def read_on_cpu(self, cpu: int, sample_id_all: bool = True) -> Optional[Any]:
"""Read a sample event from a specific CPU.
Args:
@@ -437,17 +444,38 @@ class evlist:
def enable(self) -> None:
"""Enable all events in the list."""
...
- def get_pollfd(self) -> List[int]:
+ def get_pollfd(self) -> List[Any]:
"""Get a list of file descriptors for polling."""
...
- def add(self, evsel: evsel) -> int:
+ def add(self, evsel: evsel, /) -> int:
"""Add an event to the list."""
...
+ def __len__(self) -> int: ...
+ def __getitem__(self, index: int) -> evsel: ...
def __iter__(self) -> Iterator[evsel]:
"""Iterate over the events (evsel) in the list."""
...
+class call_return:
+ """Represents a call/return event from instruction trace decoding."""
+ db_id: int
+ parent_id: int
+ insn_count: int
+ cyc_count: int
+ comm: Optional[str]
+ machine_pid: int
+ pid: Optional[int]
+ tid: Optional[int]
+ call_time: int
+ return_time: int
+ branch_count: int
+ call_ref: int
+ return_ref: int
+ flags: int
+ call_path: Optional[callchain]
+
+
class session:
def __init__(
self,
@@ -455,6 +483,11 @@ class session:
sample: Optional[Callable[[sample_event], None]] = None,
stat: Optional[Callable[[Any, Optional[str]], None]] = None,
context_switch: Optional[Callable[[switch_event], None]] = None,
+ call_return: Optional[Callable[[call_return], None]] = None,
+ itrace: Optional[str] = None,
+ vmlinux: Optional[str] = None,
+ kallsyms: Optional[str] = None,
+ symfs: Optional[str] = None
) -> None:
"""Initialize a perf session.
@@ -464,6 +497,8 @@ class session:
stat: Callback for stat events.
"""
...
+ e_machine: int
+ is_64_bit: bool
def process_events(self) -> None:
"""Process all events in the session."""
...
@@ -696,3 +731,12 @@ RECORD_STAT_ROUND: int
RECORD_MISC_SWITCH_OUT: int
"""MISC_SWITCH_OUT record."""
+
+CALL_RETURN_NO_CALL: int
+"""'return' but no matching 'call'."""
+
+CALL_RETURN_NO_RETURN: int
+"""'call' but no matching 'return'."""
+
+CALL_RETURN_NON_CALL: int
+"""A branch but not a 'call' to the start of a different symbol."""