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 16import sys 17 18from 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 23class xed_state_t(Structure): 24 25 _fields_ = [ 26 ("mode", c_int), 27 ("width", c_int) 28 ] 29 30class 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 44class 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 108