Back to home page

OSCL-LXR

 
 

    


0001 #!/usr/bin/env python
0002 # SPDX-License-Identifier: GPL-2.0
0003 # libxed.py: Python wrapper for libxed.so
0004 # Copyright (c) 2014-2021, Intel Corporation.
0005 
0006 # To use Intel XED, libxed.so must be present. To build and install
0007 # libxed.so:
0008 #            git clone https://github.com/intelxed/mbuild.git mbuild
0009 #            git clone https://github.com/intelxed/xed
0010 #            cd xed
0011 #            ./mfile.py --share
0012 #            sudo ./mfile.py --prefix=/usr/local install
0013 #            sudo ldconfig
0014 #
0015 
0016 import sys
0017 
0018 from ctypes import CDLL, Structure, create_string_buffer, addressof, sizeof, \
0019            c_void_p, c_bool, c_byte, c_char, c_int, c_uint, c_longlong, c_ulonglong
0020 
0021 # XED Disassembler
0022 
0023 class xed_state_t(Structure):
0024 
0025     _fields_ = [
0026         ("mode", c_int),
0027         ("width", c_int)
0028     ]
0029 
0030 class XEDInstruction():
0031 
0032     def __init__(self, libxed):
0033         # Current xed_decoded_inst_t structure is 192 bytes. Use 512 to allow for future expansion
0034         xedd_t = c_byte * 512
0035         self.xedd = xedd_t()
0036         self.xedp = addressof(self.xedd)
0037         libxed.xed_decoded_inst_zero(self.xedp)
0038         self.state = xed_state_t()
0039         self.statep = addressof(self.state)
0040         # Buffer for disassembled instruction text
0041         self.buffer = create_string_buffer(256)
0042         self.bufferp = addressof(self.buffer)
0043 
0044 class LibXED():
0045 
0046     def __init__(self):
0047         try:
0048             self.libxed = CDLL("libxed.so")
0049         except:
0050             self.libxed = None
0051         if not self.libxed:
0052             self.libxed = CDLL("/usr/local/lib/libxed.so")
0053 
0054         self.xed_tables_init = self.libxed.xed_tables_init
0055         self.xed_tables_init.restype = None
0056         self.xed_tables_init.argtypes = []
0057 
0058         self.xed_decoded_inst_zero = self.libxed.xed_decoded_inst_zero
0059         self.xed_decoded_inst_zero.restype = None
0060         self.xed_decoded_inst_zero.argtypes = [ c_void_p ]
0061 
0062         self.xed_operand_values_set_mode = self.libxed.xed_operand_values_set_mode
0063         self.xed_operand_values_set_mode.restype = None
0064         self.xed_operand_values_set_mode.argtypes = [ c_void_p, c_void_p ]
0065 
0066         self.xed_decoded_inst_zero_keep_mode = self.libxed.xed_decoded_inst_zero_keep_mode
0067         self.xed_decoded_inst_zero_keep_mode.restype = None
0068         self.xed_decoded_inst_zero_keep_mode.argtypes = [ c_void_p ]
0069 
0070         self.xed_decode = self.libxed.xed_decode
0071         self.xed_decode.restype = c_int
0072         self.xed_decode.argtypes = [ c_void_p, c_void_p, c_uint ]
0073 
0074         self.xed_format_context = self.libxed.xed_format_context
0075         self.xed_format_context.restype = c_uint
0076         self.xed_format_context.argtypes = [ c_int, c_void_p, c_void_p, c_int, c_ulonglong, c_void_p, c_void_p ]
0077 
0078         self.xed_tables_init()
0079 
0080     def Instruction(self):
0081         return XEDInstruction(self)
0082 
0083     def SetMode(self, inst, mode):
0084         if mode:
0085             inst.state.mode = 4 # 32-bit
0086             inst.state.width = 4 # 4 bytes
0087         else:
0088             inst.state.mode = 1 # 64-bit
0089             inst.state.width = 8 # 8 bytes
0090         self.xed_operand_values_set_mode(inst.xedp, inst.statep)
0091 
0092     def DisassembleOne(self, inst, bytes_ptr, bytes_cnt, ip):
0093         self.xed_decoded_inst_zero_keep_mode(inst.xedp)
0094         err = self.xed_decode(inst.xedp, bytes_ptr, bytes_cnt)
0095         if err:
0096             return 0, ""
0097         # Use AT&T mode (2), alternative is Intel (3)
0098         ok = self.xed_format_context(2, inst.xedp, inst.bufferp, sizeof(inst.buffer), ip, 0, 0)
0099         if not ok:
0100             return 0, ""
0101         if sys.version_info[0] == 2:
0102             result = inst.buffer.value
0103         else:
0104             result = inst.buffer.value.decode()
0105         # Return instruction length and the disassembled instruction text
0106         # For now, assume the length is in byte 166
0107         return inst.xedd[166], result