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 | import random | 113 | import random |
| 114 | import copy | 114 | import copy |
| 115 | import math | 115 | import math |
| 116 | from libxed import LibXED | ||
| 116 | 117 | ||
| 117 | pyside_version_1 = True | 118 | pyside_version_1 = True |
| 118 | if not "--pyside-version-1" in sys.argv: | 119 | if not "--pyside-version-1" in sys.argv: |
| @@ -4747,94 +4748,6 @@ class MainWindow(QMainWindow): · 4628 unmodified lines | |||
| 4747 | dialog = AboutDialog(self.glb, self) | 4748 | dialog = AboutDialog(self.glb, self) |
| 4748 | dialog.exec_() | 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 | def TryOpen(file_name): | 4751 | def TryOpen(file_name): |
| 4839 | try: | 4752 | try: |
| 4840 | return open(file_name, "rb") | 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 | ||