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