Legend:
Page
Library
Module
Module type
Parameter
Class
Class type
Source
Source file bitvector.ml
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478(**************************************************************************)(* 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). *)(* *)(**************************************************************************)(*
A bitvector can be:
- either an ocaml int with the 10 least significand bits encoding the size;
- or a boxed record with size, signed and unsigned values.
*)typettypeboxed={size:int;unsigned:Z.t;signed:Z.t}externalis_unboxed:t->bool="%obj_is_int"externalunsafe_to_unboxed:t->Z.t="%identity"externalunsafe_to_boxed:t->boxed="%identity"externalunsafe_of_unboxed:int->t="%identity"externalunsafe_of_boxed:boxed->t="%identity"externalis_small_int:Z.t->bool="%obj_is_int"externalunsafe_to_int:Z.t->int="%identity"letlimits=Array.init128(funi->Z.shift_leftZ.onei)letmasks=Array.mapZ.predlimitsletcreatevaluesize=ifsize<=0theninvalid_arg"Negative bitvector size";ifsize<Sys.int_size-10thenunsafe_of_unboxed((unsafe_to_int(Z.logandvalue(Z.pred(Z.shift_leftZ.onesize)))lsl10)lorsize)elseifsize<1024&&is_small_intvalue&&letival=unsafe_to_intvaluein(ivallsl10)asr10=ivalthenunsafe_of_unboxed((unsafe_to_intvaluelsl10)lorsize)elseletulimit,slimit,umask=ifsize<128then(Array.unsafe_getlimitssize,Array.unsafe_getlimits(size-1),Array.unsafe_getmaskssize)elseletulimit=Z.shift_leftZ.onesizein(ulimit,Z.shift_leftZ.one(size-1),Z.predulimit)inletunsigned=Z.logandvalueumaskinletsigned=ifZ.gequnsignedslimitthenZ.subunsignedulimitelseunsignedinifsize<1024&&is_small_intsigned&&letival=unsafe_to_intsignedin(ivallsl10)asr10=ivalthenunsafe_of_unboxed((unsafe_to_intsignedlsl10)lorsize)elseunsafe_of_boxed{size;unsigned;signed}letsize_oft=ifis_unboxedtthenunsafe_to_int(unsafe_to_unboxedt)land0x3ffelselet{size;_}=unsafe_to_boxedtinsizeletvalue_oft=ifis_unboxedtthenletsize=unsafe_to_int(unsafe_to_unboxedt)land0x3ffinifsize<Sys.int_size-10thenZ.of_int(unsafe_to_int(unsafe_to_unboxedt)asr10)elseletvalue=unsafe_to_int(unsafe_to_unboxedt)asr10inifvalue<0thenZ.extract(Z.of_intvalue)0sizeelseZ.of_intvalueelselet{unsigned;_}=unsafe_to_boxedtinunsignedletsigned_oft=ifis_unboxedtthenletsize=unsafe_to_int(unsafe_to_unboxedt)land0x3ffinifsize<Sys.int_size-10thenletvalue=unsafe_to_int(unsafe_to_unboxedt)asr10andmsb=1lsl(size-1)inZ.of_int((valuelxormsb)-msb)elseZ.of_int(unsafe_to_int(unsafe_to_unboxedt)asr10)elselet{signed;_}=unsafe_to_boxedtinsignedletequal=(=)letcompare=compareletucomparebv1bv2=assert(size_ofbv1=size_ofbv2);Z.compare(value_ofbv1)@@value_ofbv2letscomparebv1bv2=assert(size_ofbv1=size_ofbv2);Z.compare(signed_ofbv1)@@signed_ofbv2lethash=Hashtbl.hashexceptionBad_boundofstringexceptionOperands_size_conflictofstringtypeboolean=boolletcreate_from_tuple(value,size)=createvaluesizeletresizebvsize=create(value_ofbv)sizeletupdatebvvalue=createvalue(size_ofbv)letdiffbv1bv2=not(equalbv1bv2)letzero=createZ.zero1letone=createZ.one1letzerossize=createZ.zerosizeletonessize=createZ.onesizeletfill?lo?hisize=letlo=matchlowithNone->0|Somel->linlethi=matchhiwithNone->size-1|Someh->hiniflo<0||hi>=size||hi<lotheninvalid_arg"Invalid bitvector size";create(Z.shift_left(Z.pred(Z.shift_leftZ.one(hi-lo+1)))lo)sizeletmax_ubvn=fillnletmax_sbvn=ifn<=0theninvalid_arg"Invalid bitvector size";create(Z.pred(Z.shift_leftZ.one(n-1)))nletmin_sbvn=ifn<=0theninvalid_arg"Invalid bitvector size";create(Z.shift_leftZ.one(n-1))nletis_zerobv=equalbvzeroletis_onebv=equalbvoneletis_zerosbv=ifis_unboxedbvthenunsafe_to_int(unsafe_to_unboxedbv)lsr10=0elseZ.equal(unsafe_to_boxedbv).unsignedZ.zeroletis_onesbv=ifis_unboxedbvthenunsafe_to_int(unsafe_to_unboxedbv)lsr10=1elseZ.equal(unsafe_to_boxedbv).unsignedZ.oneletis_fillbv=equalbv(fill(size_ofbv))letis_max_ubvbv=equalbv(max_ubv(size_ofbv))letis_max_sbvbv=equalbv(max_sbv(size_ofbv))letis_min_sbvbv=equalbv(min_sbv(size_ofbv))(* Utils *)letppppfbv=Format.fprintfppf"{%s; %i}"(Z.to_string(value_ofbv))(size_ofbv)letprintbv=Printf.sprintf"{%s; %i}"(Z.to_string(value_ofbv))(size_ofbv)letbinop_errorbv1bv2msg=Printf.sprintf"%s %s %s"msg(printbv1)(printbv2)letbvint_errorbvimsg=Printf.sprintf"%s %s %i"msg(printbv)iletunsigned_compare(f:Z.t->Z.t->bool)bv1bv2msg=ifsize_ofbv1<>size_ofbv2thenraise(Operands_size_conflict(binop_errorbv1bv2msg))elsef(value_ofbv1)(value_ofbv2)letsigned_compare(f:Z.t->Z.t->bool)bv1bv2msg=ifsize_ofbv1<>size_ofbv2thenraise(Operands_size_conflict(binop_errorbv1bv2msg))elsef(signed_ofbv1)(signed_ofbv2)letunsigned_apply(f:Z.t->Z.t->Z.t)bv1bv2msg=letsize=size_ofbv1inifsize<>size_ofbv2thenraise(Operands_size_conflict(binop_errorbv1bv2msg))elsecreate(f(value_ofbv1)(value_ofbv2))sizeletsigned_apply(f:Z.t->Z.t->Z.t)bv1bv2msg=letsize=size_ofbv1inifsize<>size_ofbv2thenraise(Operands_size_conflict(binop_errorbv1bv2msg))elsecreate(f(signed_ofbv1)(signed_ofbv2))size(* Comparison *)letulebv1bv2=unsigned_compareZ.leqbv1bv2"ule"letugebv1bv2=unsigned_compareZ.geqbv1bv2"uge"letultbv1bv2=unsigned_compareZ.ltbv1bv2"ult"letugtbv1bv2=unsigned_compareZ.gtbv1bv2"ugt"letslebv1bv2=signed_compareZ.leqbv1bv2"sle"letsgebv1bv2=signed_compareZ.geqbv1bv2"sge"letsltbv1bv2=signed_compareZ.ltbv1bv2"slt"letsgtbv1bv2=signed_compareZ.gtbv1bv2"sgt"(* Arithmetic *)letsuccbv=create(Z.succ(value_ofbv))(size_ofbv)letpredbv=create(Z.pred(value_ofbv))(size_ofbv)letadd_intbvi=create(Z.add(Z.of_inti)(value_ofbv))(size_ofbv)letaddbv1bv2=unsigned_applyZ.addbv1bv2"add"letsubbv1bv2=unsigned_applyZ.subbv1bv2"sub"letmulbv1bv2=unsigned_applyZ.mulbv1bv2"mul"letudivbv1bv2=unsigned_applyZ.divbv1bv2"udiv"letumodbv1bv2=unsigned_applyZ.rembv1bv2"umod"leturembv1bv2=unsigned_applyZ.rembv1bv2"urem"letpowbv1bv2=unsigned_apply(funz1z2->Z.powz1(Z.to_intz2))bv1bv2"pow"letumaxbv1bv2=ifugebv1bv2thenbv1elsebv2letuminbv1bv2=ifulebv1bv2thenbv1elsebv2letsdivbv1bv2=signed_applyZ.divbv1bv2"sdiv"letsmodbv1bv2=signed_apply(funab->letr=Z.remabinifZ.equalrZ.zero||Z.ltaZ.zero=Z.ltbZ.zerothenrelseZ.addbr)bv1bv2"smod"letsrembv1bv2=signed_applyZ.rembv1bv2"srem"letnegbv=updatebv(Z.neg(signed_ofbv))letsmaxbv1bv2=ifsgebv1bv2thenbv1elsebv2letsminbv1bv2=ifslebv1bv2thenbv1elsebv2letis_negbv=Z.lt(signed_ofbv)Z.zeroletis_posbv=Z.gt(signed_ofbv)Z.zero(* Logical *)letlogandbv1bv2=unsigned_applyZ.logandbv1bv2"logand"letlogorbv1bv2=unsigned_applyZ.logorbv1bv2"logor"letlogxorbv1bv2=unsigned_applyZ.logxorbv1bv2"logxor"letlognotbv=updatebv(Z.lognot(value_ofbv))letshift_leftbvi=updatebv(Z.shift_left(value_ofbv)i)letshift_rightbvi=updatebv(Z.shift_right(value_ofbv)i)letshift_right_signedbvi=updatebv(Z.shift_right(signed_ofbv)i)letrotate_leftbvi=leti=imodsize_ofbvandvalue=value_ofbvinupdatebv(Z.logor(Z.shift_leftvaluei)(Z.shift_rightvalue(size_ofbv-i)))letrotate_rightbvi=leti=imodsize_ofbvandvalue=value_ofbvinupdatebv(Z.logor(Z.shift_rightvaluei)(Z.shift_leftvalue(size_ofbv-i)))letreducebvi=ifsize_ofbv<ithenraise(Bad_bound(bvint_errorbvi"reduce"))elseresizebviletextendbvi=ifsize_ofbv>ithenraise(Bad_bound(bvint_errorbvi"extend"))elseresizebviletextend_signedbvi=ifsize_ofbv>ithenraise(Bad_bound(bvint_errorbvi"extend_signed"))elsecreate(signed_ofbv)iletextend_unsafebvi=resizebviletbit_maski=Z.shift_leftZ.oneiletbit_mask_noti=Z.logxorZ.minus_one(bit_maski)letnum_bitsbv=Z.numbits(value_ofbv)letget_bitbvi=Z.testbit(value_ofbv)iletset_bitbvi=updatebv(Z.logor(bit_maski)(value_ofbv))letclear_bitbvi=updatebv(Z.logand(bit_mask_noti)(value_ofbv))letflip_bitbvi=ifget_bitbvithenclear_bitbvielseset_bitbviletappendbv1bv2=create(Z.logor(Z.shift_left(value_ofbv1)(size_ofbv2))(value_ofbv2))(size_ofbv1+size_ofbv2)letconcat=function|[]->failwith"concat"|bv::lst->List.fold_leftappendbvlstletextract~hi~lobv=iflo<0||hi>=size_ofbv||hi<lothenletmsg=Printf.sprintf"restrict %s [%i..%i]"(printbv)lohiinraise(Bad_boundmsg)elseletsize=hi-lo+1increate(Z.extract(value_ofbv)losize)size(* Conversion *)letto_hexstringbv:string=letsize=((size_ofbv+3)/4)+2inletvalue=value_ofbvinletinit_fun=function|0->'0'|1->'x'|n->letoffset=(size-n-1)*4inletdigit=unsafe_to_int(Z.extractvalueoffset4)inletshift=ifdigit<10then0x30else0x57indigit+shift|>char_of_intinString.initsizeinit_funletto_bitstringbv:string=letsize=size_ofbv+2inletvalue=value_ofbvinletinit_fun=function|0->'0'|1->'b'|n->letoffset=size-n-1inletdigit=unsafe_to_int(Z.extractvalueoffset1)indigit+0x30|>char_of_intinString.initsizeinit_funletto_asciistringbv:string=letn=(size_ofbv+7)/8inletv=Z.to_bits(value_ofbv)inlets=Bytes.maken'\x00'inBytes.blit_stringv0s0(minn(String.lengthv));Bytes.unsafe_to_stringsletto_stringbv=ifsize_ofbvmod4==0thento_hexstringbvelseto_bitstringbvletof_bitsstr=create(Z.of_bitsstr)(8*String.lengthstr)letof_stringstr=letlen=String.lengthstriniflen<3thenfailwith"Bitvector.of_string : too short string"elseletsize=match(str.[0],str.[1],str.[2])with|'0','x',_->(len-2)*4|'0','b',_->len-2|'+','0','x'|'-','0','x'->(len-3)*4|'+','0','b'|'-','0','b'->len-3|_->failwith"Bitvector.of_string : should start with [+-]?0[xb]"intrycreate(Z.of_stringstr)sizewithFailure_->raise(Invalid_argument("of_string : "^str))letof_hexstring=of_stringletof_boolb=ifbthenoneelsezeroletto_boolx=ifsize_ofx<>1thenraiseZ.OverflowelseZ.equal(value_ofx)Z.oneletof_charc=create(Z.of_int(Char.codec))8letto_charx=ifsize_ofx>8thenraiseZ.OverflowelseChar.unsafe_chr(Z.to_int(value_ofx))letof_int32i32=create(Z.of_int32i32)32letto_int32bv=Z.to_int32(signed_ofbv)letof_int64i64=create(Z.of_int64i64)64letto_int64bv=Z.to_int64(signed_ofbv)letof_int~sizei=create(Z.of_inti)sizeletto_intbv=Z.to_int(signed_ofbv)letto_uintbv=Z.to_int(value_ofbv)letpp_hexppfbv=Format.fprintfppf"{%s; %i}"(to_hexstringbv)(size_ofbv)(* Should this replace pp_hex? *)letpp_hex_or_binppfbv=Format.fprintfppf"%s"@@to_stringbvmoduleRandom=structletbitssz=sz|>create@@Z.of_int@@Random.bits()letrecunrollszbv=ifsz>30thenbits30|>appendbv|>unroll@@(sz-30)elsebitssz|>appendbvletrand=function|szwhensz<1->assertfalse|1whenRandom.bool()->one|1->zero|szwhensz<=30->bitssz|sz->bits30|>unroll@@(sz-30)endletrand=Random.randmoduletypeCommon=sigtypettypeboolean=boolvalcreate:Z.t->int->tvalcreate_from_tuple:Z.t*int->tvalvalue_of:t->Z.tvalsigned_of:t->Z.tvalsize_of:t->intvalcompare:t->t->intvalucompare:t->t->intvalscompare:t->t->intvalhash:t->intvalzero:tvalone:tvalzeros:int->tvalones:int->tvalfill:?lo:int->?hi:int->int->tvalis_zero:t->boolvalis_one:t->boolvalis_zeros:t->boolvalis_ones:t->boolvalis_fill:t->boolvalmax_ubv:int->tvalmax_sbv:int->tvalmin_sbv:int->tvalis_max_ubv:t->boolvalis_max_sbv:t->boolvalis_min_sbv:t->boolvalequal:t->t->booleanvaldiff:t->t->booleanvalule:t->t->booleanvaluge:t->t->booleanvalult:t->t->booleanvalugt:t->t->booleanvalsle:t->t->booleanvalsge:t->t->booleanvalslt:t->t->booleanvalsgt:t->t->booleanincludeSigs.ARITHMETICwithtypet:=tvalpow:t->t->tvalsucc:t->tvalpred:t->tvaladd_int:t->int->tvalumax:t->t->tvalumin:t->t->tvalsmax:t->t->tvalsmin:t->t->tvalis_neg:t->boolvalis_pos:t->bool(* land, lor, lxor and lnot are keywords... *)includeSigs.BITWISEwithtypet:=tvalreduce:t->int->tvalextend:t->int->tvalextend_signed:t->int->tvalextend_unsafe:t->int->tvalnum_bits:t->intvalget_bit:t->int->boolvalset_bit:t->int->tvalclear_bit:t->int->tvalflip_bit:t->int->tvalappend:t->t->tvalconcat:tlist->tvalextract:hi:int->lo:int->t->tendmoduleCollection=Collection.Hashed(structtypenonrect=tletequal=equallethash=hashletcompare=compareend)moduleMap=Collection.MapmoduleSet=Collection.SetmoduleHtbl=Collection.Htbl