This repository has been archived by the owner on Jul 7, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 11
/
Copy pathdecoder.c
171 lines (141 loc) · 4.99 KB
/
decoder.c
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
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
/* pyxed - Python bindings for Intel's XED2
* huku <[email protected]>
*
* decoder.c - Exports class `Decoder', the main decoder object.
*/
#include "includes.h"
#include "pyxed.h"
#include "check.h"
#include "decoder.h"
#include "instruction.h"
static int init(xed_t *self, PyObject *args, PyObject *kwds)
{
/* The call to `tp_alloc()' will initialize memory with zeros. */
self->mmode = XED_MACHINE_MODE_LONG_COMPAT_32;
self->stack_addr_width = XED_ADDRESS_WIDTH_32b;
return 0;
}
static PyObject *decode(xed_t *self, PyObject *args)
{
xed_decoded_inst_t *decoded_inst;
unsigned long long runtime_address, itext_offset, itext_size;
const xed_uint8_t *buf;
unsigned int bytes;
PyObject *r = NULL;
/* Make sure we have a valid input buffer. */
if(is_string(self->itext) == 0)
{
PyErr_SetString(PyExc_TypeError, "Invalid instruction text");
goto _err;
}
itext_offset = self->itext_offset;
itext_size = (unsigned long long)PyString_Size(self->itext);
/* Have we finished decoding? */
if(itext_offset == itext_size)
{
Py_INCREF(Py_None);
r = Py_None;
goto _err;
}
/* If the offset given is invalid, raise `InvalidOffsetException'. */
else if(itext_offset > itext_size)
{
PyErr_SetString(invalid_offset, "Invalid instruction text offset");
goto _err;
}
/* Decode next instruction from the input buffer. */
decoded_inst = PyMem_Malloc(sizeof(xed_decoded_inst_t));
xed_decoded_inst_zero(decoded_inst);
xed_decoded_inst_set_mode(decoded_inst, self->mmode,
self->stack_addr_width);
buf = (const xed_uint8_t *)PyString_AsString(self->itext) + itext_offset;
/* If we set `bytes' to something more than `XED_MAX_INSTRUCTION_BYTES', the
* call to `xed_decode()' below may fail when decoding certain instructions.
*/
if(itext_size - itext_offset <= XED_MAX_INSTRUCTION_BYTES)
bytes = (unsigned int)(itext_size - itext_offset);
else
bytes = XED_MAX_INSTRUCTION_BYTES;
/* XXX: Check return value here? */
xed_decode(decoded_inst, buf, bytes);
/* Compute the instruction's runtime address and update saved offset by the
* number of bytes corresponding to the decoded instruction (the call to
* `xed_decoded_inst_get_length()' will return a valid length even if the
* decoded instruction is not valid).
*/
runtime_address = self->runtime_address + itext_offset;
self->itext_offset += xed_decoded_inst_get_length(decoded_inst);
/* If the instruction is not valid, raise `InvalidInstructionError'. */
if(xed_decoded_inst_valid(decoded_inst) == 0)
{
PyMem_Free(decoded_inst);
PyErr_SetString(invalid_instruction, "Decoded instruction is invalid");
goto _err;
}
r = (PyObject *)new_instruction(decoded_inst, runtime_address);
_err:
return r;
}
static PyObject *set_mode(xed_t *self, PyObject *args)
{
unsigned int mmode, stack_addr_width;
if(PyArg_ParseTuple(args, "II", &mmode, &stack_addr_width) != 0)
{
self->mmode = mmode;
self->stack_addr_width = stack_addr_width;
}
Py_RETURN_NONE;
}
static PyMemberDef members[] =
{
{"itext", T_OBJECT, offsetof(xed_t, itext), 0,
"String object holding instruction text bytes"},
{"itext_offset", T_ULONGLONG, offsetof(xed_t, itext_offset), 0,
"Offset in instruction text to start decoding from"},
{"runtime_address", T_ULONGLONG, offsetof(xed_t, runtime_address), 0,
"Runtime address of the instruction text being disassembled"},
{NULL, 0, 0, 0, NULL}
};
static PyMethodDef methods[] =
{
M_VARARGS(set_mode),
M_NOARGS(decode),
M_NULL
};
static PyTypeObject type;
/* Initialization of `pyxed.Decoder' type should go here. */
static void initialize_decoder_type(PyTypeObject *type)
{
/* When compiling on Microsoft Windows with older versions of Visual Studio,
* we can't make use of designated initializers for structure types; this
* C99 feature is not supported. To properly initialize a `PyTypeObject' and
* avoid compiler warnings, we first need to initialize a `PyObject' (fully
* initialized by `PyObject_HEAD_INIT()') and then assign the latter to the
* first.
*/
static PyObject type_base[] =
{
PYOBJECT_INITIALIZER
};
/* All Python structures are castable to `PyObject' and structure assignment
* is a well defined construct.
*/
*(PyObject *)type = type_base[0];
type->tp_name = "pyxed.Decoder";
type->tp_basicsize = sizeof(xed_t);
type->tp_flags = Py_TPFLAGS_DEFAULT;
type->tp_doc = "Main decoder object.";
type->tp_methods = methods;
type->tp_members = members;
type->tp_init = (initproc)init;
type->tp_new = PyType_GenericNew;
}
void register_decoder_object(PyObject *module)
{
initialize_decoder_type(&type);
if(PyType_Ready(&type) == 0)
{
Py_INCREF(&type);
PyModule_AddObject(module, "Decoder", (PyObject *)&type);
}
}