1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099(**************************************************************************)(* 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). *)(* *)(**************************************************************************)(** Definition of DBA type *)letinvalid_boolean=Invalid_argument"not a boolean expression"letbad_bound=Invalid_argument"index out of bound"letmismatched_operands=Invalid_argument"mismatched operands size"letinvalid_assignment=Invalid_argument"mismatched assign"typesize=inttypeendianness=Basic_types.endianness=LittleEndian|BigEndiantypeid=int(** An [id] is a local identifier which characterizes an atomic instruction
inside a Dba.block *)typeaddress={base:Virtual_address.t;id:id}(** A DBA [address] is the association of a DBA block address represented by
[base] and a unique [id].
The first element of a block has [id] [0]. *)typeaddresses=addresslisttype'ajump_target=|JInnerof'a(** Jump inside the same block, to a label *)|JOuterofaddress(** Jump outside the block to its first element *)typetag=|Default|Callofaddress|Return(** For call address of return site *)typestate=|OK|KO|Undecodedofstring(** Stop because of unanticipated string of bytes **)|Unsupportedofstring(** Stop because instr is not supported by Binsec **)moduleUnary_op=structtypet=|UMinus|Not|Sextofsize|Uextofsize|RestrictofintInterval.tendmoduleBinary_op=structtypet=|Plus|Minus|Mult|DivU|DivS|RemU|RemS|Or|And|Xor|Concat|LShift|RShiftU|RShiftS|LeftRotate|RightRotate|Eq(* reified comparison: return a 1-bit value *)|Diff|LeqU|LtU|GeqU|GtU|LeqS|LtS|GeqS|GtSletinvert=function|Eq->Diff|Diff->Eq|LeqU->GtU|LtU->GeqU|GeqU->LtU|GtU->LeqU|LeqS->GtS|LtS->GeqS|GeqS->LtS|GtS->LeqS|_->failwith"BinaryOperator.invert"lethas_inverse=function|Eq|Diff|LeqU|LtU|GeqU|GtU|LeqS|LtS|GeqS|GtS->true|_->falseendmoduleVar:sigmoduleTag:sigtypeattribute=Value|Size|Last|PltmoduleAttribute:sigtypet=attributevalcompare:t->t->intvalpp:Format.formatter->t->unitmoduleMap:Map.Swithtypekey=tendtypet=|Flag|Temp|Register|Symbolofattribute*Bitvector.tlazy_t|EmptyincludeSigs.HASHABLEwithtypet:=tendtypet=private{id:int;name:string;size:size;info:Tag.t}valcreate:string->bitsize:Size.Bit.t->tag:Tag.t->tvalflag:?bitsize:Size.Bit.t->string->t(** [flag ~size fname] creates a flag variable.
- [size] defaults to 1
*)valtemporary:string->Size.Bit.t->tvaltemp:Size.Bit.t->t(** [temp n] creates a lvalue representing a temporary of size [n] with name
[Format.sprintf "temp%d" n]. *)valcompare:t->t->intincludeHashtbl.HashedTypewithtypet:=tvalfrom_id:int->t(** [from_id id] returns the variable identified by [id].
@raise Not_found if [id] is not a valid identifier.
*)end=structmoduleTag=structtypeattribute=Value|Size|Last|PltmoduleAttribute=structtypet=attributeletto_int:t->int=function|Value->0|Size->1|Last->2|Plt->3letcompare:t->t->int=funxy->to_intx-to_intyletppppf=function|Value->()|Size->Format.pp_print_stringppf":size"|Last->Format.pp_print_stringppf":last"|Plt->Format.pp_print_stringppf"@plt"moduleMap=Map.Make(structtypenonrect=tletcompare=compareend)endtypet=|Flag|Temp|Register|Symbolofattribute*Bitvector.tlazy_t|Emptyletcompareab=match(a,b)with|Flag,Flag->0|Flag,(Temp|Register|Symbol_|Empty)->-1|Temp,Flag->1|Temp,Temp->0|Temp,(Register|Symbol_|Empty)->-1|Register,(Flag|Temp)->1|Register,Register->0|Register,(Symbol_|Empty)->-1|Symbol_,(Flag|Temp|Register)->1|Symbol(attr,_),Symbol(attr',_)->compareattrattr'|Symbol_,Empty->-1|Empty,(Flag|Temp|Register|Symbol_)->1|Empty,Empty->0letequalab=match(a,b)with|Flag,Flag|Temp,Temp|Register,Register|Empty,Empty->true|Symbol(attr,_),Symbol(attr',_)->attr=attr'|((Flag|Temp|Register|Symbol_|Empty),(Flag|Temp|Register|Symbol_|Empty))->falseletweak_equalab=match(a,b)with|(Flag|Temp|Register|Empty),(Flag|Temp|Register|Empty)->true|((Flag|Temp|Register|Symbol_|Empty),(Flag|Temp|Register|Symbol_|Empty))->falselethash=function|Flag->129913994|Temp->883721435|Register->648017920|Symbol(Value,_)->543159235|Symbol(Size,_)->72223805|Symbol(Last,_)->828390822|Symbol(Plt,_)->985696643|Empty->152507349letweak_hash=function|Flag->152507349|Temp->152507349|Register->152507349|Symbol(Value,_)->543159235|Symbol(Size,_)->72223805|Symbol(Last,_)->828390822|Symbol(Plt,_)->985696643|Empty->152507349endtypet={id:int;name:string;size:size;info:Tag.t}moduleC=Weak.Make(structtypenonrect=tletequaltt'=t.size=t'.size&&Tag.weak_equalt.infot'.info&&String.equalt.namet'.namelethash{name;size;info;_}=Hash.(return(fold_string(fold_int(fold_int(seed0)size)(Tag.weak_hashinfo))name))end)moduleR=Weak.Make(structtypenonrect=tletequaltt'=t.id=t'.idlethash{id;_}=idend)letcons=C.create128letid=ref0letrev=R.create128letcreatename~bitsize~tag=lett={id=!id;name;size=Size.Bit.to_intbitsize;info=tag}inlett'=C.mergeconstinift==t'then(incrid;R.addrevt');t'letflag?(bitsize=Size.Bit.bits1)flagname=createflagname~bitsize~tag:Tag.Flaglettemporarytempnamebitsize=createtempname~bitsize~tag:Tag.Templettempnbits=letname=Format.asprintf"temp%a"Size.Bit.ppnbitsintemporarynamenbitslethash{id;_}=idletequal=(==)letcomparett'=t.id-t'.idletfrom_idid=lett={id;name="";size=0;info=Tag.Empty}inR.findrevtendmoduleExpr:sigtypet=private|VarofVar.t|Loadofsize(* size: bytes *)*endianness*t*stringoption|CstofBitvector.t|UnaryofUnary_op.t*t|BinaryofBinary_op.t*t*t|Iteoft*t*t(* sugar operator *)valv:Var.t->tvalvar:?tag:Var.Tag.t->string->int->tvalis_equal:t->t->boolvalsize_of:t->int(*
* val var : Size.Bit.t -> string -> Tag.t option -> t
* val flag : ?bits:Size.Bit.t -> string -> t
*
*)valis_constant:t->boolvalconstant:Bitvector.t->tvaltemporary:size:int->string->tvalzeros:int->tvalones:int->tvalone:tval_true:tvalzero:tval_false:tvalbinary:Binary_op.t->t->t->tvaladd:t->t->tvaladdi:t->int->tvaladdz:t->Z.t->tvalsub:t->t->tvalsubi:t->int->tvalsubz:t->Z.t->tvalmul:t->t->tvalsrem:t->t->tvalurem:t->t->tvaludiv:t->t->tvalsdiv:t->t->tvalappend:t->t->tincludeSigs.COMPARISONwithtypet:=tandtypeboolean=tvalunary:Unary_op.t->t->tvaluminus:t->tincludeSigs.LOGICALwithtypet:=tvallogxor:t->t->tvalshift_left:t->t->tvalshift_right:t->t->tvalshift_right_signed:t->t->tvalrotate_left:t->t->tvalrotate_right:t->t->tvalsext:int->t->tvaluext:int->t->tvalite:t->t->t->tvalrestrict:int->int->t->tvalbit_restrict:int->t->tvalload:?array:string->Size.Byte.t->endianness->t->tvalis_max:t->boolend=structopenBinary_optypet=|VarofVar.t|Loadofsize(* size: bytes *)*endianness*t*stringoption|CstofBitvector.t|UnaryofUnary_op.t*t|BinaryofBinary_op.t*t*t|Iteoft*t*t(* sugar operator *)typeboolean=tletrecsize_of=function|Cstb->Bitvector.size_ofb|Varv->v.size|Load(bytesize,_,_,_)->8*bytesize|Ite(_,e,_)|Unary((Unary_op.UMinus|Unary_op.Not),e)->size_ofe|Unary((Unary_op.Sextbits|Unary_op.Uextbits),_)->bits|Unary(Unary_op.Restrict{Interval.lo;Interval.hi},_)->hi-lo+1|Binary(bop,e1,e2)->(matchbopwith|Concat->size_ofe1+size_ofe2|Eq|Diff|LeqU|LtU|GeqU|GtU|LeqS|LtS|GeqS|GtS->1|Plus|Minus|Mult|DivU|DivS|RemU|RemS|Or|And|Xor|LShift|RShiftU|RShiftS|LeftRotate|RightRotate->size_ofe1)letrecis_equale1e2=match(e1,e2)with|Varv1,Varv2->v1=v2|Load(sz1,en1,e1,arr1),Load(sz2,en2,e2,arr2)->sz1=sz2&&en1=en2&&is_equale1e2&&arr1=arr2|Cstbv1,Cstbv2->Bitvector.equalbv1bv2|Unary(unop1,e1),Unary(unop2,e2)->unop1=unop2&&is_equale1e2|Binary(binop1,lexpr1,rexpr1),Binary(binop2,lexpr2,rexpr2)->binop1=binop2&&is_equallexpr1lexpr2&&is_equalrexpr1rexpr2|Ite(c1,e11,e12),Ite(c2,e21,e22)->is_equalc1c2&&is_equale11e21&&is_equale12e22|_,_->falseletis_constant=functionCst_->true|_->falselet_is_zero=functionCstbv->Bitvector.is_zerosbv|_->falselet_is_one=functionCstbv->Bitvector.is_onesbv|_->falseletis_max=functionCstbv->Bitvector.is_max_ubvbv|_->falseletvva=Varvaletvar?(tag=Var.Tag.Empty)namesize=Var(Var.create~tagname~bitsize:(Size.Bit.createsize))lettemporary~sizename=varnamesize~tag:Var.Tag.Templetconstantbv=Cstbvletzeroslength=constant(Bitvector.zeroslength)letoneslength=constant(Bitvector.oneslength)letzero=constantBitvector.zerolet_false=zeroletone=constantBitvector.onelet_true=oneletiteconditionthen_exprelse_expr=(* Valid conditions are bitvectors of size one only *)ifsize_ofcondition<>1thenraiseinvalid_boolean;ifsize_ofthen_expr<>size_ofelse_exprthenraisemismatched_operands;matchconditionwith|CstbwhenBitvector.is_zerob->else_expr|CstbwhenBitvector.is_oneb->then_expr|_->Ite(condition,then_expr,else_expr)letload?arraynbytesendiannesse=letnbytes=Size.Byte.to_intnbytesinLoad(nbytes,endianness,e,array)moduleStraight=structletunaryope=Unary(op,e)letlognot=unaryUnary_op.Notletuminus=unaryUnary_op.UMinusletsextbits=unary(Unary_op.Sextbits)letuextbits=unary(Unary_op.Uextbits)letrestrictlohie=ifhi>=size_ofe||hi<lo||lo<0thenraisebad_bound;unary(Unary_op.Restrict{Interval.lo;Interval.hi})eletbinaryope1e2=Binary(op,e1,e2)letappend=binaryConcatletshift_binaryope1e2=lets1=size_ofe1ands2=size_ofe2inifs1<s2thenraisemismatched_operandselseifs2<s1thenbinaryope1(matche2with|Cstbv->constant(Bitvector.extendbvs1)|_->uexts1e2)elsebinaryope1e2letshift_left=shift_binaryLShiftletshift_right=shift_binaryRShiftUletshift_right_signed=shift_binaryRShiftSletrotate_left=shift_binaryLeftRotateletrotate_right=shift_binaryRightRotateletsymmetric_binaryope1e2=ifsize_ofe1<>size_ofe2thenraisemismatched_operands;binaryope1e2letadd=symmetric_binaryPlusletsub=symmetric_binaryMinusletmul=symmetric_binaryMultletsrem=symmetric_binaryRemSleturem=symmetric_binaryRemUletudiv=symmetric_binaryDivUletsdiv=symmetric_binaryDivSletlogor=symmetric_binaryOrletlogxor=symmetric_binaryXorletlogand=symmetric_binaryAndletequal=symmetric_binaryEqletdiff=symmetric_binaryDiffletule=symmetric_binaryLeqUletsle=symmetric_binaryLeqSletult=symmetric_binaryLtUletslt=symmetric_binaryLtSletuge=symmetric_binaryGeqUletsge=symmetric_binaryGeqSletugt=symmetric_binaryGtUletsgt=symmetric_binaryGtSend(* f e1 (e2::e3) -> g (f e1_(|e3|..|e1| - 1) e2) (f e1_(0..|e3| - 1) e3) *)letrecsplit_applyfge1e2e3=lets1=size_ofe1ands3=size_ofe3inlete1_2=restricts3(s1-1)e1ande1_3=restrict0(s3-1)e1ing(fe1_2e2)(fe1_3e3)(* All the following construction functions are defined w.r.t to the
* "straight" ones. Hence no "rec" keyword after the let is usually *not* an
* error
*)anduminus=function|Cstbv->constant(Bitvector.negbv)|Unary(Unary_op.UMinus,e)->e|e->Straight.uminuseandlognot=function|Cstbv->constant(Bitvector.lognotbv)|Unary(Unary_op.Not,e)->e|Unary(Unary_op.Sextn,e)whensize_ofe=1->sextn(lognote)|Binary(op,e1,e2)whenBinary_op.has_inverseop->binary(Binary_op.invertop)e1e2|e->Straight.lognoteanduextsize=function|ewhensize=size_ofe->e|Cstbv->constantBitvector.(extendbvsize)|Unary(Unary_op.Uext_,e)|e->Straight.uextsizeeandsextsize=function|ewhensize=size_ofe->e|Cstbv->constantBitvector.(extend_signedbvsize)|Unary(Unary_op.Uext_,e)->Straight.uextsizee|Unary(Unary_op.Sext_,e)|e->Straight.sextsizeeandrestrictlohi=function|ewhenlo=0&&hi=size_ofe-1->e|Cstbv->constant(Bitvector.extract~hi~lobv)|Load(sz,LittleEndian,addr,array)when(8*sz)-hi>8->letsz'=Size.Byte.create(sz-(((8*sz)-hi-1)/8))inrestrictlohi(loadsz'LittleEndianaddr?array)|Load(sz,LittleEndian,addr,array)whenlo>=8->letbz'=lo/8inletlo'=lo-(8*bz')andhi'=hi-(8*bz')inletsz'=Size.Byte.create(sz-bz')inletsize=size_ofaddrinletaddr'=addaddr(constant(Bitvector.of_int~sizebz'))inrestrictlo'hi'(loadsz'LittleEndianaddr'?array)|Unary(Unary_op.Restrict{Interval.lo=lo';_},e)->Straight.restrict(lo'+lo)(lo'+hi)e|Unary(Unary_op.Uext_,e)whensize_ofe<=lo->zeros(hi-lo+1)|Unary((Unary_op.Uext_|Unary_op.Sext_),e)whensize_ofe>hi->restrictlohie|Unary(Unary_op.Uext_,e)->uext(hi-lo+1)(restrictlo(size_ofe-1)e)|Unary(Unary_op.Sext_,e)whenlo<size_ofe->sext(hi-lo+1)(restrict(minlo(size_ofe-1))(size_ofe-1)e)|Binary(((Binary_op.And|Binary_op.Or|Binary_op.Xor)asop),e1,e2)->binaryop(restrictlohie1)(restrictlohie2)|Binary(Binary_op.LShift,_,Cstb2)whenBitvector.to_uintb2>hi->zeros(hi-lo+1)|Binary(Binary_op.LShift,e1,Cstb2)whenBitvector.to_uintb2<=lo->restrict(lo-Bitvector.to_uintb2)(hi-Bitvector.to_uintb2)e1|Binary((Binary_op.RShiftU|Binary_op.RShiftS),e1,Cstb2)whensize_ofe1>hi+Bitvector.to_uintb2->restrict(lo+Bitvector.to_uintb2)(hi+Bitvector.to_uintb2)e1|Binary(Binary_op.Concat,_,e2)whenhi<size_ofe2->restrictlohie2|Binary(Binary_op.Concat,e1,e2)whenlo>=size_ofe2->restrict(lo-size_ofe2)(hi-size_ofe2)e1|Binary(Binary_op.Concat,e1,e2)->append(restrict0(hi-size_ofe2)e1)(restrictlo(size_ofe2-1)e2)|e->Straight.restrictlohieandbit_restrictoff=restrictoffoffandunaryope=matchopwith|Unary_op.Not->lognote|Unary_op.UMinus->uminuse|Unary_op.Sexts->sextse|Unary_op.Uexts->uextse|Unary_op.Restrict{Interval.lo;Interval.hi}->restrictlohieandadde1e2=match(e1,e2)with(* Constant propagation *)|Cstb1,Cstb2->constant(Bitvector.addb1b2)(* Invariant: A constant is always on the right side of the root *)|Cst_,_->adde2e1|Binary(Binary_op.Plus,e3,Cstb1),Cstb2->adde3(constant(Bitvector.addb1b2))|Binary(Binary_op.Plus,e3,(Cst_asc4)),_->add(adde3e2)c4|Binary(Binary_op.Minus,e3,Cstb1),Cstb2whenBitvector.sgeb2b1->adde3(constant(Bitvector.subb2b1))|Binary(Binary_op.Minus,e3,Cstb1),Cstb2->sube3(constant(Bitvector.subb1b2))(* Except when it is on the left side of a substraction root *)|Binary(Binary_op.Minus,Cstb1,e3),Cstb2->sub(constant(Bitvector.addb1b2))e3(* Invariant: Linear structure of expression *)|Binary(Binary_op.Plus,_,_),Binary(Binary_op.Plus,e3,e4)->add(adde1e3)e4(* Straightforward elimination *)|_,Binary(Binary_op.Minus,e3,e4)whenis_equale1e4->e3|Binary(Binary_op.Minus,e3,e4),_whenis_equale4e2->e3(* Neutral element *)|_,Cstb2whenBitvector.is_zerosb2->e1(* Default *)|_,_->Straight.adde1e2andsube1e2=match(e1,e2)with(* Constant propagation *)|Cstb1,Cstb2->constant(Bitvector.subb1b2)(* Invariant: Constant is only on: *)(* - the left side of the substraction root *)(* - the right side of the root *)|Cstb1,Binary(Binary_op.Plus,e3,Cstb2)->sub(constant(Bitvector.subb1b2))e3|Cstb1,Binary(Binary_op.Minus,e3,Cstb2)->sub(constant(Bitvector.addb1b2))e3|Cstb1,Binary(Binary_op.Minus,Cstb2,e3)whenBitvector.sgeb1b2->adde3(constant(Bitvector.subb1b2))|Cstb1,Binary(Binary_op.Minus,Cstb2,e3)->sube3(constant(Bitvector.subb2b1))|Binary(Binary_op.Plus,e3,Cstb1),Cstb2whenBitvector.sgeb1b2->adde3(constant(Bitvector.subb1b2))|Binary(Binary_op.Plus,e3,Cstb1),Cstb2->sube3(constant(Bitvector.subb2b1))|Binary(Binary_op.Minus,Cstb1,e3),Cstb2->sub(constant(Bitvector.subb1b2))e3|Binary(Binary_op.Minus,e3,Cstb1),Cstb2->sube3(constant(Bitvector.addb1b2))|Binary(Binary_op.Minus,e3,(Cst_asc4)),_->sub(sube3e2)c4(* Neutral element *)|Cstb1,_whenBitvector.is_zerosb1->uminuse2|_,Cstb2whenBitvector.is_zerosb2->e1(* Straightforward elimination *)|_,_whenis_equale1e2->zeros(size_ofe1)|_,Binary(Binary_op.Plus,e3,e4)whenis_equale1e3->uminuse4|_,Binary(Binary_op.Plus,e3,e4)whenis_equale1e4->uminuse3|Binary(Binary_op.Plus,e3,e4),_whenis_equale2e3->e4|Binary(Binary_op.Plus,e3,e4),_whenis_equale2e4->e3|_,Binary(Binary_op.Minus,e3,e4)whenis_equale1e3->e4|Binary(Binary_op.Minus,e3,e4),_whenis_equale2e3->uminuse4(* Masking *)|Unary(Unary_op.Uextn,e3),Cstb1whenBitvector.is_onesb1&&size_ofe3=1->sextn(lognote3)(* Default *)|_,_->Straight.sube1e2andmule1e2=match(e1,e2)with|Cstb1,Cstb2->constant(Bitvector.mulb1b2)(* neutral element *)|Cstb1,_whenBitvector.is_onesb1->e2(* abosrbing element *)|Cstb1,_whenBitvector.is_zerosb1->e1|_,Cst_->mule2e1|_,_->Straight.mule1e2andudive1e2=match(e1,e2)with|Cstb1,Cstb2->constant(Bitvector.udivb1b2)(* neutral element *)|_,Cstb2whenBitvector.is_onesb2->e1|_,_->Straight.udive1e2andureme1e2=match(e1,e2)with|Cstb1,Cstb2->constant(Bitvector.uremb1b2)|_,_->Straight.ureme1e2andsdive1e2=match(e1,e2)with|Cstb1,Cstb2->constant(Bitvector.sdivb1b2)(* neutral element *)|_,Cstb2whenBitvector.is_onesb2->e1|_,_->Straight.sdive1e2andsreme1e2=match(e1,e2)with|Cstb1,Cstb2->constant(Bitvector.sremb1b2)|_,_->Straight.sreme1e2andlogxore1e2=match(e1,e2)with|Cstb1,Cstb2->constant(Bitvector.logxorb1b2)|Cstb1,_whenBitvector.is_zerosb1->e2|Cstb1,_whenBitvector.is_fillb1->lognote2|Cstb1,Binary(Binary_op.Concat,e3,e4)->lets2=size_ofe2ands4=size_ofe4inletb3=Bitvector.extract~hi:(s2-1)~lo:s4b1inletb4=Bitvector.extract~hi:(s4-1)~lo:0b1inletx3=logxor(constantb3)e3inletx4=logxor(constantb4)e4inappendx3x4|_,Cst_->logxore2e1|_,_whenis_equale1e2->zeros(size_ofe1)|_,_->Straight.logxore1e2andlogore1e2=match(e1,e2)with|Cstb1,Cstb2->constant(Bitvector.logorb1b2)|Cstb1,_whenBitvector.is_zerosb1->e2|Cstb1,_whenBitvector.is_fillb1->e1|Cstb1,Binary(Binary_op.Concat,e3,e4)->lets2=size_ofe2ands4=size_ofe4inletb3=Bitvector.extract~hi:(s2-1)~lo:s4b1inletb4=Bitvector.extract~hi:(s4-1)~lo:0b1inletx3=logor(constantb3)e3inletx4=logor(constantb4)e4inappendx3x4|_,Cst_->logore2e1|_,Unary(Unary_op.Uext_,e3)->try_merge~k:(fun_->Straight.logore1e2)e3~at:0e1|_,Binary(Binary_op.LShift,Unary(Unary_op.Uext_,e3),Cstb1)->letat=Bitvector.to_uintb1intry_merge~k:(fun_->Straight.logore1e2)e3~ate1|Unary(Unary_op.Uext_,_),_|Binary(Binary_op.LShift,Unary(Unary_op.Uext_,_),Cst_),_->logore2e1|_,_whenis_equale1e2->e1|_,_->Straight.logore1e2andlogande1e2=match(e1,e2)with|Cstb1,Cstb2->constant(Bitvector.logandb1b2)|Cstb1,_whenBitvector.is_zerosb1->e1|Cstb1,_whenBitvector.is_fillb1->e2|_,Cst_->logande2e1|Cstb1,Binary(Binary_op.Concat,e3,e4)->letrectry_refine~f~kbe1e2=lethi=Bitvector.size_ofb-1inletlo=hi-size_ofe1+1inletb1=Bitvector.extract~hi~lobinifBitvector.is_fillb1||Bitvector.is_zerosb1thenlete1=ifBitvector.is_fillb1thene1elseconstantb1inletb2=Bitvector.extract~hi:(lo-1)~lo:0binmatche2with|Binary(Binary_op.Concat,e3,e4)->try_refine~f~k:(funr->k(appende1r))b2e3e4|_->k(appende1(logand(constantb2)e2))elsef()intry_refine~f:(fun_->Straight.logande1e2)~k:(funx->x)b1e3e4|_,_whenis_equale1e2->e1|_,_->Straight.logande1e2andappende1e2=match(e1,e2)with|Cstb1,Cstb2->constant(Bitvector.appendb1b2)|Cstb1,_whenBitvector.is_zerosb1->uext(size_ofe1+size_ofe2)e2|Unary(Unary_op.Uexts1,e3),_->uext(s1+size_ofe2)(appende3e2)|_,Unary(Unary_op.Uexts,e2)->Straight.appende1(Straight.append(zeros(s-size_ofe2))e2)|(Unary(Unary_op.Restrict{Interval.lo;Interval.hi},e1),Unary(Unary_op.Restrict{Interval.lo=lo';Interval.hi=hi'},e2))whenhi'+1=lo&&is_equale1e2->restrictlo'hie1|(Binary(((Binary_op.And|Binary_op.Or|Binary_op.Xor)asop),e1,e2),Binary(op',e1',e2'))whenop=op'->binaryop(appende1e1')(appende2e2')|Binary(Binary_op.Concat,e3,e4),_->appende3(appende4e2)|_,_->Straight.appende1e2andequale1e2=match(e1,e2)with|Cstb1,Cstb2->constant(Bitvector.of_bool(Bitvector.equalb1b2))|Cstb1,_whenBitvector.is_zerob1->lognote2|Cstb1,_whenBitvector.is_oneb1->e2|Cst_,Binary(Binary_op.Concat,e3,e4)->split_applyequallogande1e3e4|Cst_,Unary(Unary_op.Uextn,e3)->split_applyequallogande1(constant(Bitvector.zeros(n-size_ofe3)))e3|Binary(Binary_op.Concat,e3,e4),Binary(Binary_op.Concat,e5,e6)whensize_ofe3=size_ofe5->logand(equale3e4)(equale4e6)|_,Cst_->equale2e1|_,_whenis_equale1e2->one|_,_->Straight.equale1e2anddiffe1e2=match(e1,e2)with|Cstb1,Cstb2->constant(Bitvector.of_bool(Bitvector.diffb1b2))|Cstb1,_whenBitvector.is_zerob1->e2|Cstb1,_whenBitvector.is_oneb1->lognote2|Cst_,Binary(Binary_op.Concat,e3,e4)->split_applydifflogore1e3e4|Cst_,Unary(Unary_op.Uextn,e3)->split_applydifflogore1(constant(Bitvector.zeros(n-size_ofe3)))e3|Binary(Binary_op.Concat,e3,e4),Binary(Binary_op.Concat,e5,e6)whensize_ofe3=size_ofe5->logor(diffe3e4)(diffe4e6)|_,Cst_->diffe2e1|_,_whenis_equale1e2->zero|_,_->Straight.diffe1e2andulte1e2=match(e1,e2)with|Cstb1,Cstb2->constant(Bitvector.of_bool(Bitvector.ultb1b2))|_,_whenis_equale1e2->zero|_,_->Straight.ulte1e2andulee1e2=match(e1,e2)with|Cstb1,Cstb2->constant(Bitvector.of_bool(Bitvector.uleb1b2))|_,_whenis_equale1e2->one|_,_->Straight.ulee1e2andugte1e2=match(e1,e2)with|Cstb1,Cstb2->constant(Bitvector.of_bool(Bitvector.ugtb1b2))|_,_whenis_equale1e2->zero|_,_->Straight.ugte1e2andugee1e2=match(e1,e2)with|Cstb1,Cstb2->constant(Bitvector.of_bool(Bitvector.ugeb1b2))|_,_whenis_equale1e2->one|_,_->Straight.ugee1e2andslte1e2=match(e1,e2)with|Cstb1,Cstb2->constant(Bitvector.of_bool(Bitvector.sltb1b2))|_,_whenis_equale1e2->zero|_,_->Straight.slte1e2andslee1e2=match(e1,e2)with|Cstb1,Cstb2->constant(Bitvector.of_bool(Bitvector.sleb1b2))|_,_whenis_equale1e2->one|_,_->Straight.slee1e2andsgte1e2=match(e1,e2)with|Cstb1,Cstb2->constant(Bitvector.of_bool(Bitvector.sgtb1b2))|_,_whenis_equale1e2->zero|_,_->Straight.sgte1e2andsgee1e2=match(e1,e2)with|Cstb1,Cstb2->constant(Bitvector.of_bool(Bitvector.sgeb1b2))|_,_whenis_equale1e2->one|_,_->Straight.sgee1e2androtate_lefte1e2=match(e1,e2)with|Cstb1,Cstb2->constant(Bitvector.rotate_leftb1(Bitvector.to_uintb2))|_,Cstb2whenBitvector.is_zerosb2->e1|_,_->Straight.rotate_lefte1e2androtate_righte1e2=match(e1,e2)with|Cstb1,Cstb2->constant(Bitvector.rotate_rightb1(Bitvector.to_uintb2))|_,Cstb2whenBitvector.is_zerosb2->e1|_,_->Straight.rotate_righte1e2andshift_lefte1e2=match(e1,e2)with|Cstb1,Cstb2->constant(Bitvector.shift_leftb1(Bitvector.to_uintb2))(* w << 0 *)|_,Cstb2whenBitvector.is_zerosb2->e1(* 0 << w *)|Cstb1,_whenBitvector.is_zerosb1->e1|Binary(Concat,e3,e4),Cstb5->lett=size_ofe3ands=Bitvector.to_uintb5inift=sthenappende4(zerost)elseift<sthenappend(restrict0(size_ofe4-1+t-s)e4)(zeross)elseStraight.shift_lefte1e2|_,_->Straight.shift_lefte1e2andshift_righte1e2=match(e1,e2)with|Cstb1,Cstb2->constant(Bitvector.shift_rightb1(Bitvector.to_uintb2))(* w >> 0 *)|_,Cstb2whenBitvector.is_zerosb2->e1(* 0 >> w *)|Cstb1,_whenBitvector.is_zerosb1->e1|_,_->Straight.shift_righte1e2andshift_right_signede1e2=match(e1,e2)with|Cstb1,Cstb2->constant(Bitvector.shift_right_signedb1(Bitvector.to_uintb2))(* w >> 0 *)|_,Cstb2whenBitvector.is_zerosb2->e1(* 0 >> w *)|Cstb1,_whenBitvector.is_zerosb1->e1|_,_->Straight.shift_right_signede1e2andtry_merge~ke1~ate2=letsz1=size_ofe1andsz2=size_ofe2inifat+sz1<=sz2&&restrictat(at+sz1-1)e2=zerossz1thenifat=0thenappend(restrictsz1(sz2-1)e2)e1elseifat+sz1=sz2thenappende1(restrict0(at-1)e2)elseappend(append(restrict(at+sz1)(sz2-1)e2)e1)(restrict0(at-1)e2)elsek()andbinaryop=matchopwith|Plus->add|Minus->sub|Mult->mul|DivU->udiv|DivS->sdiv|RemU->urem|RemS->srem|And->logand|Or->logor|Xor->logxor|Concat->append|LShift->shift_left|RShiftU->shift_right|RShiftS->shift_right_signed|LeftRotate->rotate_left|RightRotate->rotate_right|Eq->equal|Diff->diff|LeqU->ule|LtU->ult|LeqS->sle|LtS->slt|GeqU->uge|GtU->ugt|GeqS->sge|GtS->sgtletaddiei=adde(constant(Bitvector.of_inti~size:(size_ofe)))letaddzez=adde(constant(Bitvector.createz(size_ofe)))letsubiei=sube(constant(Bitvector.of_inti~size:(size_ofe)))letsubzez=sube(constant(Bitvector.createz(size_ofe)))endtypeexprs=Expr.tlisttypeprintable=ExpofExpr.t|StrofstringmoduleTag=structtypet=tagletequal=(=)endmoduleJump_target=structtype'at='ajump_targetletinnern=JInnernletoutera=JOuteraletis_inner=functionJInner_->true|JOuter_->falseletis_outer=functionJOuter_->true|JInner_->falseendmoduletypeINSTR=sigtypetincludeSigs.ARITHMETICwithtypet:=tincludeSigs.BITWISEwithtypet:=tendmoduleLValue=structtypet=|VarofVar.t|RestrictofVar.t*intInterval.t|Storeofsize(* size in bytes *)*endianness*Expr.t*stringoptionletequallv1lv2=match(lv1,lv2)with|Varv1,Varv2->Var.equalv1v2|(Restrict(v1,{Interval.lo=o11;Interval.hi=o12}),Restrict(v2,{Interval.lo=o21;Interval.hi=o22}))->Var.equalv1v2&&o11=o21&&o12=o22|Store(sz1,en1,e1,arr1),Store(sz2,en2,e2,arr2)->sz1=sz2&&en1=en2&&Expr.is_equale1e2&&arr1=arr2|_,_->falseletsize_of=function|Varv->v.size|Restrict(_,{Interval.lo;Interval.hi})->letrestricted_size=hi-lo+1inrestricted_size|Store(sz,_,_,_)->8*szletvva=Varvaletvar?(tag=Var.Tag.Empty)~bitsizename=Var(Var.createname~bitsize~tag)letflag?(bitsize=Size.Bit.bits1)flagname=varflagname~bitsize~tag:Var.Tag.Flaglettemporarytempnamebitsize=vartempname~bitsize~tag:Var.Tag.Templettempnbits=letname=Format.asprintf"temp%a"Size.Bit.ppnbitsintemporarynamenbitsletrestrict(v:Var.t)lohi=ifhi>=v.size||hi<lo||lo<0thenraisebad_bound;ifhi-lo+1=v.sizethenVarvelseRestrict(v,{Interval.lo;Interval.hi})let_restrictnamebitsizelohi=letv=Var.createname~bitsize~tag:Var.Tag.Emptyinrestrictvlohiletbit_restrictvbit=restrictvbitbitlet_bit_restrictnameszbit=_restrictnameszbitbitletstore?arraynbytesendiannesse=letsz=Size.Byte.to_intnbytesinStore(sz,endianness,e,array)letis_expr_translatable=function|Expr.Var_|Expr.Load_|Expr.Unary(Unary_op.Restrict_,Expr.Var_)->true|Expr.Cst_|Expr.Unary_|Expr.Binary_|Expr.Ite_->falseletof_expr=function|Expr.Varv->Varv|Expr.Load(size,endian,e,array)->store(Size.Byte.createsize)endiane?array|Expr.Unary(Unary_op.Restrict{Interval.lo;Interval.hi},Expr.Varv)->restrictvlohi|Expr.Cst_|Expr.Unary_|Expr.Binary_|Expr.Ite_->failwith"LValue.of_expr : Cannot create lvalue from expression"letto_expr=function|Varv->Expr.vv|Restrict(v,{Interval.lo;hi})->Expr.restrictlohi(Expr.varv.namev.size~tag:v.info)|Store(size,endianness,address,array)->Expr.load(Size.Byte.createsize)endiannessaddress?array(* size expected for rhs *)letbitsize=function|Var{size;_}->Size.Bit.createsize|Restrict(_,{Interval.lo;Interval.hi})->letres=hi-lo+1inSize.Bit.createres|Store(sz,_,_,_)->Size.Byte.(to_bitsize(createsz))letresizesize=function|Var{name;info=tag;_}->varname~bitsize:size~tag|Restrict(v,{Interval.lo;Interval.hi})->restrictvlohi|Store(_sz,endianness,e,array)->store(Size.Byte.of_bitsizesize)endiannesse?arrayendmoduleInstr=structtypet=|AssignofLValue.t*Expr.t*id|SJumpofidjump_target*tag|DJumpofExpr.t*tag|IfofExpr.t*idjump_target*id|Stopofstateoption|AssertofExpr.t*id|AssumeofExpr.t*id|NondetofLValue.t*id|UndefofLValue.t*idletassignlvalrvalnid=ifSize.Bit.to_int(LValue.bitsizelval)<>Expr.size_ofrvalthenraiseinvalid_assignment;Assign(lval,rval,nid)letstatic_jump?(tag=Default)jt=SJump(jt,tag)letstatic_inner_jump?tagn=static_jump(Jump_target.innern)?tagletstatic_outer_jump?tagbase=static_jump(Jump_target.outer{base;id=0})?tagletcall~return_addressjt=lettag=Some(Callreturn_address)instatic_jump?tagjtletdynamic_jump?(tag=Default)e=matchewith|Expr.Cstv->letaddr={id=0;base=Virtual_address.of_bitvectorv}instatic_jump(Jump_target.outeraddr)|_->DJump(e,tag)letstopstate=Stopstateletitecgotonid=ifExpr.(is_equalczero)thenstatic_inner_jumpnidelseifExpr.(is_equalcone)thenstatic_jumpgotoelseIf(c,goto,nid)letundefinedlvnid=Undef(lv,nid)letnon_deterministiclvnid=Nondet(lv,nid)let_assertcnid=Assert(c,nid)letassumecnid=Assume(c,nid)end