1*2b87386cSAdrian Hunter#!/usr/bin/env python 2*2b87386cSAdrian Hunter# SPDX-License-Identifier: GPL-2.0 3*2b87386cSAdrian Hunter# libxed.py: Python wrapper for libxed.so 4*2b87386cSAdrian Hunter# Copyright (c) 2014-2021, Intel Corporation. 5*2b87386cSAdrian Hunter 6*2b87386cSAdrian Hunter# To use Intel XED, libxed.so must be present. To build and install 7*2b87386cSAdrian Hunter# libxed.so: 8*2b87386cSAdrian Hunter# git clone https://github.com/intelxed/mbuild.git mbuild 9*2b87386cSAdrian Hunter# git clone https://github.com/intelxed/xed 10*2b87386cSAdrian Hunter# cd xed 11*2b87386cSAdrian Hunter# ./mfile.py --share 12*2b87386cSAdrian Hunter# sudo ./mfile.py --prefix=/usr/local install 13*2b87386cSAdrian Hunter# sudo ldconfig 14*2b87386cSAdrian Hunter# 15*2b87386cSAdrian Hunter 16*2b87386cSAdrian Hunterimport sys 17*2b87386cSAdrian Hunter 18*2b87386cSAdrian Hunterfrom ctypes import CDLL, Structure, create_string_buffer, addressof, sizeof, \ 19*2b87386cSAdrian Hunter c_void_p, c_bool, c_byte, c_char, c_int, c_uint, c_longlong, c_ulonglong 20*2b87386cSAdrian Hunter 21*2b87386cSAdrian Hunter# XED Disassembler 22*2b87386cSAdrian Hunter 23*2b87386cSAdrian Hunterclass xed_state_t(Structure): 24*2b87386cSAdrian Hunter 25*2b87386cSAdrian Hunter _fields_ = [ 26*2b87386cSAdrian Hunter ("mode", c_int), 27*2b87386cSAdrian Hunter ("width", c_int) 28*2b87386cSAdrian Hunter ] 29*2b87386cSAdrian Hunter 30*2b87386cSAdrian Hunterclass XEDInstruction(): 31*2b87386cSAdrian Hunter 32*2b87386cSAdrian Hunter def __init__(self, libxed): 33*2b87386cSAdrian Hunter # Current xed_decoded_inst_t structure is 192 bytes. Use 512 to allow for future expansion 34*2b87386cSAdrian Hunter xedd_t = c_byte * 512 35*2b87386cSAdrian Hunter self.xedd = xedd_t() 36*2b87386cSAdrian Hunter self.xedp = addressof(self.xedd) 37*2b87386cSAdrian Hunter libxed.xed_decoded_inst_zero(self.xedp) 38*2b87386cSAdrian Hunter self.state = xed_state_t() 39*2b87386cSAdrian Hunter self.statep = addressof(self.state) 40*2b87386cSAdrian Hunter # Buffer for disassembled instruction text 41*2b87386cSAdrian Hunter self.buffer = create_string_buffer(256) 42*2b87386cSAdrian Hunter self.bufferp = addressof(self.buffer) 43*2b87386cSAdrian Hunter 44*2b87386cSAdrian Hunterclass LibXED(): 45*2b87386cSAdrian Hunter 46*2b87386cSAdrian Hunter def __init__(self): 47*2b87386cSAdrian Hunter try: 48*2b87386cSAdrian Hunter self.libxed = CDLL("libxed.so") 49*2b87386cSAdrian Hunter except: 50*2b87386cSAdrian Hunter self.libxed = None 51*2b87386cSAdrian Hunter if not self.libxed: 52*2b87386cSAdrian Hunter self.libxed = CDLL("/usr/local/lib/libxed.so") 53*2b87386cSAdrian Hunter 54*2b87386cSAdrian Hunter self.xed_tables_init = self.libxed.xed_tables_init 55*2b87386cSAdrian Hunter self.xed_tables_init.restype = None 56*2b87386cSAdrian Hunter self.xed_tables_init.argtypes = [] 57*2b87386cSAdrian Hunter 58*2b87386cSAdrian Hunter self.xed_decoded_inst_zero = self.libxed.xed_decoded_inst_zero 59*2b87386cSAdrian Hunter self.xed_decoded_inst_zero.restype = None 60*2b87386cSAdrian Hunter self.xed_decoded_inst_zero.argtypes = [ c_void_p ] 61*2b87386cSAdrian Hunter 62*2b87386cSAdrian Hunter self.xed_operand_values_set_mode = self.libxed.xed_operand_values_set_mode 63*2b87386cSAdrian Hunter self.xed_operand_values_set_mode.restype = None 64*2b87386cSAdrian Hunter self.xed_operand_values_set_mode.argtypes = [ c_void_p, c_void_p ] 65*2b87386cSAdrian Hunter 66*2b87386cSAdrian Hunter self.xed_decoded_inst_zero_keep_mode = self.libxed.xed_decoded_inst_zero_keep_mode 67*2b87386cSAdrian Hunter self.xed_decoded_inst_zero_keep_mode.restype = None 68*2b87386cSAdrian Hunter self.xed_decoded_inst_zero_keep_mode.argtypes = [ c_void_p ] 69*2b87386cSAdrian Hunter 70*2b87386cSAdrian Hunter self.xed_decode = self.libxed.xed_decode 71*2b87386cSAdrian Hunter self.xed_decode.restype = c_int 72*2b87386cSAdrian Hunter self.xed_decode.argtypes = [ c_void_p, c_void_p, c_uint ] 73*2b87386cSAdrian Hunter 74*2b87386cSAdrian Hunter self.xed_format_context = self.libxed.xed_format_context 75*2b87386cSAdrian Hunter self.xed_format_context.restype = c_uint 76*2b87386cSAdrian Hunter self.xed_format_context.argtypes = [ c_int, c_void_p, c_void_p, c_int, c_ulonglong, c_void_p, c_void_p ] 77*2b87386cSAdrian Hunter 78*2b87386cSAdrian Hunter self.xed_tables_init() 79*2b87386cSAdrian Hunter 80*2b87386cSAdrian Hunter def Instruction(self): 81*2b87386cSAdrian Hunter return XEDInstruction(self) 82*2b87386cSAdrian Hunter 83*2b87386cSAdrian Hunter def SetMode(self, inst, mode): 84*2b87386cSAdrian Hunter if mode: 85*2b87386cSAdrian Hunter inst.state.mode = 4 # 32-bit 86*2b87386cSAdrian Hunter inst.state.width = 4 # 4 bytes 87*2b87386cSAdrian Hunter else: 88*2b87386cSAdrian Hunter inst.state.mode = 1 # 64-bit 89*2b87386cSAdrian Hunter inst.state.width = 8 # 8 bytes 90*2b87386cSAdrian Hunter self.xed_operand_values_set_mode(inst.xedp, inst.statep) 91*2b87386cSAdrian Hunter 92*2b87386cSAdrian Hunter def DisassembleOne(self, inst, bytes_ptr, bytes_cnt, ip): 93*2b87386cSAdrian Hunter self.xed_decoded_inst_zero_keep_mode(inst.xedp) 94*2b87386cSAdrian Hunter err = self.xed_decode(inst.xedp, bytes_ptr, bytes_cnt) 95*2b87386cSAdrian Hunter if err: 96*2b87386cSAdrian Hunter return 0, "" 97*2b87386cSAdrian Hunter # Use AT&T mode (2), alternative is Intel (3) 98*2b87386cSAdrian Hunter ok = self.xed_format_context(2, inst.xedp, inst.bufferp, sizeof(inst.buffer), ip, 0, 0) 99*2b87386cSAdrian Hunter if not ok: 100*2b87386cSAdrian Hunter return 0, "" 101*2b87386cSAdrian Hunter if sys.version_info[0] == 2: 102*2b87386cSAdrian Hunter result = inst.buffer.value 103*2b87386cSAdrian Hunter else: 104*2b87386cSAdrian Hunter result = inst.buffer.value.decode() 105*2b87386cSAdrian Hunter # Return instruction length and the disassembled instruction text 106*2b87386cSAdrian Hunter # For now, assume the length is in byte 166 107*2b87386cSAdrian Hunter return inst.xedd[166], result 108