diff options
Diffstat (limited to 'tools/perf/scripts/python/libxed.py')
| -rw-r--r-- | tools/perf/scripts/python/libxed.py | 107 | 
1 files changed, 107 insertions, 0 deletions
| diff --git a/tools/perf/scripts/python/libxed.py b/tools/perf/scripts/python/libxed.py new file mode 100644 index 000000000000..2c70a5a7eb9c --- /dev/null +++ b/tools/perf/scripts/python/libxed.py @@ -0,0 +1,107 @@ +#!/usr/bin/env python +# SPDX-License-Identifier: GPL-2.0 +# libxed.py: Python wrapper for libxed.so +# Copyright (c) 2014-2021, Intel Corporation. + +# 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 +# + +import sys + +from ctypes import CDLL, Structure, create_string_buffer, addressof, sizeof, \ +		   c_void_p, c_bool, c_byte, c_char, c_int, c_uint, c_longlong, c_ulonglong + +# XED Disassembler + +class xed_state_t(Structure): + +	_fields_ = [ +		("mode", c_int), +		("width", c_int) +	] + +class XEDInstruction(): + +	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 = xed_state_t() +		self.statep = addressof(self.state) +		# Buffer for disassembled instruction text +		self.buffer = create_string_buffer(256) +		self.bufferp = addressof(self.buffer) + +class LibXED(): + +	def __init__(self): +		try: +			self.libxed = CDLL("libxed.so") +		except: +			self.libxed = None +		if not self.libxed: +			self.libxed = CDLL("/usr/local/lib/libxed.so") + +		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_tables_init() + +	def Instruction(self): +		return XEDInstruction(self) + +	def SetMode(self, inst, 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 DisassembleOne(self, inst, bytes_ptr, bytes_cnt, ip): +		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, "" +		if sys.version_info[0] == 2: +			result = inst.buffer.value +		else: +			result = inst.buffer.value.decode() +		# Return instruction length and the disassembled instruction text +		# For now, assume the length is in byte 166 +		return inst.xedd[166], result | 
