mirror of
https://github.com/torvalds/linux.git
synced 2026-11-10 17:11:02 +01:00
Port intel-pt-events.py and libxed.py from tools/perf/scripts/python/ to standalone modules in tools/perf/python/: - Refactor intel-pt-events.py into an IntelPTAnalyzer class with full type annotations to encapsulate trace state and stashed output. - Configure instruction trace decoding directly via perf.session's itrace option and context_switch callback. - Dynamically select 32-bit vs 64-bit disassembly mode in libxed.py using session.is_64_bit and annotate instructions with source lines via sample.srccode(). - Rename methods in libxed.py to snake_case (instruction, set_mode, disassemble_one) and remove Python 2 compatibility code. Add a shell test (test_intel_pt_events_python.sh) to verify the standalone script. Assisted-by: Antigravity:gemini-3.1-pro Signed-off-by: Ian Rogers <irogers@google.com> Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
124 lines
4.2 KiB
Python
Executable File
124 lines
4.2 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
# SPDX-License-Identifier: GPL-2.0
|
|
"""
|
|
Python wrapper for libxed.so
|
|
Ported from tools/perf/scripts/python/libxed.py
|
|
"""
|
|
from __future__ import annotations
|
|
|
|
from ctypes import CDLL, Structure, create_string_buffer, addressof, sizeof, \
|
|
c_void_p, c_byte, c_int, c_uint, c_ulonglong
|
|
|
|
# To use Intel XED, libxed.so must be present. To build and install
|
|
# libxed.so:
|
|
# git clone https://github.com/intelxed/mbuild.git mbuild
|
|
# git clone https://github.com/intelxed/xed
|
|
# cd xed
|
|
# ./mfile.py --share
|
|
# sudo ./mfile.py --prefix=/usr/local install
|
|
# sudo ldconfig
|
|
#
|
|
|
|
|
|
class XedStateT(Structure):
|
|
"""xed_state_t structure."""
|
|
_fields_ = [
|
|
("mode", c_int),
|
|
("width", c_int)
|
|
]
|
|
|
|
|
|
class XEDInstruction():
|
|
"""Represents a decoded instruction."""
|
|
|
|
def __init__(self, libxed):
|
|
# Current xed_decoded_inst_t structure is 192 bytes. Use 512 to allow for future expansion
|
|
xedd_t = c_byte * 512
|
|
self.xedd = xedd_t()
|
|
self.xedp = addressof(self.xedd)
|
|
libxed.xed_decoded_inst_zero(self.xedp)
|
|
self.state = XedStateT()
|
|
self.statep = addressof(self.state)
|
|
# Buffer for disassembled instruction text
|
|
self.buffer = create_string_buffer(256)
|
|
self.bufferp = addressof(self.buffer)
|
|
|
|
|
|
class LibXED():
|
|
"""Wrapper for libxed.so."""
|
|
|
|
def __init__(self):
|
|
try:
|
|
self.libxed = CDLL("libxed.so")
|
|
except OSError:
|
|
self.libxed = None
|
|
if not self.libxed:
|
|
try:
|
|
self.libxed = CDLL("/usr/local/lib/libxed.so")
|
|
except OSError:
|
|
self.libxed = None
|
|
|
|
if not self.libxed:
|
|
raise ImportError("libxed.so not found. Please install Intel XED.")
|
|
|
|
self.xed_tables_init = self.libxed.xed_tables_init
|
|
self.xed_tables_init.restype = None
|
|
self.xed_tables_init.argtypes = []
|
|
|
|
self.xed_decoded_inst_zero = self.libxed.xed_decoded_inst_zero
|
|
self.xed_decoded_inst_zero.restype = None
|
|
self.xed_decoded_inst_zero.argtypes = [c_void_p]
|
|
|
|
self.xed_operand_values_set_mode = self.libxed.xed_operand_values_set_mode
|
|
self.xed_operand_values_set_mode.restype = None
|
|
self.xed_operand_values_set_mode.argtypes = [c_void_p, c_void_p]
|
|
|
|
self.xed_decoded_inst_zero_keep_mode = self.libxed.xed_decoded_inst_zero_keep_mode
|
|
self.xed_decoded_inst_zero_keep_mode.restype = None
|
|
self.xed_decoded_inst_zero_keep_mode.argtypes = [c_void_p]
|
|
|
|
self.xed_decode = self.libxed.xed_decode
|
|
self.xed_decode.restype = c_int
|
|
self.xed_decode.argtypes = [c_void_p, c_void_p, c_uint]
|
|
|
|
self.xed_format_context = self.libxed.xed_format_context
|
|
self.xed_format_context.restype = c_uint
|
|
self.xed_format_context.argtypes = [
|
|
c_int, c_void_p, c_void_p, c_int, c_ulonglong, c_void_p, c_void_p
|
|
]
|
|
|
|
self.xed_decoded_inst_get_length = self.libxed.xed_decoded_inst_get_length
|
|
self.xed_decoded_inst_get_length.restype = c_uint
|
|
self.xed_decoded_inst_get_length.argtypes = [c_void_p]
|
|
|
|
self.xed_tables_init()
|
|
|
|
def instruction(self):
|
|
"""Create a new XEDInstruction."""
|
|
return XEDInstruction(self)
|
|
|
|
def set_mode(self, inst, mode):
|
|
"""Set 32-bit or 64-bit mode."""
|
|
if mode:
|
|
inst.state.mode = 4 # 32-bit
|
|
inst.state.width = 4 # 4 bytes
|
|
else:
|
|
inst.state.mode = 1 # 64-bit
|
|
inst.state.width = 8 # 8 bytes
|
|
self.xed_operand_values_set_mode(inst.xedp, inst.statep)
|
|
|
|
def disassemble_one(self, inst, bytes_ptr, bytes_cnt, ip):
|
|
"""Disassemble one instruction."""
|
|
self.xed_decoded_inst_zero_keep_mode(inst.xedp)
|
|
err = self.xed_decode(inst.xedp, bytes_ptr, bytes_cnt)
|
|
if err:
|
|
return 0, ""
|
|
# Use AT&T mode (2), alternative is Intel (3)
|
|
ok = self.xed_format_context(2, inst.xedp, inst.bufferp, sizeof(inst.buffer), ip, 0, 0)
|
|
if not ok:
|
|
return 0, ""
|
|
|
|
result = inst.buffer.value.decode('utf-8')
|
|
# Return instruction length and the disassembled instruction text
|
|
return self.xed_decoded_inst_get_length(inst.xedp), result
|