10#include <unordered_set>
26 : symbolic(symbolic) {
27 #ifdef TRITON_Z3_INTERFACE
40 auto start = std::chrono::system_clock::now();
46 if (this->do_synthesize(node, constant, opaque, result) ==
false) {
47 if (subexpr ==
true) {
48 while (this->childrenSynthesis(node, constant, opaque, result));
53 if (this->var2expr.size()) {
54 this->substituteSubExpression(result.
getOutput());
58 auto end = std::chrono::system_clock::now();
61 result.
setTime(std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count());
74 if (vars.size() == 1 && node->getLevel() > 2) {
75 ret = this->unaryOperatorSynthesis(vars, node, result);
78 if (ret ==
false && constant ==
true) {
79 ret = this->constantSynthesis(vars, node, result);
84 else if (vars.size() == 2 && node->getLevel() > 2) {
85 ret = this->binaryOperatorSynthesis(vars, node, result);
89 if (vars.size() && ret ==
false && opaque ==
true && node->getLevel() > 2) {
90 ret = this->opaqueConstantSynthesis(vars, node, result);
97 bool Synthesizer::opaqueConstantSynthesis(
const std::deque<triton::ast::SharedAbstractNode>& vars,
const triton::ast::SharedAbstractNode& node, SynthesisResult& result) {
99 #ifdef TRITON_Z3_INTERFACE
101 auto actx = node->getContext();
103 auto model = this->solver.
getModel(actx->forall(vars, actx->equal(node, actx->variable(var_c))));
106 auto constant = model.at(var_c->getId()).getValue();
107 auto size = model.at(var_c->getId()).getSize();
110 result.setOutput(actx->bv(constant, size));
111 result.setSuccess(
true);
121 bool Synthesizer::constantSynthesis(
const std::deque<triton::ast::SharedAbstractNode>& vars,
const triton::ast::SharedAbstractNode& node, SynthesisResult& result) {
123 #ifdef TRITON_Z3_INTERFACE
134 if ((bits != 8 && bits != 16 && bits != 32 && bits != 64) || insize != outsize)
141 std::array<ConstantEntry, 6> operatorTable = {
142 ConstantEntry(1, actx->bvadd(actx->variable(var_x), actx->variable(var_c))),
143 ConstantEntry(1, actx->bvand(actx->variable(var_x), actx->variable(var_c))),
144 ConstantEntry(1, actx->bvmul(actx->variable(var_x), actx->variable(var_c))),
145 ConstantEntry(0, actx->bvsub(actx->variable(var_c), actx->variable(var_x))),
146 ConstantEntry(1, actx->bvsub(actx->variable(var_x), actx->variable(var_c))),
147 ConstantEntry(1, actx->bvxor(actx->variable(var_x), actx->variable(var_c)))
150 std::vector<triton::ast::SharedAbstractNode> x = {actx->variable(var_x)};
151 for (
auto const& entry : operatorTable) {
153 auto model = this->solver.
getModel(actx->forall(x, actx->equal(entry.op, node)));
156 auto constant = model.at(var_c->getId()).getValue();
157 auto size = model.at(var_c->getId()).getSize();
161 output->setChild(entry.position, actx->bv(constant, size));
162 result.setOutput(output);
163 result.setSuccess(
true);
173 bool Synthesizer::unaryOperatorSynthesis(
const std::deque<triton::ast::SharedAbstractNode>& vars,
const triton::ast::SharedAbstractNode& node, SynthesisResult& result) {
182 if (bits != 8 && bits != 16 && bits != 32 && bits != 64)
191 for (
auto const& it :
triton::engines::synthesis::oracles::
unopTable) {
193 std::array<UnaryEntry, 40> oracles = it.second;
201 for (
auto const& oracle : oracles) {
203 if (oracle.bits != bits) {
208 actx->updateVariable(var_x->getName(), oracle.x);
209 if (node->evaluate() != oracle.r) {
226 auto out = result.getOutput();
228 auto outsize = out->getBitvectorSize();
229 auto insize = in->getBitvectorSize();
230 if (insize > outsize) {
231 result.setOutput(actx->zx(insize - outsize, out));
235 result.setSuccess(
true);
242 actx->updateVariable(var_x->getName(), save_x);
244 return result.successful();
248 bool Synthesizer::binaryOperatorSynthesis(
const std::deque<triton::ast::SharedAbstractNode>& vars,
const triton::ast::SharedAbstractNode& node, SynthesisResult& result) {
259 if (var_x->getSize() != var_y->getSize())
263 if (bits != 8 && bits != 16 && bits != 32 && bits != 64)
268 std::array<BinaryEntry, 40> oracles = it.second;
271 for (
auto const& oracle : oracles) {
273 if (oracle.bits != bits) {
278 actx->updateVariable(var_x->getName(), oracle.x);
279 actx->updateVariable(var_y->getName(), oracle.y);
280 if (node->evaluate() != oracle.r) {
289 case triton::ast::BVADD_NODE: result.setOutput(actx->bvadd(actx->variable(var_x), actx->variable(var_y)));
break;
290 case triton::ast::BVAND_NODE: result.setOutput(actx->bvand(actx->variable(var_x), actx->variable(var_y)));
break;
291 case triton::ast::BVMUL_NODE: result.setOutput(actx->bvmul(actx->variable(var_x), actx->variable(var_y)));
break;
293 case triton::ast::BVNOR_NODE: result.setOutput(actx->bvnor(actx->variable(var_x), actx->variable(var_y)));
break;
294 case triton::ast::BVOR_NODE: result.setOutput(actx->bvor(actx->variable(var_x), actx->variable(var_y)));
break;
295 case triton::ast::BVROL_NODE: result.setOutput(actx->bvrol(actx->variable(var_x), actx->variable(var_y)));
break;
296 case triton::ast::BVROR_NODE: result.setOutput(actx->bvror(actx->variable(var_x), actx->variable(var_y)));
break;
300 case triton::ast::BVSUB_NODE: result.setOutput(actx->bvsub(actx->variable(var_x), actx->variable(var_y)));
break;
304 case triton::ast::BVXOR_NODE: result.setOutput(actx->bvxor(actx->variable(var_x), actx->variable(var_y)));
break;
310 auto out = result.getOutput();
312 auto outsize = out->getBitvectorSize();
313 auto insize = in->getBitvectorSize();
314 if (insize > outsize) {
315 result.setOutput(actx->zx(insize - outsize, out));
319 result.setSuccess(
true);
326 actx->updateVariable(var_x->getName(), save_x);
327 actx->updateVariable(var_y->getName(), save_y);
329 return result.successful();
334 std::stack<triton::ast::AbstractNode*> worklist;
335 std::unordered_set<const triton::ast::AbstractNode*> visited;
338 worklist.push(node.get());
339 while (!worklist.empty()) {
340 auto current = worklist.top();
344 if (visited.find(current) != visited.end()) {
347 visited.insert(current);
356 for (
const auto& child : current->getChildren()) {
358 if (this->do_synthesize(child, constant, opaque, tmp)) {
362 current->setChild(index++, subvar);
364 result.setSuccess(
true);
368 worklist.push(child.get());
378 if (result.successful()) {
379 result.setOutput(node);
390 auto it = this->hash2var.find(tmpResult.getOutput()->getHash());
391 if (it != this->hash2var.end()) {
398 this->hash2var.insert({tmpResult.getOutput()->getHash(), subvar});
399 this->var2expr.insert({subvar, tmpResult.getOutput()});
407 std::stack<triton::ast::AbstractNode*> worklist;
408 std::unordered_set<const triton::ast::AbstractNode*> visited;
410 worklist.push(node.get());
411 while (!worklist.empty()) {
412 auto current = worklist.top();
416 if (visited.find(current) != visited.end()) {
419 visited.insert(current);
427 for (
const auto& child : current->getChildren()) {
429 auto it = this->var2expr.find(child);
430 if (it != this->var2expr.end()) {
431 auto subexpr = this->var2expr[child];
432 current->setChild(index, subexpr);
433 worklist.push(subexpr.get());
437 worklist.push(child.get());
TRITON_EXPORT SharedAstContext getContext(void) const
Access to its context.
TRITON_EXPORT void setSolver(triton::engines::solver::solver_e kind)
Initializes a predefined solver.
TRITON_EXPORT std::unordered_map< triton::usize, SolverModel > getModel(const triton::ast::SharedAbstractNode &node, triton::engines::solver::status_e *status=nullptr, triton::uint32 timeout=0, triton::uint32 *solvingTime=nullptr) const
Computes and returns a model from a symbolic constraint. State is returned in the status pointer as w...
The symbolic engine class.
TRITON_EXPORT SharedSymbolicVariable newSymbolicVariable(triton::engines::symbolic::variable_e type, triton::uint64 source, triton::uint32 size, const std::string &alias="")
Adds a symbolic variable.
The SynthesisResult engine class.
TRITON_EXPORT void setTime(triton::usize ms)
Sets the time.
TRITON_EXPORT const triton::ast::SharedAbstractNode getOutput(void)
Gets the output node.
TRITON_EXPORT void setInput(const triton::ast::SharedAbstractNode &input)
Sets the input node.
TRITON_EXPORT SynthesisResult synthesize(const triton::ast::SharedAbstractNode &node, bool constant=true, bool subexpr=true, bool opaque=false)
Synthesizes a given node. If constant is true, perform a constant synthesis. If opaque is true,...
TRITON_EXPORT Synthesizer(triton::engines::symbolic::SymbolicEngine *symbolic)
Constructor.
The exception class used by the synthesizer engine.
std::shared_ptr< triton::ast::AbstractNode > SharedAbstractNode
Shared Abstract Node.
SharedAbstractNode newInstance(AbstractNode *node, bool unroll)
AST C++ API - Duplicates the AST.
std::shared_ptr< triton::ast::AstContext > SharedAstContext
Shared AST context.
std::deque< SharedAbstractNode > search(const SharedAbstractNode &node, triton::ast::ast_e match)
Returns a deque of collected matched nodes via a depth-first pre order traversal.
std::map< triton::ast::ast_e, std::array< UnaryEntry, 40 > > unopTable
The oracle table for unary operators. Each entry is a UnaryEntry object.
std::map< triton::ast::ast_e, std::array< BinaryEntry, 40 > > binopTable
The oracle table for binary operators. Each entry is a BinaryEntry object.
@ UNDEFINED_VARIABLE
Undefined assignment.
std::size_t usize
unsigned MAX_INT 32 or 64 bits according to the CPU.
std::uint32_t uint32
unisgned 32-bits