1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
|
#!/usr/bin/env python3
# SPDX-License-Identifier: GPL-2.0
"""
Python wrapper for libxed.so
Ported from tools/perf/scripts/python/libxed.py
"""
from __future__ import annotations
from ctypes import CDLL, Structure, create_string_buffer, addressof, sizeof, \
c_void_p, c_byte, c_int, c_uint, c_ulonglong
# To use Intel XED, libxed.so must be present. To build and install
# libxed.so:
# git clone https://github.com/intelxed/mbuild.git mbuild
# git clone https://github.com/intelxed/xed
# cd xed
# ./mfile.py --share
# sudo ./mfile.py --prefix=/usr/local install
# sudo ldconfig
#
class XedStateT(Structure):
"""xed_state_t structure."""
_fields_ = [
("mode", c_int),
("width", c_int)
]
class XEDInstruction():
"""Represents a decoded instruction."""
def __init__(self, libxed):
# Current xed_decoded_inst_t structure is 192 bytes. Use 512 to allow for future expansion
xedd_t = c_byte * 512
self.xedd = xedd_t()
self.xedp = addressof(self.xedd)
libxed.xed_decoded_inst_zero(self.xedp)
self.state = XedStateT()
self.statep = addressof(self.state)
# Buffer for disassembled instruction text
self.buffer = create_string_buffer(256)
self.bufferp = addressof(self.buffer)
class LibXED():
"""Wrapper for libxed.so."""
def __init__(self):
try:
self.libxed = CDLL("libxed.so")
except OSError:
self.libxed = None
if not self.libxed:
try:
self.libxed = CDLL("/usr/local/lib/libxed.so")
except OSError:
self.libxed = None
if not self.libxed:
raise ImportError("libxed.so not found. Please install Intel XED.")
self.xed_tables_init = self.libxed.xed_tables_init
self.xed_tables_init.restype = None
self.xed_tables_init.argtypes = []
self.xed_decoded_inst_zero = self.libxed.xed_decoded_inst_zero
self.xed_decoded_inst_zero.restype = None
self.xed_decoded_inst_zero.argtypes = [c_void_p]
self.xed_operand_values_set_mode = self.libxed.xed_operand_values_set_mode
self.xed_operand_values_set_mode.restype = None
self.xed_operand_values_set_mode.argtypes = [c_void_p, c_void_p]
self.xed_decoded_inst_zero_keep_mode = self.libxed.xed_decoded_inst_zero_keep_mode
self.xed_decoded_inst_zero_keep_mode.restype = None
self.xed_decoded_inst_zero_keep_mode.argtypes = [c_void_p]
self.xed_decode = self.libxed.xed_decode
self.xed_decode.restype = c_int
self.xed_decode.argtypes = [c_void_p, c_void_p, c_uint]
self.xed_format_context = self.libxed.xed_format_context
self.xed_format_context.restype = c_uint
self.xed_format_context.argtypes = [
c_int, c_void_p, c_void_p, c_int, c_ulonglong, c_void_p, c_void_p
]
self.xed_decoded_inst_get_length = self.libxed.xed_decoded_inst_get_length
self.xed_decoded_inst_get_length.restype = c_uint
self.xed_decoded_inst_get_length.argtypes = [c_void_p]
self.xed_tables_init()
def instruction(self):
"""Create a new XEDInstruction."""
return XEDInstruction(self)
def set_mode(self, inst, mode):
"""Set 32-bit or 64-bit mode."""
if mode:
inst.state.mode = 4 # 32-bit
inst.state.width = 4 # 4 bytes
else:
inst.state.mode = 1 # 64-bit
inst.state.width = 8 # 8 bytes
self.xed_operand_values_set_mode(inst.xedp, inst.statep)
def disassemble_one(self, inst, bytes_ptr, bytes_cnt, ip):
"""Disassemble one instruction."""
self.xed_decoded_inst_zero_keep_mode(inst.xedp)
err = self.xed_decode(inst.xedp, bytes_ptr, bytes_cnt)
if err:
return 0, ""
# Use AT&T mode (2), alternative is Intel (3)
ok = self.xed_format_context(2, inst.xedp, inst.bufferp, sizeof(inst.buffer), ip, 0, 0)
if not ok:
return 0, ""
result = inst.buffer.value.decode('utf-8')
# Return instruction length and the disassembled instruction text
return self.xed_decoded_inst_get_length(inst.xedp), result
|