123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216(**************************************************************************)(* This file is part of BINSEC. *)(* *)(* Copyright (C) 2016-2024 *)(* CEA (Commissariat à l'énergie atomique et aux énergies *)(* alternatives) *)(* *)(* you can redistribute it and/or modify it under the terms of the GNU *)(* Lesser General Public License as published by the Free Software *)(* Foundation, version 2.1. *)(* *)(* It is distributed in the hope that it will be useful, *)(* but WITHOUT ANY WARRANTY; without even the implied warranty of *)(* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *)(* GNU Lesser General Public License for more details. *)(* *)(* See the GNU Lesser General Public License version 2.1 *)(* for more details (enclosed in the file licenses/LGPLv2.1). *)(* *)(**************************************************************************)moduleBv=Sexpr.BvmoduleExpr=Sexpr.ExprmoduleMemory=Sexpr.MemorymoduleStTbl=Sexpr.StTblmoduleBvTbl=Sexpr.BvTblmoduleAxTbl=Sexpr.AxTblmoduleNiTbl=Basic_types.Int.HtblmoduleBiMap=Basic_types.BigInt.Mapletbyte_size=Natural.to_intBasic_types.Constants.bytesizemoduletypeCONTEXT=sigtypebltypebvtypeaxvaladdr_space:intvalvisit_bl:Expr.t->blvalvisit_bv:Expr.t->bvvalvisit_ax:Memory.t->axvaliter_free_variables:(string->Expr.t->unit)->unitvaliter_free_arrays:(string->Memory.t->unit)->unitvalget:Expr.t->bvendtype('bl,'bv,'ax)context=(moduleCONTEXTwithtypebl='blandtypebv='bvandtypeax='ax)moduleContext(S:Libsolver.S):CONTEXTwithtypebl=S.Bl.tandtypebv=S.Bv.tandtypeax=S.Ax.t=structopenStypebl=Bl.ttypebv=Bv.ttypeax=Ax.tletfvariables=StTbl.create16letfarrays=StTbl.create4letbl_cons=BvTbl.create128letbv_cons=BvTbl.create128letax_cons=AxTbl.create64letaddr_space=Kernel_options.Machine.word_size()letarray_sort=Ax.sort~idx:addr_spacebyte_sizeletvisit_select=letreciterlenconcatindexarrayres=iflen=0thenreselseiter(len-1)concat(Bv.succindex)array(concat(Ax.selectarrayindex)res)infunlendirindexarray->letconcat=matchdirwith|Machine.LittleEndian->Bv.append|Machine.BigEndian->Fun.flipBv.appendiniter(len-1)concat(Bv.succindex)array(Ax.selectarrayindex)letrecunroll_storearrayindexxs=ifs=8thenAx.storearrayindexxelseunroll_store(Ax.storearrayindex(Bv.extract~hi:7~lo:0x))(Bv.succindex)(Bv.extract~hi:(s-1)~lo:8x)(s-8)letrecvisit_blbl=tryBvTbl.findbl_consblwithNot_found->lete=matchblwith|Cstbv->ifTerm.Bv.is_zerobvthenBl.botelseBl.top|Load_(* cannot be a bl<1> *)->assertfalse|Unary{f=Not;x;_}->Bl.lognot(visit_blx)|Binary{f=And;x;y;_}->Bl.logand(visit_blx)(visit_bly)|Binary{f=Or;x;y;_}->Bl.logor(visit_blx)(visit_bly)|Binary{f=Xor;x;y;_}->Bl.logxor(visit_blx)(visit_bly)|Binary{f=Eq;x;y;_}->Bv.equal(visit_bvx)(visit_bvy)|Binary{f=Diff;x;y;_}->Bv.diff(visit_bvx)(visit_bvy)|Binary{f=Uge;x;y;_}->Bv.uge(visit_bvx)(visit_bvy)|Binary{f=Ule;x;y;_}->Bv.ule(visit_bvx)(visit_bvy)|Binary{f=Ugt;x;y;_}->Bv.ugt(visit_bvx)(visit_bvy)|Binary{f=Ult;x;y;_}->Bv.ult(visit_bvx)(visit_bvy)|Binary{f=Sge;x;y;_}->Bv.sge(visit_bvx)(visit_bvy)|Binary{f=Sle;x;y;_}->Bv.sle(visit_bvx)(visit_bvy)|Binary{f=Sgt;x;y;_}->Bv.sgt(visit_bvx)(visit_bvy)|Binary{f=Slt;x;y;_}->Bv.slt(visit_bvx)(visit_bvy)|Ite{c;t;e;_}->Bl.ite(visit_blc)(visit_blt)(visit_ble)|Var_|Unary_|Binary_->Bv.to_bl(visit_bvbl)inBvTbl.addbl_consble;eandvisit_bvbv=tryBvTbl.findbv_consbvwithNot_found->lete=matchbvwith|Var{name;size;_}->StTbl.addfvariablesnamebv;Bv.constsizename|Load{len;dir;addr;label;_}->letindex=visit_bvaddrandarray=visit_axlabelinvisit_selectlendirindexarray|Cstbv->Bv.value(Bitvector.size_ofbv)(Bitvector.value_ofbv)|Unary{f=Not;x;_}->Bv.lognot(visit_bvx)|Unary{f=Minus;x;_}->Bv.neg(visit_bvx)|Unary{f=Uextn;x;_}->Bv.uextn(visit_bvx)|Unary{f=Sextn;x;_}->Bv.sextn(visit_bvx)|Unary{f=Restrict{lo;hi};x;_}->Bv.extract~hi~lo(visit_bvx)|Binary{f=Plus;x;y;_}->Bv.add(visit_bvx)(visit_bvy)|Binary{f=Minus;x;y;_}->Bv.sub(visit_bvx)(visit_bvy)|Binary{f=Mul;x;y;_}->Bv.mul(visit_bvx)(visit_bvy)|Binary{f=Udiv;x;y;_}->Bv.udiv(visit_bvx)(visit_bvy)|Binary{f=Sdiv;x;y;_}->Bv.sdiv(visit_bvx)(visit_bvy)|Binary{f=Umod;x;y;_}->Bv.umod(visit_bvx)(visit_bvy)|Binary{f=Smod;x;y;_}->Bv.smod(visit_bvx)(visit_bvy)|Binary{f=Or;x;y;_}->Bv.logor(visit_bvx)(visit_bvy)|Binary{f=And;x;y;_}->Bv.logand(visit_bvx)(visit_bvy)|Binary{f=Xor;x;y;_}->Bv.logxor(visit_bvx)(visit_bvy)|Binary{f=Concat;x;y;_}->Bv.append(visit_bvx)(visit_bvy)|Binary{f=Lsl;x;y;_}->Bv.shift_left(visit_bvx)(visit_bvy)|Binary{f=Lsr;x;y;_}->Bv.shift_right(visit_bvx)(visit_bvy)|Binary{f=Asr;x;y;_}->Bv.shift_right_signed(visit_bvx)(visit_bvy)|Binary{f=Rol;x;y;_}->Bv.rotate_left(visit_bvx)(visit_bvy)|Binary{f=Ror;x;y;_}->Bv.rotate_right(visit_bvx)(visit_bvy)|Binary{f=Eq|Diff|Ule|Ult|Uge|Ugt|Sle|Slt|Sge|Sgt;_}->Bl.to_bv(visit_blbv)|Ite{c;t;e;_}->Bv.ite(visit_blc)(visit_bvt)(visit_bve)inBvTbl.addbv_consbve;eandvisit_ax(ax:Memory.t)=tryAxTbl.findax_consaxwithNot_found->leta=matchaxwith|Root->Ax.constarray_sortSuid.(to_stringzero)|Symbolname->StTbl.addfarraysnameax;Ax.constarray_sortname|Layer{addr;store;over;_}->letbase=visit_bvaddrandarray=visit_axoverinSexpr.Store.fold_term(funivaluearray->lets=Expr.sizeofvalueinletx=visit_bvvalueandindex=Bv.addbase(Bv.valueaddr_spacei)inunroll_storearrayindexxs)arraystoreinAxTbl.addax_consaxa;aletiter_free_variablesf=StTbl.iterffvariablesletiter_free_arraysf=StTbl.iterffarraysletgete=BvTbl.findbv_conseendmoduleMake(F:Libsolver.F)=structmoduleOpen():Solver.S=structmoduleSolver=F()moduleContext=Context(Solver)letvisit_formula_=()letiter_free_variables=Context.iter_free_variablesletiter_free_arrays=Context.iter_free_arraysletassert_formulabl=Solver.assert_formula(Context.visit_blbl)letcheck_sat=Solver.check_satletcheck_sat_assuming?timeoutbl=Solver.check_sat_assuming?timeout(Context.visit_blbl)letget_valuebv=Solver.get_bv_value(Context.visit_bvbv)letfold_array_valuesfarx=Solver.fold_ax_valuesf(Context.visit_axar)xletpush=Solver.pushletpop=Solver.popletclose=Solver.closeendend