123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236(**************************************************************************)(* This file is part of BINSEC. *)(* *)(* Copyright (C) 2016-2026 *)(* 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). *)(* *)(**************************************************************************)(** DBA -> Formula decoder interface. *)moduleInstr_to_Formula=structmoduleF=Binsec_smtlib.FormulamoduleTypes=structtypebinary=F.bv_termtypeboolean=F.bl_termtypememory=F.ax_termendincludeTypesmoduleVarMap=Map.Make(String)typestate={(* Associate to each register the representation of the bitvector
that it contains; and a unique counter needed when we name the
definitions. *)vars:(int*binary)VarMap.t;(* mem and memcount are like vars, but for the memory. *)mem:memory;memcount:int;(* The definitions that we have put so far. *)(* Note: currently we translate the assumes directly as assertions
in the code, which works well only if we want a formula
describing a single path. For path merging, we need a shared
formula with a separate path-condition. *)formula:F.formula;}moduleState=structtypet=stateletadd_assertioncondstate={statewithformula=Binsec_smtlib.Formula.push_front_assertcondstate.formula;}letadd_commentcommentstate={statewithformula=Binsec_smtlib.Formula.push_front_commentcommentstate.formula;}letclearstate=(* Generate a new memory variable. *)letmemcount=state.memcount+1inletmemvar=F.ax_var("memory"^string_of_intmemcount)328inletformula=F.push_front_declare(F.decl@@F.AxDecl(memvar,[]))state.formulainletmem=F.mk_ax_varmemvarin(* Generate new variables. *)letvars,formula=VarMap.fold(funvar(i,b)(vars,formula)->leti=i+1inletsize=b.F.bv_term_sizeinletname=F.bv_var(var^string_of_inti)sizeinletformula=F.push_front_declare(F.decl@@F.BvDecl(name,[]))formulainletterm=F.mk_bv_varnamein(VarMap.addvar(i+1,term)vars,formula))state.vars(state.vars,formula)in{vars;formula;mem;memcount=memcount+1}endletinitial_state=letformula=F.emptyinletmemvar=F.ax_var"memory0"328inletformula=F.push_front_declare(F.decl@@F.AxDecl(memvar,[]))formulainletmem=F.mk_ax_varmemvarin{vars=VarMap.empty;mem;memcount=1;formula}letclear_memory=State.clearletget_formulax=x.formulaletassumecondstate=letstate=State.add_assertioncondstatein((),state)letadd_commentstringstate=State.add_commentstringstateletunknown~name~sizestate=letvar=F.bv_varnamesizeinletformula=F.push_front_declare(F.decl@@F.BvDecl(var,[]))state.formulain(F.mk_bv_varvar,{statewithformula})letunknown=letcount=ref0infun~sizestate->letname="unknown"^string_of_int!countinincrcount;unknown~name~sizestateletset_var~sizestringbinstate=letprev=tryfst@@VarMap.findstringstate.varswithNot_found->0inletnext=prev+1in(* Put a definition. *)letvar=F.bv_var(string^string_of_intnext)sizeinletformula=F.push_front_define(F.def@@F.BvDef(var,[],bin))state.formulainletvars=VarMap.addstring(next,F.mk_bv_varvar)state.varsin{statewithvars;formula}letget_var~sizestringstate=try(snd@@VarMap.findstringstate.vars,state)(* Ideally, we should initialize all registers with an unknown
value. *)withNot_found->letres,state=unknown~sizestateinletvars=VarMap.addstring(0,res)state.varsin(res,{statewithvars})letstore~size_endianaddrvaluestate=letmemvar=F.ax_var("memory"^string_of_intstate.memcount)328inletmem=F.mk_store(size/8)state.memaddrvalueinletformula=F.push_front_define(F.def@@F.AxDef(memvar,[],mem))state.formulainletmem=F.mk_ax_varmemvarin{statewithmem;formula;memcount=state.memcount+1}letload~size_endianaddrstate=(F.mk_select(size/8)state.memaddr,state)letitecondthen_else_state=(F.mk_bv_itecondthen_else_,state)letbool_of_binxstate=(F.mk_bv_equalxF.mk_bv_one,state)letbin_of_boolxstate=(F.mk_bv_itexF.mk_bv_oneF.mk_bv_zero,state)letundef=unknownmoduleBoolean=structincludeTypesletfalse_state=(F.mk_bl_false,state)lettrue_state=(F.mk_bl_true,state)let(||)abstate=(F.mk_bl_orab,state)let(&&)abstate=(F.mk_bl_andab,state)letnotastate=(F.mk_bl_nota,state)endmoduleBinary=structincludeTypesletbiconst~sizeistate=(F.mk_bv_cst(Bitvector.createisize),state)letbvar2op=letf:size:int->binary->binary->State.t->binary*State.t=fun~sizeabstate->let_=sizein(opab,state)infletbimul=bvar2F.mk_bv_mulletbisub=bvar2F.mk_bv_subletbiadd=bvar2F.mk_bv_addletblshr=bvar2F.mk_bv_lshrletbashr=bvar2F.mk_bv_ashrletbshl=bvar2F.mk_bv_shlletbiurem=bvar2F.mk_bv_uremletbiudiv=bvar2F.mk_bv_udivletbisrem=bvar2F.mk_bv_sremletbisdiv=bvar2F.mk_bv_sdivletbxor=bvar2F.mk_bv_xorletbor=bvar2F.mk_bv_orletband=bvar2F.mk_bv_andletbv_right_rotate~size_a_bstate=Xtrasec_options.Logger.warning"bv_right_rotate is imprecise";unknown~sizestateletbv_left_rotate~size_a_bstate=Xtrasec_options.Logger.warning"bv_left_rotate is imprecise";unknown~sizestateletbuext~size~oldsizeastate=(F.mk_bv_zero_extend(size-oldsize)a,state)letbsext~size~oldsizeastate=(F.mk_bv_sign_extend(size-oldsize)a,state)letbextract~lo~hi~oldsizeastate=iflo==0&&hi==oldsize-1then(a,state)else(F.mk_bv_extractInterval.{lo;hi}a,state)letbconcat~size1~size2abstate=let_=size1and_=size2in(F.mk_bv_concatab,state)letbpredop=letf:size:int->binary->binary->State.t->boolean*State.t=fun~sizeabstate->let_=sizein(opab,state)infletbiult=bpredF.mk_bv_ultletbiule=bpredF.mk_bv_uleletbislt=bpredF.mk_bv_sltletbisle=bpredF.mk_bv_sleletbeq=bpredF.mk_bv_equalendend