Legend:
Page
Library
Module
Module type
Parameter
Class
Class type
Source
Source file sse_symbolic.ml
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633(**************************************************************************)(* This file is part of BINSEC. *)(* *)(* Copyright (C) 2016-2023 *)(* 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)moduleS=Basic_types.String.MapmoduleState(Solver:Smt_sig.Solver)(QS:QUERY_STATISTICS):STATE=structtypet={formula:Formula.formula;(* SMT2 formula *)vsymbols:Formula.bv_termS.t;(* collection of visible symbols *)vmemory:Formula.ax_term;(* visible memory *)fid:int;(* unique indice counter *)fvariables:Formula.bv_varlistS.t;(* collection of free variables *)fmemory:Formula.ax_var;(* initial memory *)model:Smt_model.t;(* a model that satisfy constraints *)}(** Symbolic state *)letmemory_name="__memory"moduleValue=structtypet=Formula.bv_termletconstant=Formula.mk_bv_cstletlookup(v:Dba.Var.t)t=tryS.findv.namet.vsymbolswithNot_found->raise(Undefv)letread~addrbytes(dir:Machine.endianness)t=letarray=t.vmemoryinletcontent=Formula.mk_selectbytesarrayaddrinletcontent=matchdirwithLittleEndian->content|BigEndian->byteswapcontentin(content,t)letselect_~addr:____=raise(Errors.not_yet_implemented"arrays")letitecondthen_smtelse_smt=Formula.(mk_bv_ite(mk_bv_equalcondmk_bv_one)then_smtelse_smt)letunarye(op:Dba.Unary_op.t)=matchopwith|Not->Formula.mk_bv_not|UMinus->Formula.mk_bv_neg|Sextn->Formula.mk_bv_sign_extend(n-Dba.Expr.size_ofe)|Uextn->Formula.mk_bv_zero_extend(n-Dba.Expr.size_ofe)|Restrictinterval->Formula.mk_bv_extractintervalletas_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_rightletreceval(e:Dba.Expr.t)state=matchewith|Var{info=Symbol(_,(lazybv));_}|Cstbv->Formula.mk_bv_cstbv|Varv->lookupvstate|Load(bytes,dir,e,None)->letsmt_e=evalestateinfst(read~addr:smt_ebytesdirstate)|Load_->raise(Errors.not_yet_implemented"arrays")|Binary(bop,lop,rop)ase->Logger.debug~level:6"Translating binary %a"Dba_printer.Ascii.pp_bl_terme;letl_smt_e=evallopstateinletr_smt_e=evalropstateinbinarybopl_smt_er_smt_e|Unary(uop,e)->letv=evalestateinunaryeuopv|Ite(c,then_e,else_e)->letcond=evalcstateinletthen_smt=evalthen_estateinletelse_smt=evalelse_estateinitecondthen_smtelse_smtletunary_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)e1e2endletempty()=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=S.empty;vmemory=Formula.mk_ax_varfmemory;fid=1;fvariables=S.empty;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~keepfmletfresh({name;size;_}:Dba.Var.t)state=letv=Formula.bv_var(Printf.sprintf"%s_%d"namestate.fid)sizeinletfid=state.fid+1inleth=matchS.findnamestate.fvariableswith|exceptionNot_found->[v]|h->v::hinletfvariables=S.addnamehstate.fvariablesinletvsymbols=S.addname(Formula.mk_bv_varv)state.vsymbolsinletformula=state.formula|>Formula.push_front_declare@@Formula.mk_bv_declv[]in{statewithformula;vsymbols;fid;fvariables}letalloc~array:__=raise(Errors.not_yet_implemented"arrays")letassignnamevaluestate=letvalue_size=Formula_utils.bv_sizevalueinletvar=Formula.bv_var(Printf.sprintf"%s_%d"namestate.fid)value_sizeinletfid=state.fid+1inletvsymbols=S.addname(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:____=raise(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()inS.iter(fun_->List.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));modelletwith_solverformulaf=QS.Solver.start_timer();letsession=Solver.open_session()inFormula.iter_forward(Solver.putsession)formula;letr=fsessioninSolver.close_sessionsession;QS.Solver.stop_timer();rletcheck_satistifiabilityformulavarsmemory=with_solverformula(funsession->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)formulavarsmemory=with_solverformula(funsession->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[])endletget_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.singleton(Formula.BvVarvar)inletformula=do_optimization~keepformulainmatchFormula.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_uniqueletkeepstate=S.fold(fun_ek->matchewith|{Formula.bv_term_desc=Formula.BvFun(v,[]);_}->Formula.VarSet.add(Formula.BvVarv)k|_->assertfalse)state.vsymbols@@S.fold(fun_lk->List.fold_left(funkv->Formula.VarSet.add(Formula.BvVarv)k)kl)state.fvariables@@matchstate.vmemorywith|{Formula.ax_term_desc=Formula.AxFun(v,[]);_}->Formula.VarSet.add(Formula.AxVarv)@@Formula.VarSet.singleton(Formula.AxVarstate.fmemory)|_->assertfalseletassumeestate=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_sat();Some{statewithformula;fid}|Some{entry_desc=Formula.Define{def_desc=Formula.BlDef(v,_,{bl_term_desc=Formula.BlFalse;_});_;};_;}->assert(v=var);QS.Preprocess.incr_unsat();None|_->(letformula=Formula.push_front_assert(Formula.mk_bl_varvar)formulainmatchSolver.check_satistifiabilityformulastate.fvariablesstate.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_sat();True{statewithformula;fid}|Some{entry_desc=Formula.Define{def_desc=Formula.BlDef(v,_,{bl_term_desc=Formula.BlFalse;_});_;};_;}->assert(v=var);QS.Preprocess.incr_unsat();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.fvariablesstate.fmemory,Solver.check_satistifiabilityformula'state.fvariablesstate.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_sat()elseifBitvector.is_zerobvthenQS.Preprocess.incr_unsat()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.fvariablesstate.fmemoryletmerge__=raiseNon_mergeableletppppfstate=Smt_model.ppppfstate.modelletpp_smtsliceppfstate=matchslicewith|None->Formula_pp.pp_formulappfstate.formula|Somel->letkeep,state=List.fold_left(fun(keep,state)(e,n)->letstate=assignn(Value.evalestate)stateinmatchFormula.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)letas_ascii~namestate=letbuf=Buffer.create16inList.iter(funvar->letname=Formula_utils.bv_var_namevarinmatchSmt_model.find_variablestate.modelnamewith|None->Buffer.add_charbuf'.'|Somebv->assert(Bitvector.size_ofbvmodbyte_size=0);letreciterbv=letsize=Bitvector.size_ofbvinifsize=byte_sizethenBuffer.add_charbuf(Bitvector.to_charbv)elseletbyte=Bitvector.extractbv{Interval.lo=0;hi=7}inBuffer.add_charbuf(Bitvector.to_charbyte);iter(Bitvector.extractbv{Interval.lo=8;hi=size-1})initerbv)@@List.rev@@S.findnamestate.fvariables;Buffer.contentsbufletas_c_string~name:__=raise(Errors.not_yet_implemented"arrays")letassign({name;_}:Dba.Var.t)state=assignnamestateletto_formula{formula;_}=formulaend