cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

libxed.py (3395B)


      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