libxed.py 3.3 KB

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