Legend:
Page
Library
Module
Module type
Parameter
Class
Class type
Source
Source file sexpr.ml
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603(**************************************************************************)(* 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). *)(* *)(**************************************************************************)moduleBv=BitvectormoduleBiMap=Basic_types.BigInt.MapexceptionNon_mergeable=Types.Non_mergeablemodulerecExpr:(Term.Swithtypea:=stringandtypeb:=Memory.t)=Term.Make(structtypet=stringletcompare__=0letequal__=truelethash_=0end)(Memory)andChunk:sigincludeLmap.Valuetypebuffer=(int,Bigarray.int8_unsigned_elt,Bigarray.c_layout)Bigarray.Array1.tvalof_buf:buffer->tvalof_expr:Expr.t->tvalto_expr:t->Expr.tvalis_exported:t->boolvalequal:t->t->boolend=structtypettypebuffer=(int,Bigarray.int8_unsigned_elt,Bigarray.c_layout)Bigarray.Array1.texternalis_unboxed:t->bool="%obj_is_int"externalstill_unboxed:Bv.t->bool="%obj_is_int"externalto_bv:t->Bv.t="%identity"externalof_bv:Bv.t->t="%identity"externalto_expr:t->Expr.t="%identity"externalof_expr:Expr.t->t="%identity"externalto_buf:t->buffer="%identity"externalof_buf:buffer->t="%identity"letis_bufx=Obj.tag(Obj.reprx)=Obj.custom_tagletof_bvbv=ifstill_unboxedbvthenof_bvbvelseof_expr(Expr.constantbv)letequalxy=x==y||(not(is_unboxedx))&&(not(is_bufx))&&(not(is_unboxedy))&&(not(is_bufy))&&Expr.is_equal(to_exprx)(to_expry)letlenx=ifis_unboxedxthenBv.size_of(to_bvx)lsr3elseifis_bufxthenBigarray.Array1.dim(to_bufx)elseExpr.sizeof(to_exprx)lsr3letcrop~lo~hix=ifis_bufxthenof_buf(Bigarray.Array1.sub(to_bufx)lo(hi-lo+1))elseletlo=lolsl3andhi=(hilsl3)+7inifis_unboxedxthenof_bv(Bv.extract(to_bvx){lo;hi})elseof_expr(Expr.restrict~lo~hi(to_exprx))letbuf_to_bvx=letx=to_bufxinlets=Bigarray.Array1.dimxinBv.create(Z.of_bits(String.init(Bigarray.Array1.dimx)(funi->Char.unsafe_chr(Bigarray.Array1.unsafe_getxi))))(slsl3)letconcatxy=ifis_unboxedxthenifis_unboxedythenof_bv(Bv.append(to_bvx)(to_bvy))elseifis_bufythenof_bv(Bv.append(to_bvx)(buf_to_bvy))elseof_expr(Expr.append(Expr.constant(to_bvx))(to_expry))elseifis_bufxthenifis_unboxedythenof_bv(Bv.append(buf_to_bvx)(to_bvy))elseifis_bufythenof_bv(Bv.append(buf_to_bvx)(buf_to_bvy))elseof_expr(Expr.append(Expr.constant(buf_to_bvx))(to_expry))elseifis_unboxedythenof_expr(Expr.append(to_exprx)(Expr.constant(to_bvy)))elseifis_bufythenof_expr(Expr.append(to_exprx)(Expr.constant(buf_to_bvy)))elseof_expr(Expr.append(to_exprx)(to_expry))letto_exprx=ifis_unboxedxthenExpr.constant(to_bvx)elseifis_bufxthenExpr.constant(buf_to_bvx)elseto_exprxletof_expr(x:Expr.t)=matchxwithCstbv->of_bvbv|x->of_exprxletis_exportedx=not(is_bufx)endandStore:sigtypetvalempty:tvalsingleton:Bv.t->Chunk.t->tvalstore:Bv.t->Chunk.t->t->tvalselect:(Z.t->int->Chunk.t)->Bv.t->int->t->Chunk.tvaliter:(Z.t->Expr.t->unit)->t->unitvalfold:(Z.t->Expr.t->'a->'a)->'a->t->'avalmap:(Z.t->Chunk.t->Chunk.t)->t->tvalmerge:(Z.t->Chunk.toption->Chunk.toption->Chunk.toption)->t->t->tend=structincludeLmap.Make(Chunk)letsingletonkv=letz=Bv.value_ofkands=Chunk.lenvinletu=Z.addz(Z.of_ints)inletn=Bv.size_ofkinifZ.numbitsu>n&&Z.popcountu>1thenleto=Z.to_int(Z.extractu0n)instorez(Chunk.crop~hi:(s-o-1)~lo:0v)(singletonZ.zero(Chunk.crop~hi:(s-1)~lo:(s-o)v))elsesingletonzvletstorekvt=letz=Bv.value_ofkands=Chunk.lenvinletu=Z.addz(Z.of_ints)inletn=Bv.size_ofkinifZ.numbitsu>n&&Z.popcountu>1thenleto=Z.to_int(Z.extractu0n)instorez(Chunk.crop~hi:(s-o-1)~lo:0v)(storeZ.zero(Chunk.crop~hi:(s-1)~lo:(s-o)v)t)elsestorezvtletselectfkst=letz=Bv.value_ofkinletu=Z.addz(Z.of_ints)inletn=Bv.size_ofkinifZ.numbitsu>n&&Z.popcountu>1thenleto=Z.to_int(Z.extractu0n)inChunk.concat(selectfZ.zeroot)(selectfz(s-o)t)elseselectfzstletiterft=iter(funkv->ifChunk.is_exportedvthenfk(Chunk.to_exprv))tletfoldfbt=fold(funkvb->ifChunk.is_exportedvthenfk(Chunk.to_exprv)belseb)btendandMemory:sigtypet=|Root|Symbolofstring|Layerof{id:int;over:t;addr:Expr.t;store:Store.t}|Overlayof{id:int;over:t;addr:Expr.t;store:Store.t}valcompare:t->t->intvalequal:t->t->boolvalhash:t->intvalsource:addr:Expr.t->len:int->Loader_buf.t->t->tvalwrite:addr:Expr.t->Expr.t->Expr.endianness->t->tvalread:addr:Expr.t->int->Expr.endianness->t->Expr.t*tvalmerge:Expr.t->t->t->tvalbswap:Expr.t->Expr.tend=structletbswap=letrecitereir=ifi=0thenrelseitere(i-8)(Expr.append(Expr.restrict~hi:(i-1)~lo:(i-8)e)r)infune->letsize=Expr.sizeofeinassert(sizeland0x7=0);itere(size-8)(Expr.restrict~hi:(size-1)~lo:(size-8)e)typet=|Root|Symbolofstring|Layerof{id:int;over:t;addr:Expr.t;store:Store.t}|Overlayof{id:int;over:t;addr:Expr.t;store:Store.t}exceptionWritebackof(Expr.t*t)letid=ref0lethash=function|Root->0|Symbolname->Hashtbl.hashname|Layer{id;_}|Overlay{id;_}->idletcomparett'=hasht-hasht'letequaltt'=match(t,t')with|Root,Root->true|Symbolid,Symbolid'->id=id'|((Layer{id;_}|Overlay{id;_}),(Layer{id=id';_}|Overlay{id=id';_}))->id=id'|((Root|Symbol_|Layer_|Overlay_),(Root|Symbol_|Layer_|Overlay_))->falseletrebase(addr:Expr.t)=matchaddrwith|Cstbv->(Expr.zeros(Bv.size_ofbv),bv)|Binary{f=Plus;x;y=Cstbv;_}->(x,bv)|Binary{f=Minus;x;y=Cstbv;_}->(x,Bv.negbv)|_->(addr,Bv.zeros(Expr.sizeofaddr))letblitoffsetbuflenover=lets=Bigarray.Array1.dimbufiniflen<=sthenletbuf=Bigarray.Array1.subbuf0leninStore.storeoffset(Chunk.of_bufbuf)overelseletbuf'=Bigarray.Array1.createBigarray.int8_unsignedBigarray.C_layout(len-s)inBigarray.Array1.fillbuf'0;ifs=0thenStore.storeoffset(Chunk.of_bufbuf')overelseStore.store(Bv.add_intoffsets)(Chunk.of_bufbuf')(Store.storeoffset(Chunk.of_bufbuf)over)letfilladdrlenorigover=letaddr,offset=rebaseaddrinincrid;Overlay{id=!id;over;addr;store=blitoffsetoriglenStore.empty}letsource~addr~lenorigover=matchoverwith|Root|Symbol_|Layer_->filladdrlenorigover|Overlay{id=id';addr=addr';store=store';over=over'}->(matchExpr.subaddraddr'with|Expr.Cstbv->letstore=blitbvoriglenstore'inincrid;Overlay{id=!id;over=over';addr=addr';store}|_->filladdrlenorig(Layer{id=id';addr=addr';store=store';over=over'}))letoverlayaddrvalueover=letaddr,offset=rebaseaddrinincrid;Overlay{id=!id;over;addr;store=Store.singletonoffset(Chunk.of_exprvalue);}letwrite~addrvalue(dir:Expr.endianness)over=letvalue=matchdirwithLittleEndian->value|BigEndian->bswapvalueinmatchoverwith|Root|Symbol_|Layer_->overlayaddrvalueover|Overlay{id=id';addr=addr';store=store';over=over'}->(matchExpr.subaddraddr'with|Expr.Cstbv->letstore=Store.storebv(Chunk.of_exprvalue)store'inincrid;Overlay{id=!id;over=over';addr=addr';store}|_->overlayaddrvalue(Layer{id=id';addr=addr';store=store';over=over'}))letrecread~addrbytes(dir:Expr.endianness)memory=matchmemorywith|Root|Symbol_->Expr.loadbytesdiraddrmemory|Layer{id;addr=addr';store;over}|Overlay{id;addr=addr';store;over}->(matchExpr.subaddraddr'with|Expr.Cstbv->(letmissis=Chunk.of_expr(read~addr:(Expr.addzaddr'i)sExpr.LittleEndianover)inletbytes=Chunk.to_expr(Store.selectmissbvbytesstore)inmatchdirwithLittleEndian->bytes|BigEndian->bswapbytes)|_->(letbytes=Expr.loadbytesdiraddrmemoryinmatchmemorywith|Overlay_->raise_notrace(Writeback(bytes,Layer{id;addr=addr';store;over}))|_->bytes))letrecmergectt'=ift==t'thentelsematch(t,t')with|Overlay{over;addr;store;_},t'whenover==t'->incrid;letid=!idandstore=Store.map(funoffsetchunk->ifChunk.is_exportedchunkthenletvalue=Chunk.to_exprchunkinletsize=Expr.sizeofvalueinChunk.of_expr(Expr.itecvalue(read~addr:(Expr.addzaddroffset)(size/8)LittleEndianover))elseraise_notraceNon_mergeable)storeinOverlay{id;over;addr;store}|t,Overlay{over;_}whent==over->merge(Expr.lognotc)t't|(Overlay{over;addr;store;_},Overlay{over=over';addr=addr';store=store';_})whenExpr.is_equaladdraddr'&&over==over'->incrid;letid=!idandstore=Store.merge(funoffseto0o1->match(o0,o1)with|Somec0,Somec1->ifChunk.equalc0c1theno0elseSome(Chunk.of_expr(Expr.itec(Chunk.to_exprc0)(Chunk.to_exprc1)))|Somec0,None->letvalue=Chunk.to_exprc0inletsize=Expr.sizeofvalueinSome(Chunk.of_expr(Expr.itecvalue(read~addr:(Expr.addzaddroffset)(size/8)LittleEndianover)))|None,Somec1->letvalue=Chunk.to_exprc1inletsize=Expr.sizeofvalueinSome(Chunk.of_expr(Expr.itec(read~addr:(Expr.addzaddroffset)(size/8)LittleEndianover)value))|None,None->None)storestore'inOverlay{id;over;addr;store}|((Root|Symbol_|Layer_|Overlay_),(Root|Symbol_|Layer_|Overlay_))->raise_notraceNon_mergeableletread~addrbytesdirmemory=try(read~addrbytesdirmemory,memory)withWritebackr->rendmoduleBvTbl=Hashtbl.Make(structincludeExprletequal=is_equalend)moduleAxTbl=Hashtbl.Make(Memory)moduleBiTbl=Basic_types.BigInt.HtblmoduleStTbl=Basic_types.String.HtblmoduleS=Basic_types.String.MapmoduleI=Map.Make(structtypet=Z.tletcomparexy=-Z.comparexyend)moduleModel=structtypet=Bv.tBvTbl.t*charBiTbl.t*charBiTbl.tStTbl.tletempty()=(BvTbl.create0,BiTbl.create0,StTbl.create0)letmaybe_pp_charppfc=ifString_utils.is_char_printablecthenFormat.fprintfppf" (%c)"cletpp_variablesppfvarsvalues=ifS.is_emptyvars=falsethen(Format.pp_print_stringppf"# Variables";Format.pp_print_cutppf();S.iter(funnamelist->letlist=List.revlistinFormat.fprintfppf"%s : @[<hov>%a@]@ "name(Format.pp_print_list~pp_sep:Format.pp_print_space(funppfvar->matchBvTbl.findvaluesvarwith|exceptionNot_found->Format.pp_print_stringppf"--"|bv->Bitvector.pp_hex_or_binppfbv))list;matchlistwith|var::_::_whenExpr.sizeofvar=8->Format.pp_print_stringppf" [as ascii] ";List.iter(funvar->matchBvTbl.findvaluesvarwith|exceptionNot_found->Format.pp_print_stringppf"."|bv->Format.pp_print_charppf(Bitvector.to_charbv))list;Format.pp_print_spaceppf()|_->())vars)letpp_int_as_bvppfx=function|1->Format.fprintfppf"#b%d"x|4->Format.fprintfppf"#x%01x"x|8->Format.fprintfppf"#x%02x"x|12->Format.fprintfppf"#x%03x"x|16->Format.fprintfppf"#x%04x"x|20->Format.fprintfppf"#x%05x"x|24->Format.fprintfppf"#x%06x"x|28->Format.fprintfppf"#x%07x"x|32->Format.fprintfppf"#x%08x"x|64whenx>=0->Format.fprintfppf"#x%016x"x|sz->Format.fprintfppf"(_ bv%d %d)"xszletpp_bvppfvaluesize=trypp_int_as_bvppf(Z.to_intvalue)sizewithZ.Overflow->Format.fprintfppf"(_ bv%a %d)"Z.pp_printvaluesizeletpp_memoryppfmemoryaddr_space=ifBiTbl.lengthmemory=0thenFormat.pp_print_stringppf"-- empty memory --"else(Format.pp_print_stringppf"# Memory";Format.pp_print_cutppf();letimg=Kernel_functions.get_img()inletnoname=""inletsection_nameaddr=letaddress=Virtual_address.to_int(Virtual_address.of_bigintaddr)inmatchLoader_utils.find_section_by_address~addressimgwith|None->noname|Somesection->Loader.Section.namesectioninletpp_sectionppfname=ifname==nonamethenFormat.pp_print_stringppf"unamed section"elseFormat.fprintfppf"section %s"nameinletlast_section=ref"--"inI.iter(funaddrbyte->letname=section_nameaddrinifname<>!last_sectionthen(Format.fprintfppf"; %a@ "pp_sectionname;last_section:=name);pp_bvppfaddraddr_space;Format.fprintfppf" : %02x %a@ "(Char.codebyte)maybe_pp_charbyte)@@BiTbl.foldI.addmemoryI.empty)letpp_arrayppfnamearrayaddr_space=Format.pp_print_stringppf"# Array ";Format.pp_print_stringppfname;Format.pp_print_cutppf();I.iter(funaddrbyte->pp_bvppfaddraddr_space;Format.fprintfppf" : %02x %a@ "(Char.codebyte)maybe_pp_charbyte)@@BiTbl.foldI.addarrayI.emptyletppppfvarsaddr_space(values,memory,arrays)=ifS.is_emptyvars&&BiTbl.lengthmemory=0&&StTbl.lengtharrays=0thenFormat.fprintfppf"@[<h>--- Empty model ---@]"else(Format.fprintfppf"@[<v 0>--- Model ---@ ";pp_variablesppfvarsvalues;Format.pp_print_spaceppf();pp_memoryppfmemoryaddr_space;StTbl.iter(funnamearray->ifBiTbl.lengtharray<>0then(Format.pp_print_spaceppf();pp_arrayppfnamearrayaddr_space))arrays;Format.pp_close_boxppf())letreceval((vars,_,_)asm)=function|Expr.Cstbv->bv|e->(tryBvTbl.findvarsewithNot_found->letsize=Expr.sizeofeinletvalue=matchewith|Expr.Cst_->assertfalse|Expr.Var_->Bitvector.create(Z.of_int(Expr.hashe))size|Expr.Load{addr;len;dir;label;_}->eval_loadm(evalmaddr)lendirlabel|Expr.Unary{f;x;_}->Term.Bv.unaryf(evalmx)|Expr.Binary{f;x;y;_}->Term.Bv.binaryf(evalmx)(evalmy)|Expr.Ite{c;t;e;_}->ifBv.zero=evalmcthenevalmeelseevalmtinBvTbl.addvarsevalue;value)andeval_load((_,cache,arrays)ast)ptrlendir(memory:Memory.t)=matchmemorywith|Root->letindex=matchdirwith|LittleEndian->Bv.add_intptr|BigEndian->lethi=Bv.add_intptr(len-1)infuni->Bv.add_inthi(-i)inletbits=String.initlen(funi->tryBiTbl.findcache(Bv.value_of(indexi))withNot_found->'\x00')inBv.create(Z.of_bitsbits)(lenlsl3)|Symboln->letindex=matchdirwith|LittleEndian->Bv.add_intptr|BigEndian->lethi=Bv.add_intptr(len-1)infuni->Bv.add_inthi(-i)inletbits=String.initlen(funi->tryBiTbl.find(StTbl.findarraysn)(Bv.value_of(indexi))withNot_found->'\x00')inBv.create(Z.of_bitsbits)(lenlsl3)|Layer{addr;store;over;_}|Overlay{addr;store;over;_}->letaddr=evaltaddrinletsize=Bv.size_ofaddrinletoffset=Bv.subptraddrinletmissis=Chunk.of_expr(Expr.loadsExpr.LittleEndian(Expr.constant(Bv.addaddr(Bv.createisize)))over)inletbytes=Chunk.to_expr(Store.selectmissoffsetlenstore)inletbytes=matchdirwith|LittleEndian->bytes|BigEndian->Memory.bswapbytesinevaltbytesend