123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672(**************************************************************************)(* 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). *)(* *)(**************************************************************************)openOptionsopenTypesletbyte_size=Natural.to_intBasic_types.Constants.bytesizeletbyteswape=letrecloopesizee'=ifsize=0thene'elseloope(size-8)(Formula.mk_bv_concat(Formula.mk_bv_extract{lo=size-8;hi=size-1}e)e')inletsize=Formula_utils.bv_sizeeinloope(size-8)(Formula.mk_bv_extract{lo=size-8;hi=size-1}e)moduleVMap=Dba_types.Var.MapmoduleState(Solver:Smt_sig.Solver)(QS:QUERY_STATISTICS):RAW_STATE=structmoduleUid=structtypet=intletzero=0letsucc=(+)1letcompare=(-)endtypet={mutableformula:Formula.formula;(* SMT2 formula *)vsymbols:Formula.bv_termVMap.t;(* collection of visible symbols *)vmemory:Formula.ax_term;(* visible memory *)mutablefid:int;(* unique indice counter *)fmemory:Formula.ax_var;(* initial memory *)model:Smt_model.t;(* a model that satisfy constraints *)}(** Symbolic state *)letmemory_name="__memory"moduleValue=structtypet=Formula.bv_termletkind=Abstractletconstant=Formula.mk_bv_cstletvaridnamesize=Formula.mk_bv_var(Formula.bv_var(Printf.sprintf"%s_0%d"nameid)size)letitecondthen_smtelse_smt=Formula.(mk_bv_ite(mk_bv_equalcondmk_bv_one)then_smtelse_smt)letas_bvbope1e2=Formula.(mk_bv_ite(bope1e2)mk_bv_onemk_bv_zero)letrotate_right_constn=Formula.mk_bv_rotate_rightnletrotate_left_constn=Formula.mk_bv_rotate_leftnletrotateshift_funcrev_shift_funcconst_rot_funcvalueshift=letopenFormulainmatchshift.bv_term_descwith|BvCstx->letop=Bitvector.value_ofx|>Z.to_int|>const_rot_funcinopvalue|_->letpart1=shift_funcvalueshiftandshift_size=Formula_utils.bv_sizeshiftandvalue_size=Formula_utils.bv_sizevalue|>Z.of_intinletvalue_size=Bitvector.createvalue_sizeshift_size|>mk_bv_cstinletoffset=mk_bv_subvalue_sizeshiftinletpart2=rev_shift_funcvalueoffsetinmk_bv_orpart1part2letrotate_right=rotateFormula.mk_bv_lshrFormula.mk_bv_shlrotate_right_constletrotate_left=rotateFormula.mk_bv_shlFormula.mk_bv_lshrrotate_left_constletbinary(op:Dba.Binary_op.t)=matchopwith|Plus->Formula.mk_bv_add|Minus->Formula.mk_bv_sub|Mult->Formula.mk_bv_mul|DivU->Formula.mk_bv_udiv|DivS->Formula.mk_bv_sdiv|ModU->Formula.mk_bv_urem|ModS->Formula.mk_bv_smod|Eq->as_bvFormula.mk_bv_equal|Diff->as_bvFormula.mk_bv_distinct|LeqU->as_bvFormula.mk_bv_ule|LtU->as_bvFormula.mk_bv_ult|GeqU->as_bvFormula.mk_bv_uge|GtU->as_bvFormula.mk_bv_ugt|LeqS->as_bvFormula.mk_bv_sle|LtS->as_bvFormula.mk_bv_slt|GeqS->as_bvFormula.mk_bv_sge|GtS->as_bvFormula.mk_bv_sgt|Xor->Formula.mk_bv_xor|And->Formula.mk_bv_and|Or->Formula.mk_bv_or|Concat->Formula.mk_bv_concat|LShift->Formula.mk_bv_shl|RShiftU->Formula.mk_bv_lshr|RShiftS->Formula.mk_bv_ashr|LeftRotate->rotate_left|RightRotate->rotate_rightletunary_op(op:Term.unaryTerm.operator)=matchopwith|Not->Formula.BvNot|Minus->Formula.BvNeg|Sextsize->Formula.BvSignExtendsize|Uextsize->Formula.BvZeroExtendsize|Restrictit->Formula.BvExtractitletunaryope=Formula.mk_bv_unop(unary_opop)eletbinary_op(op:Term.binaryTerm.operator)=matchopwith|Plus->Dba.Binary_op.Plus|Minus->Dba.Binary_op.Minus|Mul->Dba.Binary_op.Mult|Udiv->Dba.Binary_op.DivU|Umod->Dba.Binary_op.ModU|Sdiv->Dba.Binary_op.DivS|Smod->Dba.Binary_op.ModS|Or->Dba.Binary_op.Or|And->Dba.Binary_op.And|Xor->Dba.Binary_op.Xor|Concat->Dba.Binary_op.Concat|Lsl->Dba.Binary_op.LShift|Lsr->Dba.Binary_op.RShiftU|Asr->Dba.Binary_op.RShiftS|Rol->Dba.Binary_op.LeftRotate|Ror->Dba.Binary_op.RightRotate|Eq->Dba.Binary_op.Eq|Diff->Dba.Binary_op.Diff|Ule->Dba.Binary_op.LeqU|Ult->Dba.Binary_op.LtU|Uge->Dba.Binary_op.GeqU|Ugt->Dba.Binary_op.GtU|Sle->Dba.Binary_op.LeqS|Slt->Dba.Binary_op.LtS|Sge->Dba.Binary_op.GeqS|Sgt->Dba.Binary_op.GtSletbinaryope1e2=binary(binary_opop)e1e2endletlookup(v:Dba.Var.t)t=tryVMap.findvt.vsymbolswithNot_found->raise(Undefv)letread~addrbytes(dir:Machine.endianness)t=letarray=t.vmemoryinletcontent=Formula.mk_selectbytesarrayaddrinletcontent=matchdirwithLittleEndian->content|BigEndian->byteswapcontentin(content,t)letselect_~addr:____=Errors.not_yet_implemented"arrays"letempty()=letword_size=Kernel_options.Machine.word_size()inletfmemory=Formula.ax_var(memory_name^"_0")word_sizebyte_sizein{formula=Formula.empty|>Formula.push_back_declare@@Formula.mk_ax_declfmemory[];vsymbols=VMap.empty;vmemory=Formula.mk_ax_varfmemory;fid=1;fmemory;model=Smt_model.empty;}letdo_optimization?(keep=Formula.VarSet.empty)fm=letlevel=3inifFormula.VarSet.is_emptykeepthenLogger.debug~level"Optimize"elseLogger.debug~level"@[<v 2>Optimize but keep intact these variables:@ %a@]"Formula_pp.pp_varsetkeep;Formula_transformation.optimize_from_options?is_controlled:None~keepfmletalloc~array:__=Errors.not_yet_implemented"arrays"letassign(lval:Dba.Var.t)valuestate=letvalue_size=Formula_utils.bv_sizevalueinletvar=Formula.bv_var(Printf.sprintf"%s_%d"lval.namestate.fid)value_sizeinletfid=state.fid+1inletvsymbols=VMap.addlval(Formula.mk_bv_varvar)state.vsymbolsinletformula=state.formula|>Formula.push_front_define@@Formula.mk_bv_defvar[]valuein{statewithformula;vsymbols;fid}letwrite~addrvalue(dir:Machine.endianness)state=letvalue=matchdirwithLittleEndian->value|BigEndian->byteswapvalueinletaddr_size=Formula_utils.bv_sizeaddrandwrite_size=Formula_utils.bv_sizevalue/8inletlayer=Formula.ax_var(Printf.sprintf"%s_%d"memory_namestate.fid)addr_sizebyte_sizeinletfid=state.fid+1inletvmemory=Formula.mk_ax_varlayerinletformula=state.formula|>Formula.push_front_define@@Formula.mk_ax_deflayer[]@@Formula.mk_storewrite_sizestate.vmemoryaddrvaluein{statewithformula;vmemory;fid}letstore_~addr:____=Errors.not_yet_implemented"arrays"letmemcpy~addrsizeimgstate=letreader=Lreader.of_zero_extend_bufferimginletchunk=Lreader.Read.readreadersizeinletaddr_size=Bitvector.size_ofaddrinletlayer=Formula.ax_var(Printf.sprintf"%s_%d"memory_namestate.fid)addr_sizebyte_sizeinletfid=state.fid+1inletvmemory=Formula.mk_ax_varlayerinletformula=state.formula|>Formula.push_front_define@@Formula.mk_ax_deflayer[]@@Formula.mk_storesizestate.vmemory(Formula.mk_bv_cstaddr)(Formula.mk_bv_cstchunk)in{statewithformula;vmemory;fid}moduleSolver=structletextract_modelsessionvarsmemory=letmodel=Smt_model.create()inList.iter(funvar->Smt_model.add_varmodel(Formula_utils.bv_var_namevar)(Solver.get_bv_valuesession(Formula.mk_bv_varvar)))vars;Array.iter(fun(addr,value)->Smt_model.add_memcellmodeladdrvalue)(Solver.get_ax_valuessession(Formula.mk_ax_varmemory));modelletdeclare_varsessionmarkedvarvars=match(var:Formula.var)with|BvVarbv_varwhennot(Formula.VarSet.memvarmarked)->Solver.putsession(Formula.mk_declare(Formula.mk_bv_declbv_var[]));bv_var::vars|_->varsletwith_solverformulaf=QS.Solver.start_timer();letsession=Solver.open_session()inletvars,_=Formula.fold_forward(funentry(vars,marked)->letvars,marked=matchentry.entry_descwith|Declare{decl_desc=BvDecl(bv_var,_);_}->(bv_var::vars,Formula.VarSet.add(BvVarbv_var)marked)|Declare{decl_desc=BlDecl_|AxDecl_;_}->(vars,marked)|Define{def_desc=BvDef(bv_var,_,bv_term);_}->letdeps=Formula_utils.bv_term_variablesbv_termin(Formula.VarSet.fold(declare_varsessionmarked)depsvars,Formula.VarSet.add(BvVarbv_var)(Formula.VarSet.uniondepsmarked))|Define{def_desc=BlDef(bl_var,_,bl_term);_}->letdeps=Formula_utils.bl_term_variablesbl_termin(Formula.VarSet.fold(declare_varsessionmarked)depsvars,Formula.VarSet.add(BlVarbl_var)(Formula.VarSet.uniondepsmarked))|Define{def_desc=AxDef(ax_var,_,ax_term);_}->letdeps=Formula_utils.ax_term_variablesax_termin(Formula.VarSet.fold(declare_varsessionmarked)depsvars,Formula.VarSet.add(AxVarax_var)(Formula.VarSet.uniondepsmarked))|Assertbl_term|Assumebl_term->letdeps=Formula_utils.bl_term_variablesbl_termin(Formula.VarSet.fold(declare_varsessionmarked)depsvars,Formula.VarSet.uniondepsmarked)|Comment_->(vars,marked)inSolver.putsessionentry;(vars,marked))formula([],Formula.VarSet.empty)inletr=fsessionvarsinSolver.close_sessionsession;QS.Solver.stop_timer();rletcheck_satistifiabilityformulamemory=with_solverformula(funsessionvars->matchSolver.check_satsessionwith|Formula.SAT->QS.Solver.incr_sat();Logger.debug~level:4"SMT query resulted in SAT";Some(extract_modelsessionvarsmemory)|Formula.UNSAT->QS.Solver.incr_unsat();Logger.debug~level:4"SMT query resulted in UNSAT";None|Formula.UNKNOWN|Formula.TIMEOUT->QS.Solver.incr_err();Logger.warning~level:0"SMT query resulted in UNKNOWN";raiseUnknown)letenumeratee?(n=1lslFormula_utils.bv_sizee)formulamemory=with_solverformula(funsessionvars->letrecloope'nenum=ifn=0thenenumelsematchSolver.check_satsessionwith|Formula.SAT->QS.Solver.incr_sat();letbv=Solver.get_bv_valuesessione'inLogger.debug~level:5"Solver returned %a ; %d solutions still to be found"Bitvector.pp_hexbv(n-1);letmodel=extract_modelsessionvarsmemoryinSolver.putsession@@Formula.mk_assert@@Formula.mk_bv_distincte(Formula.mk_bv_cstbv);loope'(n-1)((bv,model)::enum)|Formula.UNSAT->QS.Solver.incr_unsat();Logger.debug~level:4"Solver returned UNSAT";enum|Formula.UNKNOWN|Formula.TIMEOUT->QS.Solver.incr_err();Logger.warning~level:0"SMT query resulted in UNKNOWN";raiseUnknowninloopen[])endletkeepstate=VMap.fold(fun_ek->matchewith|{Formula.bv_term_desc=Formula.BvFun(v,[]);_}->Formula.VarSet.add(Formula.BvVarv)k|_->assertfalse)state.vsymbols@@matchstate.vmemorywith|{Formula.ax_term_desc=Formula.AxFun(v,[]);_}->Formula.VarSet.add(Formula.AxVarv)@@Formula.VarSet.singleton(Formula.AxVarstate.fmemory)|_->assertfalseletget_valueestate=letsize=Formula_utils.bv_sizeeinletvar=Formula.bv_var(Printf.sprintf"__value_%d"state.fid)sizeinletformula=state.formula|>Formula.push_front_define@@Formula.mk_bv_defvar[]einletkeep=Formula.VarSet.add(Formula.BvVarvar)(keepstate)inletformula=do_optimization~keepformulainstate.formula<-Option.get(Formula.pop_frontformula);matchFormula.peek_frontformulawith|Some{entry_desc=Formula.Define{def_desc=Formula.BvDef(v,_,{bv_term_desc=Formula.BvCstbv;_});_;};_;}->assert(v=var);QS.Preprocess.incr_const();Logger.debug~level:4"Value of %a resolved to constant %a"Formula_pp.pp_bv_termeBitvector.ppbv;bv|_->raiseNon_uniqueletassumeestate=lete=Formula.mk_bv_equaleFormula.mk_bv_oneinletvar=Formula.bl_var(Printf.sprintf"__assume_%d"state.fid)inletfid=state.fid+1inletformula=state.formula|>Formula.push_front_define@@Formula.mk_bl_defvar[]einletkeep=Formula.VarSet.add(Formula.BlVarvar)@@keepstateinletformula=do_optimization~keepformulainmatchFormula.peek_frontformulawith|Some{entry_desc=Formula.Define{def_desc=Formula.BlDef(v,_,{bl_term_desc=Formula.BlTrue;_});_;};_;}->assert(v=var);QS.Preprocess.incr_true();Some{statewithformula;fid}|Some{entry_desc=Formula.Define{def_desc=Formula.BlDef(v,_,{bl_term_desc=Formula.BlFalse;_});_;};_;}->assert(v=var);QS.Preprocess.incr_false();None|_->(letformula=Formula.push_front_assert(Formula.mk_bl_varvar)formulainmatchSolver.check_satistifiabilityformulastate.fmemorywith|Somemodel->Some{statewithformula;fid;model}|None->None)lettestestate=lete=Formula.mk_bv_equaleFormula.mk_bv_oneinletvar=Formula.bl_var(Printf.sprintf"__assume_%d"state.fid)inletfid=state.fid+1inletformula=state.formula|>Formula.push_front_define@@Formula.mk_bl_defvar[]einletkeep=Formula.VarSet.add(Formula.BlVarvar)@@keepstateinletformula=do_optimization~keepformulainmatchFormula.peek_frontformulawith|Some{entry_desc=Formula.Define{def_desc=Formula.BlDef(v,_,{bl_term_desc=Formula.BlTrue;_});_;};_;}->assert(v=var);QS.Preprocess.incr_true();True{statewithformula;fid}|Some{entry_desc=Formula.Define{def_desc=Formula.BlDef(v,_,{bl_term_desc=Formula.BlFalse;_});_;};_;}->assert(v=var);QS.Preprocess.incr_false();False{statewithformula;fid}|_->(letformula=Formula.push_front_assert(Formula.mk_bl_varvar)formulaandformula'=Formula.push_front_assert(Formula.mk_bl_not(Formula.mk_bl_varvar))formulainmatch(Solver.check_satistifiabilityformulastate.fmemory,Solver.check_satistifiabilityformula'state.fmemory)with|Somemodel,Somemodel'->Both{t={statewithformula;fid;model};f={statewithformula=formula';fid;model=model'};}|Somemodel,None->True{statewithformula;fid;model}|None,Somemodel'->False{statewithformula=formula';fid;model=model'}|None,None->raiseUnknown)letenumeratee?n?(except=[])state=letsize=Formula_utils.bv_sizeeinletvar=Formula.bv_var(Printf.sprintf"__enum_%d"state.fid)sizeinletfid=state.fid+1inletformula=state.formula|>Formula.push_front_define@@Formula.mk_bv_defvar[]einletkeep=Formula.VarSet.add(Formula.BvVarvar)@@keepstateinletformula=do_optimization~keepformulainmatchFormula.peek_frontformulawith|Some{entry_desc=Formula.Define{def_desc=Formula.BvDef(v,_,{bv_term_desc=Formula.BvCstbv;_});_;};_;}->assert(v=var);ifBitvector.is_onebvthenQS.Preprocess.incr_true()elseifBitvector.is_zerobvthenQS.Preprocess.incr_false()elseQS.Preprocess.incr_const();Logger.debug~level:4"Enumeration of %a resolved to constant %a"Formula_pp.pp_bv_termeBitvector.ppbv;[(bv,{statewithformula;fid})]|_->letevar=Formula.mk_bv_varvarinletformula=List.fold_left(funfbv->Formula.push_front_assert(Formula.mk_bv_distinctevar(Formula.mk_bv_cstbv))f)formulaexceptinList.map(fun(bv,model)->letformula=formula|>Formula.push_front_assert@@Formula.mk_bv_equalevar(Formula.mk_bv_cstbv)in(bv,{statewithformula;fid;model}))@@Solver.enumerateevar?nformulastate.fmemoryletget_a_valueet=matchenumeratee~n:1twith|[(bv,t')]->t.fid<-t'.fid;t.formula<-t'.formula;bv|_->raiseUnknownletmerge~parent:___=raiseNon_mergeableletassertionst=Formula.fold_forward(fun(e:Formula.entry)r->matchewith|{entry_desc=Assertb;_}->Formula.mk_bv_itebFormula.mk_bv_oneFormula.mk_bv_zero::r|_->r)t.formula[]letppppfstate=Smt_model.ppppfstate.modelletclose_formula=letdeclare_varmarkedvarformula=match(var:Formula.var)with|BvVarbv_varwhennot(Formula.VarSet.memvarmarked)->Formula.push_back_declare(Formula.mk_bv_declbv_var[])formula|_->formulainfunformula->fst(Formula.fold_forward(funentry(formula,marked)->matchentry.entry_descwith|Declare{decl_desc=BvDecl(bv_var,_);_}->(formula,Formula.VarSet.add(BvVarbv_var)marked)|Declare{decl_desc=BlDecl_|AxDecl_;_}->(formula,marked)|Define{def_desc=BvDef(bv_var,_,bv_term);_}->letdeps=Formula_utils.bv_term_variablesbv_termin(Formula.VarSet.fold(declare_varmarked)depsformula,Formula.VarSet.add(BvVarbv_var)(Formula.VarSet.uniondepsmarked))|Define{def_desc=BlDef(bl_var,_,bl_term);_}->letdeps=Formula_utils.bl_term_variablesbl_termin(Formula.VarSet.fold(declare_varmarked)depsformula,Formula.VarSet.add(BlVarbl_var)(Formula.VarSet.uniondepsmarked))|Define{def_desc=AxDef(ax_var,_,ax_term);_}->letdeps=Formula_utils.ax_term_variablesax_termin(Formula.VarSet.fold(declare_varmarked)depsformula,Formula.VarSet.add(AxVarax_var)(Formula.VarSet.uniondepsmarked))|Assertbl_term|Assumebl_term->letdeps=Formula_utils.bl_term_variablesbl_termin(Formula.VarSet.fold(declare_varmarked)depsformula,Formula.VarSet.uniondepsmarked)|Comment_->(formula,marked))formula(formula,Formula.VarSet.empty))letpp_smtsliceppfstate=letstate={statewithformula=close_formulastate.formula}inmatchslicewith|None->Formula_pp.pp_formulappfstate.formula|Somel->letkeep,state=List.fold_left(fun(keep,state)(e,n)->letstate=letvalue_size=Formula_utils.bv_sizeeinletvar=Formula.bv_varnvalue_sizeinletformula=state.formula|>Formula.push_front_define@@Formula.mk_bv_defvar[]ein{statewithformula}inmatchFormula.peek_frontstate.formulawith|Some{entry_desc=Formula.Define{def_desc=Formula.BvDef(v,_,_);_};_;}->(Formula.VarSet.add(Formula.BvVarv)keep,state)|_->assertfalse)(Formula.VarSet.empty,state)linFormula_pp.pp_formulappf(do_optimization~keepstate.formula)letto_formula{formula;_}=close_formulaformulaletgetter_=Noneletsetter_=NoneendtypeOptions.Engine.t+=Legacylet()=Options.Engine.register"legacy"Legacy(fun()->(moduleState((valSmt_solver.get_solver()))))