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/pathConstraint.hpp>
13 
14 
15 
16 /* setup doctest context
17 
18 >>> from triton import TritonContext, ARCH
19 >>> ctxt = TritonContext()
20 >>> ctxt.setArchitecture(ARCH.X86_64)
21 >>> astCtxt = ctxt.getAstContext()
22 
23 */
24 
25 /*! \page py_PathConstraint_page PathConstraint
26     \brief [**python api**] All information about the PathConstraint Python object.
27 
28 \tableofcontents
29 
30 \section py_PathConstraint_description Description
31 <hr>
32 
33 This object is used to represent a path constraint.
34 
35 ~~~~~~~~~~~~~{.py}
36 >>> pcl = ctxt.getPathConstraints()
37 >>> for pc in pcl:
38 ...     if pc.isMultipleBranches():
39 ...         b1 =  pc.getBranchConstraints()[0]['constraint']
40 ...         b2 =  pc.getBranchConstraints()[1]['constraint']
41 ...
42 ...         print('Constraint branch 1: %s' % (b1))
43 ...         print('Constraint branch 2: %s' % (b2))
44 ...
45 ...         seed = list()
46 ...
47 ...         # Branch 1, we assume that the path constraint contains a symbolic variable
48 ...         models  = ctxt.getModel(b)
49 ...         for k, v in models.items():
50 ...             seed.append(v)
51 ...
52 ...         # Branch 2, we assume that the path constraint contains a symbolic variable.
53 ...         models  = ctxt.getModel(b2)
54 ...         for k, v in models.items():
55 ...             seed.append(v)
56 ...
57 ...         if seed:
58 ...             print('B1: %s (%c)  |  B2: %s (%c)' % (seed[0], chr(seed[0].getValue()), seed[1], chr(seed[1].getValue())))
59 ...
60 
61 ~~~~~~~~~~~~~
62 
63 A possible output is :
64 
65 ~~~~~~~~~~~~~{.py}
66 Constraint branch 1: (not (= (ite (= ((_ extract 0 0) ref!179) (_ bv1 1)) (_ bv4195769 64) (_ bv4195762 64)) (_ bv4195762 64)))
67 Constraint branch 2: (= (ite (= ((_ extract 0 0) ref!179) (_ bv1 1)) (_ bv4195769 64) (_ bv4195762 64)) (_ bv4195762 64))
68 B1: SymVar_0 = 65 (e)  |  B2: SymVar_0 = 0 ()
69 [...]
70 ~~~~~~~~~~~~~
71 
72 \section PathConstraint_py_api Python API - Methods of the PathConstraint class
73 <hr>
74 
75 - <b>dict getBranchConstraints(void)</b><br>
76 Returns the branch constraints as list of dictionary `{isTaken, srcAddr, dstAddr, constraint}`. The source address is the location
77 of the branch instruction and the destination address is the destination of the jump. E.g: `"0x11223344: jne 0x55667788"`, 0x11223344
78 is the source address and 0x55667788 is the destination if and only if the branch is taken, otherwise the destination is the next
79 instruction address.
80 
81 - <b>integer getTakenAddress(void)</b><br>
82 Returns the address of the taken branch.
83 
84 - <b>\ref py_AstNode_page getTakenPredicate(void)</b><br>
85 Returns the predicate of the taken branch.
86 
87 - <b>bool isMultipleBranches(void)</b><br>
88 Returns true if it is not a direct jump.
89 
90 */
91 
92 
93 
94 namespace triton {
95   namespace bindings {
96     namespace python {
97 
98       //! PathConstraint destructor.
PathConstraint_dealloc(PyObject * self)99       void PathConstraint_dealloc(PyObject* self) {
100         std::cout << std::flush;
101         delete PyPathConstraint_AsPathConstraint(self);
102         Py_TYPE(self)->tp_free((PyObject*)self);
103       }
104 
105 
PathConstraint_getBranchConstraints(PyObject * self,PyObject * noarg)106       static PyObject* PathConstraint_getBranchConstraints(PyObject* self, PyObject* noarg) {
107         try {
108           PyObject* ret = nullptr;
109           const auto& branches = PyPathConstraint_AsPathConstraint(self)->getBranchConstraints();
110 
111           ret = xPyList_New(branches.size());
112           for (triton::usize index = 0; index != branches.size(); index++) {
113             PyObject* dict = xPyDict_New();
114             xPyDict_SetItem(dict, PyStr_FromString("isTaken"),    PyBool_FromLong(std::get<0>(branches[index])));
115             xPyDict_SetItem(dict, PyStr_FromString("srcAddr"),    PyLong_FromUint64(std::get<1>(branches[index])));
116             xPyDict_SetItem(dict, PyStr_FromString("dstAddr"),    PyLong_FromUint64(std::get<2>(branches[index])));
117             xPyDict_SetItem(dict, PyStr_FromString("constraint"), PyAstNode(std::get<3>(branches[index])));
118             PyList_SetItem(ret, index, dict);
119           }
120 
121           return ret;
122         }
123         catch (const triton::exceptions::Exception& e) {
124           return PyErr_Format(PyExc_TypeError, "%s", e.what());
125         }
126       }
127 
128 
PathConstraint_getTakenAddress(PyObject * self,PyObject * noarg)129       static PyObject* PathConstraint_getTakenAddress(PyObject* self, PyObject* noarg) {
130         try {
131           return PyLong_FromUint64(PyPathConstraint_AsPathConstraint(self)->getTakenAddress());
132         }
133         catch (const triton::exceptions::Exception& e) {
134           return PyErr_Format(PyExc_TypeError, "%s", e.what());
135         }
136       }
137 
138 
PathConstraint_getTakenPredicate(PyObject * self,PyObject * noarg)139       static PyObject* PathConstraint_getTakenPredicate(PyObject* self, PyObject* noarg) {
140         try {
141           return PyAstNode(PyPathConstraint_AsPathConstraint(self)->getTakenPredicate());
142         }
143         catch (const triton::exceptions::Exception& e) {
144           return PyErr_Format(PyExc_TypeError, "%s", e.what());
145         }
146       }
147 
148 
PathConstraint_isMultipleBranches(PyObject * self,PyObject * noarg)149       static PyObject* PathConstraint_isMultipleBranches(PyObject* self, PyObject* noarg) {
150         try {
151           if (PyPathConstraint_AsPathConstraint(self)->isMultipleBranches())
152             Py_RETURN_TRUE;
153           Py_RETURN_FALSE;
154         }
155         catch (const triton::exceptions::Exception& e) {
156           return PyErr_Format(PyExc_TypeError, "%s", e.what());
157         }
158       }
159 
160 
161       //! PathConstraint methods.
162       PyMethodDef PathConstraint_callbacks[] = {
163         {"getBranchConstraints",        PathConstraint_getBranchConstraints,      METH_NOARGS,    ""},
164         {"getTakenAddress",             PathConstraint_getTakenAddress,           METH_NOARGS,    ""},
165         {"getTakenPredicate",           PathConstraint_getTakenPredicate,         METH_NOARGS,    ""},
166         {"isMultipleBranches",          PathConstraint_isMultipleBranches,        METH_NOARGS,    ""},
167         {nullptr,                       nullptr,                                  0,              nullptr}
168       };
169 
170 
171       PyTypeObject PathConstraint_Type = {
172         PyVarObject_HEAD_INIT(&PyType_Type, 0)
173         "PathConstraint",                           /* tp_name */
174         sizeof(PathConstraint_Object),              /* tp_basicsize */
175         0,                                          /* tp_itemsize */
176         (destructor)PathConstraint_dealloc,         /* tp_dealloc */
177         0,                                          /* tp_print */
178         0,                                          /* tp_getattr */
179         0,                                          /* tp_setattr */
180         0,                                          /* tp_compare */
181         0,                                          /* tp_repr */
182         0,                                          /* tp_as_number */
183         0,                                          /* tp_as_sequence */
184         0,                                          /* tp_as_mapping */
185         0,                                          /* tp_hash */
186         0,                                          /* tp_call */
187         0,                                          /* tp_str */
188         0,                                          /* tp_getattro */
189         0,                                          /* tp_setattro */
190         0,                                          /* tp_as_buffer */
191         Py_TPFLAGS_DEFAULT,                         /* tp_flags */
192         "PathConstraint objects",                   /* tp_doc */
193         0,                                          /* tp_traverse */
194         0,                                          /* tp_clear */
195         0,                                          /* tp_richcompare */
196         0,                                          /* tp_weaklistoffset */
197         0,                                          /* tp_iter */
198         0,                                          /* tp_iternext */
199         PathConstraint_callbacks,                   /* tp_methods */
200         0,                                          /* tp_members */
201         0,                                          /* tp_getset */
202         0,                                          /* tp_base */
203         0,                                          /* tp_dict */
204         0,                                          /* tp_descr_get */
205         0,                                          /* tp_descr_set */
206         0,                                          /* tp_dictoffset */
207         0,                                          /* tp_init */
208         0,                                          /* tp_alloc */
209         0,                                          /* tp_new */
210         0,                                          /* tp_free */
211         0,                                          /* tp_is_gc */
212         0,                                          /* tp_bases */
213         0,                                          /* tp_mro */
214         0,                                          /* tp_cache */
215         0,                                          /* tp_subclasses */
216         0,                                          /* tp_weaklist */
217         0,                                          /* tp_del */
218         #if IS_PY3
219         0,                                          /* tp_version_tag */
220         0,                                          /* tp_finalize */
221         #else
222         0                                           /* tp_version_tag */
223         #endif
224       };
225 
226 
PyPathConstraint(const triton::engines::symbolic::PathConstraint & pc)227       PyObject* PyPathConstraint(const triton::engines::symbolic::PathConstraint& pc) {
228         PathConstraint_Object* object;
229 
230         PyType_Ready(&PathConstraint_Type);
231         object = PyObject_NEW(PathConstraint_Object, &PathConstraint_Type);
232         if (object != NULL)
233           object->pc = new triton::engines::symbolic::PathConstraint(pc);
234 
235         return (PyObject*)object;
236       }
237 
238     }; /* python namespace */
239   }; /* bindings namespace */
240 }; /* triton namespace */
241