1
|
|
//! \file
|
2
|
|
/*
|
3
|
|
** Copyright (C) - Triton
|
4
|
|
**
|
5
|
|
** This program is under the terms of the Apache License 2.0.
|
6
|
|
*/
|
7
|
|
|
8
|
|
#include <triton/pythonObjects.hpp>
|
9
|
|
#include <triton/pythonUtils.hpp>
|
10
|
|
#include <triton/pythonXFunctions.hpp>
|
11
|
|
#include <triton/exceptions.hpp>
|
12
|
|
#include <triton/register.hpp>
|
13
|
|
|
14
|
|
|
15
|
|
|
16
|
|
/* setup doctest context
|
17
|
|
|
18
|
|
>>> from __future__ import print_function
|
19
|
|
>>> from triton import ARCH, TritonContext, Instruction, REG
|
20
|
|
>>> ctxt = TritonContext()
|
21
|
|
>>> ctxt.setArchitecture(ARCH.X86_64)
|
22
|
|
|
23
|
|
>>> inst = Instruction(b"\x8A\xA4\x4A\x00\x01\x00\x00")
|
24
|
|
>>> inst.setAddress(0x40000)
|
25
|
|
|
26
|
|
*/
|
27
|
|
|
28
|
|
/*! \page py_Register_page Register
|
29
|
|
\brief [**python api**] All information about the Register Python object.
|
30
|
|
|
31
|
|
\tableofcontents
|
32
|
|
|
33
|
|
\section py_Register_description Description
|
34
|
|
<hr>
|
35
|
|
|
36
|
|
This object is used to represent a register operand according to the CPU architecture.
|
37
|
|
|
38
|
|
|
39
|
|
\subsection py_Register_example Example
|
40
|
|
|
41
|
|
~~~~~~~~~~~~~{.py}
|
42
|
|
>>> ctxt.processing(inst)
|
43
|
|
True
|
44
|
|
>>> print(inst)
|
45
|
|
0x40000: mov ah, byte ptr [rdx + rcx*2 + 0x100]
|
46
|
|
|
47
|
|
>>> op0 = inst.getOperands()[0]
|
48
|
|
>>> print(op0)
|
49
|
|
ah:8 bv[15..8]
|
50
|
|
|
51
|
|
>>> op0.getName()
|
52
|
|
'ah'
|
53
|
|
|
54
|
|
>>> op0.getSize()
|
55
|
|
1
|
56
|
|
|
57
|
|
>>> op0.getBitSize()
|
58
|
|
8
|
59
|
|
|
60
|
|
>>> ctxt.getParentRegister(op0).getName()
|
61
|
|
'rax'
|
62
|
|
|
63
|
|
~~~~~~~~~~~~~
|
64
|
|
|
65
|
|
\subsection py_Register_constructor Constructor
|
66
|
|
|
67
|
|
~~~~~~~~~~~~~{.py}
|
68
|
|
>>> ah = ctxt.getRegister(REG.X86_64.AH)
|
69
|
|
>>> print(ah)
|
70
|
|
ah:8 bv[15..8]
|
71
|
|
|
72
|
|
>>> print(ah.getBitSize())
|
73
|
|
8
|
74
|
|
|
75
|
|
>>> print(ctxt.registers.rax)
|
76
|
|
rax:64 bv[63..0]
|
77
|
|
|
78
|
|
~~~~~~~~~~~~~
|
79
|
|
|
80
|
|
\section Register_py_api Python API - Methods of the Register class
|
81
|
|
<hr>
|
82
|
|
|
83
|
|
- <b>integer getBitSize(void)</b><br>
|
84
|
|
Returns the size (in bits) of the register.<br>
|
85
|
|
e.g: `64`
|
86
|
|
|
87
|
|
- <b>\ref py_BitsVector_page getBitvector(void)</b><br>
|
88
|
|
Returns the bit vector of the register.
|
89
|
|
|
90
|
|
- <b>\ref py_EXTEND_page getExtendSize(void)</b><br>
|
91
|
|
Returns the size (in bits) of the extend. Mainly used for AArch64.<br>
|
92
|
|
e.g: `16`
|
93
|
|
|
94
|
|
- <b>\ref py_EXTEND_page getExtendType(void)</b><br>
|
95
|
|
Returns the extend type of the operand. Mainly used for AArch64.<br>
|
96
|
|
e.g: `EXTEND.ARM.UXTW`
|
97
|
|
|
98
|
|
- <b>\ref py_REG_page getId(void)</b><br>
|
99
|
|
Returns the enum of the register.<br>
|
100
|
|
e.g: `REG.X86_64.RBX`
|
101
|
|
|
102
|
|
- <b>string getName(void)</b><br>
|
103
|
|
Returns the name of the register.<br>
|
104
|
|
e.g: `rbx`
|
105
|
|
|
106
|
|
- <b>\ref py_SHIFT_page getShiftType(void)</b><br>
|
107
|
|
Returns the shift type of the operand. Mainly used for AArch64.<br>
|
108
|
|
e.g: `SHIFT.ARM.LSL`
|
109
|
|
|
110
|
|
- <b>integer getShiftImmediate(void)</b><br>
|
111
|
|
Returns the shift immediate value of the operand. Mainly used for AArch64 and ARM32.<br>
|
112
|
|
e.g: `2`
|
113
|
|
|
114
|
|
- <b>\ref py_REG_page getShiftRegister(void)</b><br>
|
115
|
|
Returns the shift register of the operand. Mainly used for ARM32.<br>
|
116
|
|
e.g: `REG.ARM32.R0`
|
117
|
|
|
118
|
|
- <b>integer getSize(void)</b><br>
|
119
|
|
Returns the size (in bytes) of the register.<br>
|
120
|
|
e.g: `8`
|
121
|
|
|
122
|
|
- <b>\ref py_OPERAND_page getType(void)</b><br>
|
123
|
|
Returns the type of the register. In this case this function returns `OPERAND.REG`.
|
124
|
|
|
125
|
|
- <b>bool isMutable(void)</b><br>
|
126
|
|
Returns true if this register is mutable. Mainly used in AArch64 to define that some registers like XZR are immutable.
|
127
|
|
|
128
|
|
- <b>bool isOverlapWith(\ref py_Register_page other)</b><br>
|
129
|
|
Returns true if `other` and `self` overlap.
|
130
|
|
|
131
|
|
*/
|
132
|
|
|
133
|
|
|
134
|
|
|
135
|
|
namespace triton {
|
136
|
|
namespace bindings {
|
137
|
|
namespace python {
|
138
|
|
|
139
|
|
//! Register destructor.
|
140
|
1
|
void Register_dealloc(PyObject* self) {
|
141
|
1
|
std::cout << std::flush;
|
142
|
1
|
delete PyRegister_AsRegister(self);
|
143
|
1
|
Py_TYPE(self)->tp_free((PyObject*)self);
|
144
|
|
}
|
145
|
|
|
146
|
|
|
147
|
1
|
static PyObject* Register_getBitSize(PyObject* self, PyObject* noarg) {
|
148
|
|
try {
|
149
|
1
|
return PyLong_FromUint32(PyRegister_AsRegister(self)->getBitSize());
|
150
|
|
}
|
151
|
0
|
catch (const triton::exceptions::Exception& e) {
|
152
|
0
|
return PyErr_Format(PyExc_TypeError, "%s", e.what());
|
153
|
|
}
|
154
|
|
}
|
155
|
|
|
156
|
|
|
157
|
1
|
static PyObject* Register_getBitvector(PyObject* self, PyObject* noarg) {
|
158
|
|
try {
|
159
|
1
|
return PyBitsVector(*PyRegister_AsRegister(self));
|
160
|
|
}
|
161
|
0
|
catch (const triton::exceptions::Exception& e) {
|
162
|
0
|
return PyErr_Format(PyExc_TypeError, "%s", e.what());
|
163
|
|
}
|
164
|
|
}
|
165
|
|
|
166
|
|
|
167
|
1
|
static PyObject* Register_getExtendSize(PyObject* self, PyObject* noarg) {
|
168
|
|
try {
|
169
|
1
|
return PyLong_FromUint32(PyRegister_AsRegister(self)->getExtendSize());
|
170
|
|
}
|
171
|
0
|
catch (const triton::exceptions::Exception& e) {
|
172
|
0
|
return PyErr_Format(PyExc_TypeError, "%s", e.what());
|
173
|
|
}
|
174
|
|
}
|
175
|
|
|
176
|
|
|
177
|
1
|
static PyObject* Register_getExtendType(PyObject* self, PyObject* noarg) {
|
178
|
|
try {
|
179
|
1
|
return PyLong_FromUint32(PyRegister_AsRegister(self)->getExtendType());
|
180
|
|
}
|
181
|
0
|
catch (const triton::exceptions::Exception& e) {
|
182
|
0
|
return PyErr_Format(PyExc_TypeError, "%s", e.what());
|
183
|
|
}
|
184
|
|
}
|
185
|
|
|
186
|
|
|
187
|
1
|
static PyObject* Register_getId(PyObject* self, PyObject* noarg) {
|
188
|
|
try {
|
189
|
1
|
return PyLong_FromUint32(PyRegister_AsRegister(self)->getId());
|
190
|
|
}
|
191
|
0
|
catch (const triton::exceptions::Exception& e) {
|
192
|
0
|
return PyErr_Format(PyExc_TypeError, "%s", e.what());
|
193
|
|
}
|
194
|
|
}
|
195
|
|
|
196
|
|
|
197
|
1
|
static PyObject* Register_getName(PyObject* self, PyObject* noarg) {
|
198
|
|
try {
|
199
|
1
|
return Py_BuildValue("s", PyRegister_AsRegister(self)->getName().c_str());
|
200
|
|
}
|
201
|
0
|
catch (const triton::exceptions::Exception& e) {
|
202
|
0
|
return PyErr_Format(PyExc_TypeError, "%s", e.what());
|
203
|
|
}
|
204
|
|
}
|
205
|
|
|
206
|
|
|
207
|
1
|
static PyObject* Register_getShiftType(PyObject* self, PyObject* noarg) {
|
208
|
|
try {
|
209
|
1
|
return PyLong_FromUint32(PyRegister_AsRegister(self)->getShiftType());
|
210
|
|
}
|
211
|
0
|
catch (const triton::exceptions::Exception& e) {
|
212
|
0
|
return PyErr_Format(PyExc_TypeError, "%s", e.what());
|
213
|
|
}
|
214
|
|
}
|
215
|
|
|
216
|
|
|
217
|
1
|
static PyObject* Register_getShiftImmediate(PyObject* self, PyObject* noarg) {
|
218
|
|
try {
|
219
|
1
|
return PyLong_FromUint64(PyRegister_AsRegister(self)->getShiftImmediate());
|
220
|
|
}
|
221
|
0
|
catch (const triton::exceptions::Exception& e) {
|
222
|
0
|
return PyErr_Format(PyExc_TypeError, "%s", e.what());
|
223
|
|
}
|
224
|
|
}
|
225
|
|
|
226
|
|
|
227
|
1
|
static PyObject* Register_getShiftRegister(PyObject* self, PyObject* noarg) {
|
228
|
|
try {
|
229
|
1
|
return PyLong_FromUint64(PyRegister_AsRegister(self)->getShiftRegister());
|
230
|
|
}
|
231
|
0
|
catch (const triton::exceptions::Exception& e) {
|
232
|
0
|
return PyErr_Format(PyExc_TypeError, "%s", e.what());
|
233
|
|
}
|
234
|
|
}
|
235
|
|
|
236
|
|
|
237
|
1
|
static PyObject* Register_getSize(PyObject* self, PyObject* noarg) {
|
238
|
|
try {
|
239
|
1
|
return PyLong_FromUint32(PyRegister_AsRegister(self)->getSize());
|
240
|
|
}
|
241
|
0
|
catch (const triton::exceptions::Exception& e) {
|
242
|
0
|
return PyErr_Format(PyExc_TypeError, "%s", e.what());
|
243
|
|
}
|
244
|
|
}
|
245
|
|
|
246
|
|
|
247
|
1
|
static PyObject* Register_getType(PyObject* self, PyObject* noarg) {
|
248
|
|
try {
|
249
|
1
|
return PyLong_FromUint32(PyRegister_AsRegister(self)->getType());
|
250
|
|
}
|
251
|
0
|
catch (const triton::exceptions::Exception& e) {
|
252
|
0
|
return PyErr_Format(PyExc_TypeError, "%s", e.what());
|
253
|
|
}
|
254
|
|
}
|
255
|
|
|
256
|
|
|
257
|
1
|
static PyObject* Register_isMutable(PyObject* self, PyObject* noarg) {
|
258
|
|
try {
|
259
|
1
|
if (PyRegister_AsRegister(self)->isMutable())
|
260
|
1
|
Py_RETURN_TRUE;
|
261
|
1
|
Py_RETURN_FALSE;
|
262
|
|
}
|
263
|
0
|
catch (const triton::exceptions::Exception& e) {
|
264
|
0
|
return PyErr_Format(PyExc_TypeError, "%s", e.what());
|
265
|
|
}
|
266
|
|
}
|
267
|
|
|
268
|
|
|
269
|
1
|
static PyObject* Register_isOverlapWith(PyObject* self, PyObject* reg2) {
|
270
|
|
try {
|
271
|
|
triton::arch::Register* reg1;
|
272
|
|
|
273
|
1
|
if (!PyRegister_Check(reg2))
|
274
|
0
|
return PyErr_Format(PyExc_TypeError, "Register::isOverlapWith(): Expected a Register as argument.");
|
275
|
|
|
276
|
1
|
reg1 = PyRegister_AsRegister(self);
|
277
|
1
|
if (reg1->isOverlapWith(*PyRegister_AsRegister(reg2)))
|
278
|
1
|
Py_RETURN_TRUE;
|
279
|
1
|
Py_RETURN_FALSE;
|
280
|
|
}
|
281
|
0
|
catch (const triton::exceptions::Exception& e) {
|
282
|
0
|
return PyErr_Format(PyExc_TypeError, "%s", e.what());
|
283
|
|
}
|
284
|
|
}
|
285
|
|
|
286
|
|
|
287
|
|
#if !defined(IS_PY3_8) || !IS_PY3_8
|
288
|
0
|
static int Register_print(PyObject* self, void* io, int s) {
|
289
|
0
|
std::cout << PyRegister_AsRegister(self);
|
290
|
0
|
return 0;
|
291
|
|
}
|
292
|
|
#endif
|
293
|
|
|
294
|
|
|
295
|
0
|
static long Register_hash(PyObject* self) {
|
296
|
0
|
return static_cast<long>(PyRegister_AsRegister(self)->getId());
|
297
|
|
}
|
298
|
|
|
299
|
|
|
300
|
1
|
static PyObject* Register_str(PyObject* self) {
|
301
|
|
try {
|
302
|
1
|
std::stringstream str;
|
303
|
1
|
str << PyRegister_AsRegister(self);
|
304
|
1
|
return PyStr_FromFormat("%s", str.str().c_str());
|
305
|
|
}
|
306
|
0
|
catch (const triton::exceptions::Exception& e) {
|
307
|
0
|
return PyErr_Format(PyExc_TypeError, "%s", e.what());
|
308
|
|
}
|
309
|
|
}
|
310
|
|
|
311
|
|
|
312
|
1
|
static PyObject* Register_richcompare(PyObject* self, PyObject* other, int op) {
|
313
|
1
|
PyObject* result = nullptr;
|
314
|
1
|
triton::uint32 id1 = 0;
|
315
|
1
|
triton::uint32 id2 = 0;
|
316
|
|
|
317
|
1
|
if (!PyRegister_Check(other)) {
|
318
|
|
result = Py_NotImplemented;
|
319
|
|
}
|
320
|
|
|
321
|
|
else {
|
322
|
1
|
id1 = PyRegister_AsRegister(self)->getId();
|
323
|
1
|
id2 = PyRegister_AsRegister(other)->getId();
|
324
|
|
|
325
|
1
|
switch (op) {
|
326
|
|
case Py_LT:
|
327
|
0
|
result = (id1 < id2) ? Py_True : Py_False;
|
328
|
|
break;
|
329
|
|
case Py_LE:
|
330
|
0
|
result = (id1 <= id2) ? Py_True : Py_False;
|
331
|
|
break;
|
332
|
|
case Py_EQ:
|
333
|
1
|
result = (id1 == id2) ? Py_True : Py_False;
|
334
|
|
break;
|
335
|
|
case Py_NE:
|
336
|
0
|
result = (id1 != id2) ? Py_True : Py_False;
|
337
|
|
break;
|
338
|
|
case Py_GT:
|
339
|
0
|
result = (id1 > id2) ? Py_True : Py_False;
|
340
|
|
break;
|
341
|
|
case Py_GE:
|
342
|
0
|
result = (id1 >= id2) ? Py_True : Py_False;
|
343
|
|
break;
|
344
|
|
}
|
345
|
|
}
|
346
|
|
|
347
|
1
|
Py_INCREF(result);
|
348
|
1
|
return result;
|
349
|
|
}
|
350
|
|
|
351
|
|
|
352
|
|
//! Register methods.
|
353
|
|
PyMethodDef Register_callbacks[] = {
|
354
|
|
{"getBitSize", Register_getBitSize, METH_NOARGS, ""},
|
355
|
|
{"getBitvector", Register_getBitvector, METH_NOARGS, ""},
|
356
|
|
{"getExtendSize", Register_getExtendSize, METH_NOARGS, ""},
|
357
|
|
{"getExtendType", Register_getExtendType, METH_NOARGS, ""},
|
358
|
|
{"getId", Register_getId, METH_NOARGS, ""},
|
359
|
|
{"getName", Register_getName, METH_NOARGS, ""},
|
360
|
|
{"getShiftType", Register_getShiftType, METH_NOARGS, ""},
|
361
|
|
{"getShiftImmediate", Register_getShiftImmediate, METH_NOARGS, ""},
|
362
|
|
{"getShiftRegister", Register_getShiftRegister, METH_NOARGS, ""},
|
363
|
|
{"getSize", Register_getSize, METH_NOARGS, ""},
|
364
|
|
{"getType", Register_getType, METH_NOARGS, ""},
|
365
|
|
{"isMutable", Register_isMutable, METH_NOARGS, ""},
|
366
|
|
{"isOverlapWith", Register_isOverlapWith, METH_O, ""},
|
367
|
|
{nullptr, nullptr, 0, nullptr}
|
368
|
|
};
|
369
|
|
|
370
|
|
|
371
|
|
PyTypeObject Register_Type = {
|
372
|
|
PyVarObject_HEAD_INIT(&PyType_Type, 0)
|
373
|
|
"Register", /* tp_name */
|
374
|
|
sizeof(Register_Object), /* tp_basicsize */
|
375
|
|
0, /* tp_itemsize */
|
376
|
|
(destructor)Register_dealloc, /* tp_dealloc */
|
377
|
|
#if IS_PY3_8
|
378
|
|
0, /* tp_vectorcall_offset */
|
379
|
|
#else
|
380
|
|
(printfunc)Register_print, /* tp_print */
|
381
|
|
#endif
|
382
|
|
0, /* tp_getattr */
|
383
|
|
0, /* tp_setattr */
|
384
|
|
0, /* tp_compare */
|
385
|
|
(reprfunc)Register_str, /* tp_repr */
|
386
|
|
0, /* tp_as_number */
|
387
|
|
0, /* tp_as_sequence */
|
388
|
|
0, /* tp_as_mapping */
|
389
|
|
(hashfunc)Register_hash, /* tp_hash */
|
390
|
|
0, /* tp_call */
|
391
|
|
(reprfunc)Register_str, /* tp_str */
|
392
|
|
0, /* tp_getattro */
|
393
|
|
0, /* tp_setattro */
|
394
|
|
0, /* tp_as_buffer */
|
395
|
|
Py_TPFLAGS_DEFAULT, /* tp_flags */
|
396
|
|
"Register objects", /* tp_doc */
|
397
|
|
0, /* tp_traverse */
|
398
|
|
0, /* tp_clear */
|
399
|
|
(richcmpfunc)Register_richcompare, /* tp_richcompare */
|
400
|
|
0, /* tp_weaklistoffset */
|
401
|
|
0, /* tp_iter */
|
402
|
|
0, /* tp_iternext */
|
403
|
|
Register_callbacks, /* tp_methods */
|
404
|
|
0, /* tp_members */
|
405
|
|
0, /* tp_getset */
|
406
|
|
0, /* tp_base */
|
407
|
|
0, /* tp_dict */
|
408
|
|
0, /* tp_descr_get */
|
409
|
|
0, /* tp_descr_set */
|
410
|
|
0, /* tp_dictoffset */
|
411
|
|
0, /* tp_init */
|
412
|
|
0, /* tp_alloc */
|
413
|
|
0, /* tp_new */
|
414
|
|
0, /* tp_free */
|
415
|
|
0, /* tp_is_gc */
|
416
|
|
0, /* tp_bases */
|
417
|
|
0, /* tp_mro */
|
418
|
|
0, /* tp_cache */
|
419
|
|
0, /* tp_subclasses */
|
420
|
|
0, /* tp_weaklist */
|
421
|
|
0, /* tp_del */
|
422
|
|
#if IS_PY3
|
423
|
|
0, /* tp_version_tag */
|
424
|
|
0, /* tp_finalize */
|
425
|
|
#if IS_PY3_8
|
426
|
|
0, /* tp_vectorcall */
|
427
|
|
#if !IS_PY3_9
|
428
|
|
0, /* bpo-37250: kept for backwards compatibility in CPython 3.8 only */
|
429
|
|
#endif
|
430
|
|
#endif
|
431
|
|
#else
|
432
|
|
0 /* tp_version_tag */
|
433
|
|
#endif
|
434
|
|
};
|
435
|
|
|
436
|
|
|
437
|
1
|
PyObject* PyRegister(const triton::arch::Register& reg) {
|
438
|
|
Register_Object* object;
|
439
|
|
|
440
|
1
|
PyType_Ready(&Register_Type);
|
441
|
1
|
object = PyObject_NEW(Register_Object, &Register_Type);
|
442
|
1
|
if (object != NULL)
|
443
|
1
|
object->reg = new triton::arch::Register(reg);
|
444
|
|
|
445
|
1
|
return (PyObject*)object;
|
446
|
|
}
|
447
|
|
|
448
|
|
}; /* python namespace */
|
449
|
|
}; /* bindings namespace */
|
450
|
1
|
}; /* triton namespace */
|