Legend:
Page
Library
Module
Module type
Parameter
Class
Class type
Source
Source file smt2_solver.ml
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224(**************************************************************************)(* This file is part of BINSEC. *)(* *)(* Copyright (C) 2016-2022 *)(* 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). *)(* *)(**************************************************************************)letbyte_size=Natural.to_intBasic_types.Constants.bytesizemoduleSession=structletn=ref0typestate=Dead|Assert|Sat|Unsattypesession={solver:Prover.t;mutablestate:state;pid:Subprocess.t;stdin:out_channel;stdout:in_channel;stderr:in_channel;stdlog:out_channeloption;fdlog:out_channeloption;formatter:Format.formatter;}letcloset=ignore@@Subprocess.closet.pid;matcht.fdlogwithNone->()|Somefd->close_outfdletstart?stdlogtimeoutsolver=Options.Logger.debug"Openning session %d"!n;letfdlog=matchSmt_options.SMT_dir.get_opt()with|None->None|Somedir->ifnot(Sys.file_existsdir)thenUnix.mkdirdir0o777;letfilename=Filename.concatdir(Printf.sprintf"query_%d.smt2"!n)inSome(open_outfilename)inincrn;letcmd=Prover.command~incremental:truetimeoutsolverinletpid=Subprocess.spawn~pdeathsig:Sys.sigkillcmdinletstdin=Subprocess.stdinpidandstdout=Subprocess.stdoutpidandstderr=Subprocess.stderrpidinletformatter=match(stdlog,fdlog)with|None,None->Format.formatter_of_out_channelstdin|Somestdlog,None->letoutputstrposlen=output_substringstdlogstrposlen;output_substringstdinstrposlenandflush()=flushstdlog;flushstdininFormat.make_formatteroutputflush|None,Somefdlog->letoutputstrposlen=output_substringfdlogstrposlen;output_substringstdinstrposlenandflush()=flushfdlog;flushstdininFormat.make_formatteroutputflush|Somestdlog,Somefdlog->letoutputstrposlen=output_substringstdlogstrposlen;output_substringfdlogstrposlen;output_substringstdinstrposlenandflush()=flushstdlog;flushfdlog;flushstdininFormat.make_formatteroutputflushinFormat.fprintfformatter"@[<v 0>(set-option :print-success false)@ (set-info :smt-lib-version \
2.5)@ (set-logic QF_ABV)@ @]";{solver;state=Assert;pid;stdin;stdout;stderr;stdlog;fdlog;formatter;}typestatus=SAT|UNSAT|UNKNOWNletcheck_satt=Format.fprintft.formatter"(check-sat)@.";matchinput_linet.stdoutwith|"sat"->t.state<-Sat;SAT|"unsat"->t.state<-Unsat;UNSAT|"unknown"->t.state<-Assert;UNKNOWN|s->Options.Logger.fatal"Solver returned: %s"s|exceptionEnd_of_file->t.state<-Dead;UNKNOWNletvalue_of_constantcst=letopenSmtlibinmatchcstwith|CstBoolfalse->Z.zero|CstBooltrue->Z.one|CstBinaryb->Z.of_string_base2b|CstDecimald|CstDecimalSize(d,_)->Z.of_string_base10d|CstHexadecimalx->Z.of_string_base16x|CstNumeral_|CstString_->Options.Logger.fatal"Model construction: unexpected constant %a as bitvector value"Smtlib_pp.pp_spec_constantcstletget_valuetppx=assert(t.state=Sat);Format.fprintft.formatter"(get-value (%a))@."ppx;letlexbuf=Lexing.from_channelt.stdoutinletopenSmtlibinmatchSmtlib_parser.ivalueSmtlib_lexer.tokenlexbufwith|[(_,{term_desc=TermSpecConstantcst;_})]->value_of_constantcst|_->assertfalseletputtppx=ppt.formatterx;Format.pp_print_spacet.formatter();t.state<-Assertend(* utils *)letpp_int_as_bvppfx=function|1->Format.fprintfppf"#b%d"(xland1)|4->Format.fprintfppf"#x%01x"(xland0xf)|8->Format.fprintfppf"#x%02x"(xland0xff)|12->Format.fprintfppf"#x%03x"(xland0xfff)|16->Format.fprintfppf"#x%04x"(xland0xffff)|20->Format.fprintfppf"#x%05x"(xland0xfffff)|24->Format.fprintfppf"#x%06x"(xland0xffffff)|28->Format.fprintfppf"#x%07x"(xland0xfffffff)|32->Format.fprintfppf"#x%08x"(xland0xffffffff)|szwhenx<0->Format.fprintfppf"(_ bv%a %d)"Z.pp_print(Z.extract(Z.of_intx)0sz)sz|sz->Format.fprintfppf"(_ bv%d %d)"xszletpp_bvppfvaluesize=trypp_int_as_bvppf(Z.to_intvalue)sizewithZ.Overflow->Format.fprintfppf"(_ bv%a %d)"Z.pp_print(ifZ.ltvalueZ.zerothenZ.extractvalue0sizeelsevalue)sizemodulePrinter=structopenSexprtypeterm=string*inttypeaccess=Selectofterm*int|Storeofterm*intanddef=BlofExpr.t|BvofExpr.t|AxofMemory.tandt={mutableid:Suid.t;bv_decl:stringBvTbl.t;bl_cons:stringBvTbl.t;bv_cons:stringBvTbl.t;ax_cons:stringAxTbl.t;ax_root:Memory.tAxTbl.t;ordered_defs:defQueue.t;ordered_mem:accessQueue.tAxTbl.t;word_size:int;debug:name:string->label:string->string;}letcreate?(word_size=Kernel_options.Machine.word_size())?(debug=fun~name~label:_->name)~next_id()=letbv_cons=BvTbl.create128andbl_cons=BvTbl.create32inBvTbl.addbl_consExpr.zero"false";BvTbl.addbv_consExpr.zero"#b0";BvTbl.addbl_consExpr.one"true";BvTbl.addbv_consExpr.one"#b1";{id=next_id;bv_decl=BvTbl.create16;bl_cons;bv_cons;ax_cons=AxTbl.create64;ax_root=AxTbl.create64;ordered_defs=Queue.create();ordered_mem=AxTbl.create4;word_size;debug;}letpp_int_as_offsetsizeppfi=pp_bvppfisizeletonce=""letrecvisit_blctxbl=tryifBvTbl.findctx.bl_consbl==oncethen(letname=Suid.to_stringctx.idinctx.id<-Suid.incrctx.id;BvTbl.replacectx.bl_consblname)withNot_found->(matchblwith|Cst_->()|Load_(* cannot be a bl<1> *)->assertfalse|Unary{f=Not;x;_}->BvTbl.addctx.bl_consblonce;visit_blctxx;Queue.push(Blbl)ctx.ordered_defs|Binary{f=And|Or;x;y;_}->BvTbl.addctx.bl_consblonce;visit_blctxx;visit_blctxy;Queue.push(Blbl)ctx.ordered_defs|Binary{f=Eq|Diff|Uge|Ule|Ugt|Ult|Sge|Sle|Sgt|Slt;x;y;_;}->BvTbl.addctx.bl_consblonce;visit_bvctxx;visit_bvctxy;Queue.push(Blbl)ctx.ordered_defs|Ite{c;t;e;_}->BvTbl.addctx.bl_consblonce;visit_blctxc;visit_blctxt;visit_blctxe;Queue.push(Blbl)ctx.ordered_defs|Var_|Unary_|Binary_->visit_bvctxbl)andvisit_bvctxbv=tryifBvTbl.findctx.bv_consbv==oncethen(letname=Suid.to_stringctx.idinctx.id<-Suid.incrctx.id;BvTbl.replacectx.bv_consbvname)withNot_found->(matchbvwith|Var{name;size;label;_}->letname=ctx.debug~name~labelinBvTbl.addctx.bv_consbvname;ifsize=1thenBvTbl.addctx.bl_consbv(Printf.sprintf"(= %s #b1)"name);BvTbl.addctx.bv_declbv(Format.sprintf"(declare-fun %s () (_ BitVec %d))"namesize)|Load{len;addr;label;_}->BvTbl.addctx.bv_consbvonce;visit_bvctxaddr;visit_bvctxaddr;visit_axctxlabel;iflen>1thenvisit_axctxlabel;Queue.push(Bvbv)ctx.ordered_defs;letroot=AxTbl.findctx.ax_rootlabelinletordered_mem=AxTbl.findctx.ordered_memrootinQueue.push(Select((BvTbl.findctx.bv_consaddr,Expr.sizeofaddr),len))ordered_mem|Cst_->BvTbl.addctx.bv_consbvonce;Queue.push(Bvbv)ctx.ordered_defs|Unary{x;_}->BvTbl.addctx.bv_consbvonce;visit_bvctxx;Queue.push(Bvbv)ctx.ordered_defs|Binary{f=Eq|Diff|Uge|Ule|Ugt|Ult|Sge|Sle|Sgt|Slt;_}->BvTbl.addctx.bv_consbvonce;visit_blctxbv;Queue.push(Bvbv)ctx.ordered_defs|Binary{f=Rol|Ror;x;y=(Load_|Unary_|Binary_|Ite_)asy;_;}->BvTbl.addctx.bv_consbvonce;visit_bvctxx;visit_bvctxx;visit_bvctxy;visit_bvctxy;Queue.push(Bvbv)ctx.ordered_defs|Binary{x;y;_}->BvTbl.addctx.bv_consbvonce;visit_bvctxx;visit_bvctxy;Queue.push(Bvbv)ctx.ordered_defs|Ite{c;t;e;_}->BvTbl.addctx.bv_consbvonce;visit_blctxc;visit_bvctxt;visit_bvctxe;Queue.push(Bvbv)ctx.ordered_defs)andvisit_axctx(ax:Memory.t)=tryifAxTbl.findctx.ax_consax==oncethen(letname=Suid.to_stringctx.idinctx.id<-Suid.incrctx.id;AxTbl.replacectx.ax_consaxname)withNot_found->(matchaxwith|Root->AxTbl.addctx.ax_consax(ctx.debug~name:Suid.(to_stringzero)~label:"memory");AxTbl.addctx.ax_rootaxax;AxTbl.addctx.ordered_memax(Queue.create())|Symbolname->AxTbl.addctx.ax_consaxname;AxTbl.addctx.ax_rootaxax;AxTbl.addctx.ordered_memax(Queue.create())|Layer{addr=Cst_;store;over;_}|Overlay{addr=Cst_;store;over;_}->AxTbl.addctx.ax_consaxonce;Store.iter(fun_bv->visit_bvctxbv;ifExpr.sizeofbv>1thenvisit_bvctxbv)store;visit_axctxover;letroot=AxTbl.findctx.ax_rootoverinAxTbl.addctx.ax_rootaxroot;Queue.push(Axax)ctx.ordered_defs;letordered_mem=AxTbl.findctx.ordered_memrootinStore.iter(funibv->letindex=Format.asprintf"%a"(pp_int_as_offsetctx.word_size)iinQueue.push(Store((index,ctx.word_size),Expr.sizeofbv))ordered_mem)store|Layer{addr;store;over;_}|Overlay{addr;store;over;_}->AxTbl.addctx.ax_consaxonce;visit_bvctxaddr;visit_bvctxaddr;Store.iter(fun_bv->visit_bvctxbv;ifExpr.sizeofbv>1thenvisit_bvctxbv)store;visit_axctxover;letroot=AxTbl.findctx.ax_rootoverinAxTbl.addctx.ax_rootaxroot;Queue.push(Axax)ctx.ordered_defs;letordered_mem=AxTbl.findctx.ordered_memrootinletindex=BvTbl.findctx.bv_consaddrinStore.iter(funibv->letindex=Format.asprintf"(bvadd %s %a)"index(pp_int_as_offsetctx.word_size)iinQueue.push(Store((index,ctx.word_size),Expr.sizeofbv))ordered_mem)store)letpp_unopppf(op:Term.unaryTerm.operator)=matchopwith|Not->Format.pp_print_stringppf"bvnot"|Minus->Format.pp_print_stringppf"bvneg"|Uextn->Format.fprintfppf"(_ zero_extend %d)"n|Sextn->Format.fprintfppf"(_ sign_extend %d)"n|Restrict{Interval.hi;lo}->Format.fprintfppf"(_ extract %d %d)"hiloletpp_binop=letstring_of_binop(op:Term.binaryTerm.operator)=matchopwith|Plus->"bvadd"|Minus->"bvsub"|Mul->"bvmul"|Udiv->"bvudiv"|Sdiv->"bvsdiv"|Umod->"bvurem"|Smod->"bvsrem"|Or->"bvor"|And->"bvand"|Xor->"bvxor"|Concat->"concat"|Lsl->"bvshl"|Lsr->"bvlshr"|Asr->"bvashr"|Rol->"rotate_left"|Ror->"rotate_right"|Eq->"="|Diff->assertfalse|Ule->"bvule"|Ult->"bvult"|Uge->"bvuge"|Ugt->"bvugt"|Sle->"bvsle"|Slt->"bvslt"|Sge->"bvsge"|Sgt->"bvsgt"infunppff->Format.pp_print_stringppf(string_of_binopf)letrecprint_blctxppfbl=tryletname=BvTbl.findctx.bl_consblinifname==oncethenprint_bl_no_consctxppfblelseFormat.pp_print_stringppfnamewithNot_found->Format.pp_print_stringppf"(= ";Format.pp_print_spaceppf();print_bvctxppfbl;Format.pp_print_stringppf" #b1)"andprint_bl_no_consctxppfbl=matchblwith|Cst_(* true and false should already be in the cache *)|Load_(* cannot be a bl<1> *)->assertfalse|Unary{f=Not;x;_}->Format.pp_print_stringppf"(not";Format.pp_print_spaceppf();print_blctxppfx;Format.pp_print_charppf')'|Binary{f=(And|Or)asf;x;y;_}->Format.pp_print_charppf'(';(Format.pp_print_stringppf@@matchfwithAnd->"and"|Or->"or"|_->assertfalse);Format.pp_print_spaceppf();print_blctxppfx;Format.pp_print_spaceppf();print_blctxppfy;Format.pp_print_charppf')'|Binary{f=Diff;x;y;_}->Format.pp_print_stringppf"(not";Format.pp_print_spaceppf();Format.pp_print_stringppf"(=";Format.pp_print_spaceppf();print_bvctxppfx;Format.pp_print_spaceppf();print_bvctxppfy;Format.pp_print_stringppf"))"|Binary{f=(Eq|Uge|Ule|Ugt|Ult|Sge|Sle|Sgt|Slt)asf;x;y;_;}->Format.pp_print_charppf'(';pp_binopppff;Format.pp_print_spaceppf();print_bvctxppfx;Format.pp_print_spaceppf();print_bvctxppfy;Format.pp_print_charppf')'|Ite{c;t;e;_}->Format.pp_print_stringppf"(ite";Format.pp_print_spaceppf();print_blctxppfc;Format.pp_print_spaceppf();print_blctxppft;Format.pp_print_spaceppf();print_blctxppfe;Format.pp_print_charppf')'|Var_|Unary_|Binary_->Format.pp_print_stringppf"(=";Format.pp_print_spaceppf();print_bvctxppfbl;Format.pp_print_spaceppf();Format.pp_print_stringppf"#b1)"andprint_bvctxppfbv=letname=BvTbl.findctx.bv_consbvinifname==oncethenprint_bv_no_consctxppfbvelseFormat.pp_print_stringppfnameandprint_bv_no_consctxppfbv=matchbvwith|Var{name;_}->Format.pp_print_stringppfname|Load{len=1;addr;label;_}->Format.pp_print_stringppf"(select";Format.pp_print_spaceppf();print_axctxppflabel;Format.pp_print_spaceppf();print_bvctxppfaddr;Format.pp_print_charppf')'|Load{len;dir;addr;label;_}->Format.pp_print_stringppf"(concat";print_multi_selectdirppflen(AxTbl.findctx.ax_conslabel)(BvTbl.findctx.bv_consaddr)(Expr.sizeofaddr);Format.pp_print_charppf')'|Cstbv->letsize=Bv.size_ofbvandvalue=Bv.value_ofbvinpp_bvppfvaluesize|Unary{f;x;_}->Format.pp_print_charppf'(';pp_unopppff;Format.pp_print_spaceppf();print_bvctxppfx;Format.pp_print_charppf')'|Binary{f=Eq|Uge|Ule|Ugt|Ult|Sge|Sle|Sgt|Slt;_}->Format.pp_print_stringppf"(ite";Format.pp_print_spaceppf();print_blctxppfbv;Format.pp_print_spaceppf();Format.pp_print_stringppf"#b1";Format.pp_print_spaceppf();Format.pp_print_stringppf"#b0)"|Binary{f=Diff;x;y;_}->Format.pp_print_stringppf"(ite (=";Format.pp_print_spaceppf();print_bvctxppfx;Format.pp_print_spaceppf();print_bvctxppfy;Format.pp_print_charppf')';Format.pp_print_spaceppf();Format.pp_print_stringppf"#b0";Format.pp_print_spaceppf();Format.pp_print_stringppf"#b1)"|Binary{f=(Rol|Ror)asf;x;y=Cstbv;_}->Format.pp_print_stringppf"((_";Format.pp_print_spaceppf();pp_binopppff;Format.pp_print_spaceppf();Z.pp_printppf(Bv.value_ofbv);Format.pp_print_charppf')';Format.pp_print_spaceppf();print_bvctxppfx;Format.pp_print_charppf')'|Binary{f=(Rol|Ror)asf;x;y;_}->Format.pp_print_stringppf"(bvor";Format.pp_print_spaceppf();Format.pp_print_charppf'(';pp_binopppf(matchfwithRol->Lsl|Ror->Lsr|_->assertfalse);Format.pp_print_spaceppf();Format.pp_print_stringppf(BvTbl.findctx.bv_consx);Format.pp_print_spaceppf();Format.pp_print_stringppf(BvTbl.findctx.bv_consy);Format.pp_print_charppf')';Format.pp_print_spaceppf();Format.pp_print_charppf'(';pp_binopppf(matchfwithRol->Lsr|Ror->Lsl|_->assertfalse);Format.pp_print_spaceppf();Format.pp_print_stringppf(BvTbl.findctx.bv_consx);Format.pp_print_spaceppf();Format.pp_print_stringppf"(bvsub";Format.pp_print_spaceppf();pp_int_as_bvppf(Expr.sizeofx)(Expr.sizeofx);Format.pp_print_spaceppf();Format.pp_print_stringppf(BvTbl.findctx.bv_consy);Format.pp_print_stringppf")))"|Binary{f;x;y;_}->Format.pp_print_charppf'(';pp_binopppff;Format.pp_print_spaceppf();print_bvctxppfx;Format.pp_print_spaceppf();print_bvctxppfy;Format.pp_print_charppf')'|Ite{c;t;e;_}->Format.pp_print_stringppf"(ite";Format.pp_print_spaceppf();print_blctxppfc;Format.pp_print_spaceppf();print_bvctxppft;Format.pp_print_spaceppf();print_bvctxppfe;Format.pp_print_charppf')'andprint_axctxppfax=letname=AxTbl.findctx.ax_consaxinifname==oncethenprint_ax_no_consctxppfaxelseFormat.pp_print_stringppfnameandprint_ax_no_consctxppf(ax:Memory.t)=matchaxwith|Root->Suid.ppppfSuid.zero|Symbol_->assertfalse|Layer{addr;store;over;_}|Overlay{addr;store;over;_}->Store.iter(fun_value->for_=1toExpr.sizeofvaluelsr3doFormat.pp_print_stringppf"(store";Format.pp_print_spaceppf()done)store;print_axctxppfover;letaddr_space=ctx.word_sizeinletrebase,idx=matchaddrwith|Cst_->(false,"")|_->(true,BvTbl.findctx.bv_consaddr)inletrecunroll_storeloibv=Format.pp_print_spaceppf();ifrebasethenifZ.zero=ithen(Format.pp_print_stringppfidx;Format.pp_print_spaceppf())else(Format.pp_print_stringppf"(bvadd";Format.pp_print_spaceppf();Format.pp_print_stringppfidx;Format.pp_print_spaceppf();pp_bvppfiaddr_space;Format.pp_print_charppf')')elsepp_bvppfiaddr_space;Format.pp_print_spaceppf();letsize=Expr.sizeofbvinifsize>8then(Format.fprintfppf"((_ extract %d %d)"(lo+7)lo;Format.pp_print_spaceppf();print_bvctxppfbv;Format.pp_print_stringppf"))";letlo'=lo+8iniflo'<sizethenunroll_storelo'(Z.succi)bv)else(print_bvctxppfbv;Format.pp_print_charppf')')inStore.iter(unroll_store0)storeandprint_multi_select=letrecprint_multi_select_leppflenaxbvsize=iflen=1thenFormat.fprintfppf" (select@ %s@ %s)"axbvelseletlen=len-1inFormat.fprintfppf" (select@ %s@ (bvadd@ %s@ "axbv;pp_int_as_bvppflensize;Format.pp_print_stringppf"))";print_multi_select_leppflenaxbvsizeinletrecprint_multi_select_beippflenaxbvsize=ifi=0then(Format.fprintfppf"@ (select@ %s@ %s)"axbv;print_multi_select_be1ppflenaxbvsize)elseifi<lenthen(Format.fprintfppf" (select@ %s@ (bvadd@ %s@ "axbv;pp_int_as_bvppfisize;Format.pp_print_stringppf"))";print_multi_select_be(i+1)ppflenaxbvsize)infunction|LittleEndian->print_multi_select_le|BigEndian->print_multi_select_be0letpp_print_declsppfctx=BvTbl.iter(fun_decl->Format.pp_print_stringppfdecl;Format.pp_print_spaceppf())ctx.bv_decl;AxTbl.iter(fun(ax:Memory.t)ordered_mem->matchaxwith|Root->Format.fprintfppf"(declare-fun %s () (Array (_ BitVec %d) (_ BitVec %d)))@ "(ctx.debug~name:Suid.(to_stringzero)~label:"memory")ctx.word_sizebyte_size|Symbolname->ifnot(Queue.is_emptyordered_mem)thenFormat.fprintfppf"(declare-fun %s () (Array (_ BitVec %d) (_ BitVec %d)))@ "namectx.word_sizebyte_size|_->assertfalse)ctx.ordered_memletpp_print_defsppfctx=Queue.iter(function|Blbl->letname=BvTbl.findctx.bl_consblinifname!=oncethen(Format.fprintfppf"@[<h>(define-fun %s () Bool "name;print_bl_no_consctxppfbl;Format.fprintfppf")@]@ ")|Bvbv->letname=BvTbl.findctx.bv_consbvinifname!=oncethen(Format.fprintfppf"@[<h>(define-fun %s () (_ BitVec %d) "name(Expr.sizeofbv);print_bv_no_consctxppfbv;Format.fprintfppf")@]@ ")|Axax->letname=AxTbl.findctx.ax_consaxinifname!=oncethen(Format.fprintfppf"@[<h>(define-fun %s () (Array (_ BitVec %d) (_ BitVec %d)) "name(Kernel_options.Machine.word_size())byte_size;print_ax_no_consctxppfax;Format.fprintfppf")@]@ "))ctx.ordered_defsletpp_print_bl=print_blletpp_print_bv=print_bvletpp_print_ax=print_axendmoduleCross=structopenSexprtypek=|BlofExpr.t|BvofExpr.t|AxofMemory.t|AssertofExpr.t|BvDefineofFormula.bv_var*Expr.t|AxDefineofFormula.ax_var*Memory.tandt={mutableid:Suid.t;bv_decl:Formula.declBvTbl.t;ax_decl:Formula.declAxTbl.t;bl_cons:Formula.bl_varBvTbl.t;bv_cons:Formula.bv_varBvTbl.t;ax_cons:Formula.ax_varAxTbl.t;ordered:kQueue.t;word_size:int;debug:name:string->label:string->string;}letcreate?(word_size=Kernel_options.Machine.word_size())?(debug=fun~name~label:_->name)~next_id()={id=next_id;bv_decl=BvTbl.create16;ax_decl=AxTbl.create1;bl_cons=BvTbl.create32;bv_cons=BvTbl.create128;ax_cons=AxTbl.create64;ordered=Queue.create();word_size;debug;}letbl_once=Formula.bl_var"!"letbv_once=Formula.bv_var"!"1letax_once=Formula.ax_var"!"11letrecvisit_blctxbl=tryifBvTbl.findctx.bl_consbl==bl_oncethen(letname=Suid.to_stringctx.idinctx.id<-Suid.incrctx.id;BvTbl.replacectx.bl_consbl(Formula.bl_varname))withNot_found->(matchblwith|Cst_->()|Load_(* cannot be a bl<1> *)->assertfalse|Unary{f=Not;x;_}->BvTbl.addctx.bl_consblbl_once;visit_blctxx;Queue.push(Blbl)ctx.ordered|Binary{f=And|Or;x;y;_}->BvTbl.addctx.bl_consblbl_once;visit_blctxx;visit_blctxy;Queue.push(Blbl)ctx.ordered|Binary{f=Eq|Diff|Uge|Ule|Ugt|Ult|Sge|Sle|Sgt|Slt;x;y;_;}->BvTbl.addctx.bl_consblbl_once;visit_bvctxx;visit_bvctxy;Queue.push(Blbl)ctx.ordered|Ite{c;t;e;_}->BvTbl.addctx.bl_consblbl_once;visit_blctxc;visit_blctxt;visit_blctxe;Queue.push(Blbl)ctx.ordered|Var_|Unary_|Binary_->visit_bvctxbl)andvisit_bvctxbv=tryifBvTbl.findctx.bv_consbv==bv_oncethen(letname=Suid.to_stringctx.idinctx.id<-Suid.incrctx.id;BvTbl.replacectx.bv_consbv(Formula.bv_varname(Expr.sizeofbv)))withNot_found->(matchbvwith|Var{name;size;label;_}->letname=ctx.debug~name~labelinletvar=Formula.bv_varnamesizeinBvTbl.addctx.bv_consbvvar;BvTbl.addctx.bv_declbv(Formula.mk_bv_declvar[])|Load{addr;label;_}->BvTbl.addctx.bv_consbvbv_once;visit_bvctxaddr;visit_axctxlabel;Queue.push(Bvbv)ctx.ordered|Cst_->BvTbl.addctx.bv_consbvbv_once;Queue.push(Bvbv)ctx.ordered|Unary{x;_}->BvTbl.addctx.bv_consbvbv_once;visit_bvctxx;Queue.push(Bvbv)ctx.ordered|Binary{f=Eq|Diff|Uge|Ule|Ugt|Ult|Sge|Sle|Sgt|Slt;_}->BvTbl.addctx.bv_consbvbv_once;visit_blctxbv;Queue.push(Bvbv)ctx.ordered|Binary{x;y;_}->BvTbl.addctx.bv_consbvbv_once;visit_bvctxx;visit_bvctxy;Queue.push(Bvbv)ctx.ordered|Ite{c;t;e;_}->BvTbl.addctx.bv_consbvbv_once;visit_blctxc;visit_bvctxt;visit_bvctxe;Queue.push(Bvbv)ctx.ordered)andvisit_axctxax=tryifAxTbl.findctx.ax_consax==ax_oncethen(letname=Suid.to_stringctx.idinctx.id<-Suid.incrctx.id;AxTbl.replacectx.ax_consax(Formula.ax_varnamectx.word_size8))withNot_found->(matchaxwith|Memory.Root->letvar=Formula.ax_var(ctx.debug~name:Suid.(to_stringzero)~label:"memory")ctx.word_size8inAxTbl.addctx.ax_consaxvar;AxTbl.addctx.ax_declax(Formula.mk_ax_declvar[])|Memory.Symbolname->letvar=Formula.ax_var(ctx.debug~name~label:"")ctx.word_size8inAxTbl.addctx.ax_consaxvar;AxTbl.addctx.ax_declax(Formula.mk_ax_declvar[])|Memory.Layer{addr;store;over;_}|Memory.Overlay{addr;store;over;_}->AxTbl.addctx.ax_consaxax_once;visit_bvctxaddr;Store.iter(fun_bv->visit_bvctxbv)store;visit_axctxover;Queue.push(Axax)ctx.ordered)letassert_blctxbl=visit_blctxbl;Queue.push(Assertbl)ctx.orderedletdefine_bvctxnamebv=visit_bvctxbv;letvar=Formula.bv_varname(Expr.sizeofbv)inQueue.push(BvDefine(var,bv))ctx.orderedletdefine_axctxnameax=visit_axctxax;letvar=Formula.ax_varnamectx.word_size8inQueue.push(AxDefine(var,ax))ctx.orderedletmk_unop(op:Term.unaryTerm.operator)=matchopwith|Not->Formula.BvNot|Minus->Formula.BvNeg|Uextn->Formula.BvZeroExtendn|Sextn->Formula.BvSignExtendn|Restricti->Formula.BvExtractiletmk_comp(op:Term.binaryTerm.operator)=matchopwith|Eq->Formula.BvEqual|Diff->Formula.BvDistinct|Uge->Formula.BvUge|Ule->Formula.BvUle|Ugt->Formula.BvUgt|Ult->Formula.BvUlt|Sge->Formula.BvSge|Sle->Formula.BvSle|Sgt->Formula.BvSgt|Slt->Formula.BvSlt|Plus|Minus|Mul|Udiv|Sdiv|Umod|Smod|Or|And|Xor|Concat|Lsl|Lsr|Asr|Rol|Ror->assertfalseletmk_bnop(op:Term.binaryTerm.operator)=matchopwith|Eq|Diff|Uge|Ule|Ugt|Ult|Sge|Sle|Sgt|Slt->assertfalse|Plus->Formula.BvAdd|Minus->Formula.BvSub|Mul->Formula.BvMul|Udiv->Formula.BvUdiv|Sdiv->Formula.BvSdiv|Umod->Formula.BvUrem|Smod->Formula.BvSmod|Or->Formula.BvOr|And->Formula.BvAnd|Xor->Formula.BvXor|Concat->Formula.BvConcat|Lsl->Formula.BvShl|Lsr->Formula.BvLshr|Asr->Formula.BvAshr|Rol|Ror->assertfalseletrecmk_blctxbl=tryletvar=BvTbl.findctx.bl_consblinifvar==bl_oncethenmk_bl_no_consctxblelseFormula.mk_bl_varvarwithNot_found->Formula.mk_bv_equal(mk_bvctxbl)Formula.mk_bv_oneandmk_bl_no_consctxbl=matchblwith|Cstbv->ifBitvector.is_onebvthenFormula.mk_bl_trueelseFormula.mk_bl_false|Load_(* cannot be a bl<1> *)->assertfalse|Unary{f=Not;x;_}->Formula.mk_bl_not(mk_blctxx)|Binary{f=And;x;y;_}->Formula.mk_bl_and(mk_blctxx)(mk_blctxy)|Binary{f=Or;x;y;_}->Formula.mk_bl_or(mk_blctxx)(mk_blctxy)|Binary{f=(Eq|Diff|Uge|Ule|Ugt|Ult|Sge|Sle|Sgt|Slt)asf;x;y;_;}->Formula.mk_bv_comp(mk_compf)(mk_bvctxx)(mk_bvctxy)|Ite{c;t;e;_}->Formula.mk_bl_ite(mk_blctxc)(mk_blctxt)(mk_blctxe)|Var_|Unary_|Binary_->Formula.mk_bv_equal(mk_bvctxbl)Formula.mk_bv_oneandmk_bvctxbv=letvar=BvTbl.findctx.bv_consbvinifvar==bv_oncethenmk_bv_no_consctxbvelseFormula.mk_bv_varvarandmk_bv_no_consctxbv=matchbvwith|Var_->assertfalse|Load{len;dir=LittleEndian;addr;label;_}->Formula.mk_selectlen(mk_axctxlabel)(mk_bvctxaddr)|Load{len;dir=BigEndian;addr;label;_}->mk_select_belen(mk_axctxlabel)(mk_bvctxaddr)|Cstbv->Formula.mk_bv_cstbv|Unary{f;x;_}->Formula.mk_bv_unop(mk_unopf)(mk_bvctxx)|Binary{f=Eq|Diff|Uge|Ule|Ugt|Ult|Sge|Sle|Sgt|Slt;_}->Formula.mk_bv_ite(mk_blctxbv)Formula.mk_bv_oneFormula.mk_bv_zero|Binary{f=Rol;x;y=Cstbv;_}->Formula.mk_bv_rotate_left(Bv.to_uintbv)(mk_bvctxx)|Binary{f=Ror;x;y=Cstbv;_}->Formula.mk_bv_rotate_right(Bv.to_uintbv)(mk_bvctxx)|Binary{f=Rol;x;y;_}->Formula.mk_bv_or(Formula.mk_bv_shl(mk_bvctxx)(mk_bvctxy))(Formula.mk_bv_lshr(mk_bvctxx)(Formula.mk_bv_sub_int(mk_bvctxy)(Expr.sizeofx)))|Binary{f=Ror;x;y;_}->Formula.mk_bv_or(Formula.mk_bv_lshr(mk_bvctxx)(mk_bvctxy))(Formula.mk_bv_shl(mk_bvctxx)(Formula.mk_bv_sub_int(mk_bvctxy)(Expr.sizeofx)))|Binary{f;x;y;_}->Formula.mk_bv_bnop(mk_bnopf)(mk_bvctxx)(mk_bvctxy)|Ite{c;t;e;_}->Formula.mk_bv_ite(mk_blctxc)(mk_bvctxt)(mk_bvctxe)andmk_axctxax=letvar=AxTbl.findctx.ax_consaxinifvar==ax_oncethenmk_ax_no_consctxaxelseFormula.mk_ax_varvarandmk_ax_no_consctxax=matchaxwith|Memory.Root|Memory.Symbol_->assertfalse|Memory.Layer{addr;store;over;_}|Memory.Overlay{addr;store;over;_}->letaddr=mk_bvctxaddrinStore.fold(funibvstore->Formula.mk_store1store(Formula.mk_bv_addaddr(Formula.mk_bv_cst(Bitvector.createictx.word_size)))(mk_bvctxbv))(mk_axctxover)storeandmk_select_be=letrecmk_select_belenaxbvsel=iflen=0thenselelseletlen=len-1inmk_select_belenaxbv(Formula.mk_bv_concatsel(Formula.mk_select1ax(Formula.mk_bv_add_intbvlen)))infunlenaxbv->letlen=len-1inmk_select_belenaxbv(Formula.mk_select1ax(Formula.mk_bv_add_intbvlen))letto_formulactx=Queue.fold(funformula->function|Blbl->letvar=BvTbl.findctx.bl_consblinifvar!=bl_oncethenFormula.push_front_define(Formula.mk_bl_defvar[](mk_bl_no_consctxbl))formulaelseformula|Bvbv->letvar=BvTbl.findctx.bv_consbvinifvar!=bv_oncethenFormula.push_front_define(Formula.mk_bv_defvar[](mk_bv_no_consctxbv))formulaelseformula|Axax->letvar=AxTbl.findctx.ax_consaxinifvar!=ax_oncethenFormula.push_front_define(Formula.mk_ax_defvar[](mk_ax_no_consctxax))formulaelseformula|Assertbl->Formula.push_front_assert(mk_blctxbl)formula|BvDefine(var,bv)->Formula.push_front_define(Formula.mk_bv_defvar[](mk_bvctxbv))formula|AxDefine(var,ax)->Formula.push_front_define(Formula.mk_ax_defvar[](mk_axctxax))formula)(BvTbl.fold(fun_declformula->Formula.push_front_declaredeclformula)ctx.bv_decl(AxTbl.fold(fun_declformula->Formula.push_front_declaredeclformula)ctx.ax_declFormula.empty))ctx.orderedendmoduleSolver():Solver_sig.S=structopenSexprtyperesult=Sat|Unsat|Unknowntypeterm=Printer.termletput(ctx:Printer.t)ppfconstraints=Format.pp_open_vboxppf0;(* visit assertions *)List.iter(Printer.visit_blctx)constraints;(* print declarations *)Printer.pp_print_declsppfctx;(* print assertions *)Format.pp_open_hovboxppf0;Printer.pp_print_defsppfctx;List.iter(funbl->Format.pp_print_stringppf"(assert ";Printer.print_blctxppfbl;Format.pp_print_charppf')';Format.pp_print_spaceppf())constraints;Format.pp_close_boxppf();Format.pp_close_boxppf()letsession=Session.start(* ~stdlog:stderr *)(Formula_options.Solver.Timeout.get())(Formula_options.Solver.get())letctx=refNoneletbindfideconstraints=letctx=letx=Printer.create~next_id:fid()inctx:=Somex;xinPrinter.visit_axctxMemory.Root;Printer.visit_bvctxe;Printer.visit_bvctxe;putctxsession.formatterconstraints;(BvTbl.findctx.bv_conse,Expr.sizeofe)letputfidconstraints=letctx=letx=Printer.create~next_id:fid()inctx:=Somex;xinPrinter.visit_axctxMemory.Root;putctxsession.formatterconstraintsletgete=(BvTbl.find(Option.get!ctx).bv_conse,Expr.sizeofe)letset_memory~addry=Session.putsession(funppf()->Format.fprintfppf"(assert (= (select %s "Suid.(to_stringzero);Format.pp_print_charppf' ';pp_bvppfaddr(Option.get!ctx).Printer.word_size;Format.pp_print_stringppf") ";pp_bvppfy8;Format.pp_print_stringppf"))")()letneq(e,s)x=Session.putsession(funppf()->Format.fprintfppf"(assert (not (= %s "e;pp_bvppfxs;Format.pp_print_stringppf")))")()letget_value(x,_)=Session.get_valuesessionFormat.pp_print_stringxletget_atnamexs=Session.get_valuesession(funppfx->Format.pp_print_stringppf"(select ";Format.pp_print_stringppfname;Format.pp_print_charppf' ';pp_bvppfxs;Format.pp_print_charppf')')xletget_arrayar=matchAxTbl.find(Option.get!ctx).ordered_memarwith|exceptionNot_found->[||]|history->ifQueue.is_emptyhistorythen[||]elseletdirty=BiTbl.create(Queue.lengthhistory)inletname=Format.asprintf"%a"(Printer.pp_print_ax(Option.get!ctx))arandaddr_space=(Option.get!ctx).word_sizeinletbinding=Queue.fold(funbinding(access:Printer.access)->matchaccesswith|Select(index,len)->letindex=get_valueindexinletrecfoldindexlenbinding=iflen=0thenbindingelseifBiTbl.memdirtyindexthenfold(Z.succindex)(len-1)bindingelseletk=get_atnameindexaddr_spaceinfold(Z.succindex)(len-1)((index,Char.unsafe_chr(Z.to_intk))::binding)infoldindexlenbinding|Store(index,len)->letindex=get_valueindexinletrecloopindexlen=iflen<>0then(BiTbl.replacedirtyindex();loop(Z.succindex)(len-1))inloopindexlen;binding)[]historyinArray.of_listbindingletcheck_sat()=matchSession.check_satsessionwith|UNKNOWN->Unknown|UNSAT->Unsat|SAT->Satletclose()=Session.closesessionend