Factor out libxed.py so it can be reused.
Showing the changes to tools/perf/scripts/python (2 of 2 files). Show all
Unified · Split
| @@ -113,6 +113,7 @@ import os · 112 unmodified lines | ||
| 113 | 113 | import random |
| 114 | 114 | import copy |
| 115 | 115 | import math |
| 116 | +from libxed import LibXED | |
| 116 | 117 | |
| 117 | 118 | pyside_version_1 = True |
| 118 | 119 | if not "--pyside-version-1" in sys.argv: |
| @@ -4747,94 +4748,6 @@ class MainWindow(QMainWindow): · 4628 unmodified lines | ||
| 4747 | 4748 | dialog = AboutDialog(self.glb, self) |
| 4748 | 4749 | dialog.exec_() |
| 4749 | 4750 | |
| 4750 | −# XED Disassembler | |
| 4751 | − | |
| 4752 | −class xed_state_t(Structure): | |
| 4753 | − | |
| 4754 | − _fields_ = [ | |
| 4755 | − ("mode", c_int), | |
| 4756 | − ("width", c_int) | |
| 4757 | − ] | |
| 4758 | − | |
| 4759 | −class XEDInstruction(): | |
| 4760 | − | |
| 4761 | − def __init__(self, libxed): | |
| 4762 | − # Current xed_decoded_inst_t structure is 192 bytes. Use 512 to allow for future expansion | |
| 4763 | − xedd_t = c_byte * 512 | |
| 4764 | − self.xedd = xedd_t() | |
| 4765 | − self.xedp = addressof(self.xedd) | |
| 4766 | − libxed.xed_decoded_inst_zero(self.xedp) | |
| 4767 | − self.state = xed_state_t() | |
| 4768 | − self.statep = addressof(self.state) | |
| 4769 | − # Buffer for disassembled instruction text | |
| 4770 | − self.buffer = create_string_buffer(256) | |
| 4771 | − self.bufferp = addressof(self.buffer) | |
| 4772 | − | |
| 4773 | −class LibXED(): | |
| 4774 | − | |
| 4775 | − def __init__(self): | |
| 4776 | − try: | |
| 4777 | − self.libxed = CDLL("libxed.so") | |
| 4778 | − except: | |
| 4779 | − self.libxed = None | |
| 4780 | − if not self.libxed: | |
| 4781 | − self.libxed = CDLL("/usr/local/lib/libxed.so") | |
| 4782 | − | |
| 4783 | − self.xed_tables_init = self.libxed.xed_tables_init | |
| 4784 | − self.xed_tables_init.restype = None | |
| 4785 | − self.xed_tables_init.argtypes = [] | |
| 4786 | − | |
| 4787 | − self.xed_decoded_inst_zero = self.libxed.xed_decoded_inst_zero | |
| 4788 | − self.xed_decoded_inst_zero.restype = None | |
| 4789 | − self.xed_decoded_inst_zero.argtypes = [ c_void_p ] | |
| 4790 | − | |
| 4791 | − self.xed_operand_values_set_mode = self.libxed.xed_operand_values_set_mode | |
| 4792 | − self.xed_operand_values_set_mode.restype = None | |
| 4793 | − self.xed_operand_values_set_mode.argtypes = [ c_void_p, c_void_p ] | |
| 4794 | − | |
| 4795 | − self.xed_decoded_inst_zero_keep_mode = self.libxed.xed_decoded_inst_zero_keep_mode | |
| 4796 | − self.xed_decoded_inst_zero_keep_mode.restype = None | |
| 4797 | − self.xed_decoded_inst_zero_keep_mode.argtypes = [ c_void_p ] | |
| 4798 | − | |
| 4799 | − self.xed_decode = self.libxed.xed_decode | |
| 4800 | − self.xed_decode.restype = c_int | |
| 4801 | − self.xed_decode.argtypes = [ c_void_p, c_void_p, c_uint ] | |
| 4802 | − | |
| 4803 | − self.xed_format_context = self.libxed.xed_format_context | |
| 4804 | − self.xed_format_context.restype = c_uint | |
| 4805 | − self.xed_format_context.argtypes = [ c_int, c_void_p, c_void_p, c_int, c_ulonglong, c_void_p, c_void_p ] | |
| 4806 | − | |
| 4807 | − self.xed_tables_init() | |
| 4808 | − | |
| 4809 | − def Instruction(self): | |
| 4810 | − return XEDInstruction(self) | |
| 4811 | − | |
| 4812 | − def SetMode(self, inst, mode): | |
| 4813 | − if mode: | |
| 4814 | − inst.state.mode = 4 # 32-bit | |
| 4815 | − inst.state.width = 4 # 4 bytes | |
| 4816 | − else: | |
| 4817 | − inst.state.mode = 1 # 64-bit | |
| 4818 | − inst.state.width = 8 # 8 bytes | |
| 4819 | − self.xed_operand_values_set_mode(inst.xedp, inst.statep) | |
| 4820 | − | |
| 4821 | − def DisassembleOne(self, inst, bytes_ptr, bytes_cnt, ip): | |
| 4822 | − self.xed_decoded_inst_zero_keep_mode(inst.xedp) | |
| 4823 | − err = self.xed_decode(inst.xedp, bytes_ptr, bytes_cnt) | |
| 4824 | − if err: | |
| 4825 | − return 0, "" | |
| 4826 | − # Use AT&T mode (2), alternative is Intel (3) | |
| 4827 | − ok = self.xed_format_context(2, inst.xedp, inst.bufferp, sizeof(inst.buffer), ip, 0, 0) | |
| 4828 | − if not ok: | |
| 4829 | − return 0, "" | |
| 4830 | − if sys.version_info[0] == 2: | |
| 4831 | − result = inst.buffer.value | |
| 4832 | − else: | |
| 4833 | − result = inst.buffer.value.decode() | |
| 4834 | − # Return instruction length and the disassembled instruction text | |
| 4835 | − # For now, assume the length is in byte 166 | |
| 4836 | − return inst.xedd[166], result | |
| 4837 | − | |
| 4838 | 4751 | def TryOpen(file_name): |
| 4839 | 4752 | try: |
| 4840 | 4753 | return open(file_name, "rb") |
| @@ -0,0 +1,107 @@ | ||
| 1 | +#!/usr/bin/env python | |
| 2 | +# SPDX-License-Identifier: GPL-2.0 | |
| 3 | +# libxed.py: Python wrapper for libxed.so | |
| 4 | +# Copyright (c) 2014-2021, Intel Corporation. | |
| 5 | + | |
| 6 | +# To use Intel XED, libxed.so must be present. To build and install | |
| 7 | +# libxed.so: | |
| 8 | +# git clone https://github.com/intelxed/mbuild.git mbuild | |
| 9 | +# git clone https://github.com/intelxed/xed | |
| 10 | +# cd xed | |
| 11 | +# ./mfile.py --share | |
| 12 | +# sudo ./mfile.py --prefix=/usr/local install | |
| 13 | +# sudo ldconfig | |
| 14 | +# | |
| 15 | + | |
| 16 | +import sys | |
| 17 | + | |
| 18 | +from ctypes import CDLL, Structure, create_string_buffer, addressof, sizeof, \ | |
| 19 | + c_void_p, c_bool, c_byte, c_char, c_int, c_uint, c_longlong, c_ulonglong | |
| 20 | + | |
| 21 | +# XED Disassembler | |
| 22 | + | |
| 23 | +class xed_state_t(Structure): | |
| 24 | + | |
| 25 | + _fields_ = [ | |
| 26 | + ("mode", c_int), | |
| 27 | + ("width", c_int) | |
| 28 | + ] | |
| 29 | + | |
| 30 | +class XEDInstruction(): | |
| 31 | + | |
| 32 | + def __init__(self, libxed): | |
| 33 | + # Current xed_decoded_inst_t structure is 192 bytes. Use 512 to allow for future expansion | |
| 34 | + xedd_t = c_byte * 512 | |
| 35 | + self.xedd = xedd_t() | |
| 36 | + self.xedp = addressof(self.xedd) | |
| 37 | + libxed.xed_decoded_inst_zero(self.xedp) | |
| 38 | + self.state = xed_state_t() | |
| 39 | + self.statep = addressof(self.state) | |
| 40 | + # Buffer for disassembled instruction text | |
| 41 | + self.buffer = create_string_buffer(256) | |
| 42 | + self.bufferp = addressof(self.buffer) | |
| 43 | + | |
| 44 | +class LibXED(): | |
| 45 | + | |
| 46 | + def __init__(self): | |
| 47 | + try: | |
| 48 | + self.libxed = CDLL("libxed.so") | |
| 49 | + except: | |
| 50 | + self.libxed = None | |
| 51 | + if not self.libxed: | |
| 52 | + self.libxed = CDLL("/usr/local/lib/libxed.so") | |
| 53 | + | |
| 54 | + self.xed_tables_init = self.libxed.xed_tables_init | |
| 55 | + self.xed_tables_init.restype = None | |
| 56 | + self.xed_tables_init.argtypes = [] | |
| 57 | + | |
| 58 | + self.xed_decoded_inst_zero = self.libxed.xed_decoded_inst_zero | |
| 59 | + self.xed_decoded_inst_zero.restype = None | |
| 60 | + self.xed_decoded_inst_zero.argtypes = [ c_void_p ] | |
| 61 | + | |
| 62 | + self.xed_operand_values_set_mode = self.libxed.xed_operand_values_set_mode | |
| 63 | + self.xed_operand_values_set_mode.restype = None | |
| 64 | + self.xed_operand_values_set_mode.argtypes = [ c_void_p, c_void_p ] | |
| 65 | + | |
| 66 | + self.xed_decoded_inst_zero_keep_mode = self.libxed.xed_decoded_inst_zero_keep_mode | |
| 67 | + self.xed_decoded_inst_zero_keep_mode.restype = None | |
| 68 | + self.xed_decoded_inst_zero_keep_mode.argtypes = [ c_void_p ] | |
| 69 | + | |
| 70 | + self.xed_decode = self.libxed.xed_decode | |
| 71 | + self.xed_decode.restype = c_int | |
| 72 | + self.xed_decode.argtypes = [ c_void_p, c_void_p, c_uint ] | |
| 73 | + | |
| 74 | + self.xed_format_context = self.libxed.xed_format_context | |
| 75 | + self.xed_format_context.restype = c_uint | |
| 76 | + self.xed_format_context.argtypes = [ c_int, c_void_p, c_void_p, c_int, c_ulonglong, c_void_p, c_void_p ] | |
| 77 | + | |
| 78 | + self.xed_tables_init() | |
| 79 | + | |
| 80 | + def Instruction(self): | |
| 81 | + return XEDInstruction(self) | |
| 82 | + | |
| 83 | + def SetMode(self, inst, mode): | |
| 84 | + if mode: | |
| 85 | + inst.state.mode = 4 # 32-bit | |
| 86 | + inst.state.width = 4 # 4 bytes | |
| 87 | + else: | |
| 88 | + inst.state.mode = 1 # 64-bit | |
| 89 | + inst.state.width = 8 # 8 bytes | |
| 90 | + self.xed_operand_values_set_mode(inst.xedp, inst.statep) | |
| 91 | + | |
| 92 | + def DisassembleOne(self, inst, bytes_ptr, bytes_cnt, ip): | |
| 93 | + self.xed_decoded_inst_zero_keep_mode(inst.xedp) | |
| 94 | + err = self.xed_decode(inst.xedp, bytes_ptr, bytes_cnt) | |
| 95 | + if err: | |
| 96 | + return 0, "" | |
| 97 | + # Use AT&T mode (2), alternative is Intel (3) | |
| 98 | + ok = self.xed_format_context(2, inst.xedp, inst.bufferp, sizeof(inst.buffer), ip, 0, 0) | |
| 99 | + if not ok: | |
| 100 | + return 0, "" | |
| 101 | + if sys.version_info[0] == 2: | |
| 102 | + result = inst.buffer.value | |
| 103 | + else: | |
| 104 | + result = inst.buffer.value.decode() | |
| 105 | + # Return instruction length and the disassembled instruction text | |
| 106 | + # For now, assume the length is in byte 166 | |
| 107 | + return inst.xedd[166], result | |