123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222(**************************************************************************)(* 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). *)(* *)(**************************************************************************)moduleKey=Virtual_addressmoduleValue=structtypet=Instruction.tlethash(i:t)=Virtual_address.hashi.Instruction.addressletequali1i2=i1=i2endmoduletypeS=sigincludeCfg.Svalordered_iter_vertex:compare:(vertex->vertex->int)->(vertex->unit)->t->unitvaliter_vertex_by_address:(vertex->unit)->t->unitvaloutput_graph:out_channel->t->entry:vertex->Virtual_address.tlist->unitvaldump:filename:string->t->unitendmoduleMake(H:Hashtbl.HashedType)=structmoduleG=Cfg.Make(Key)(Value)(H)includeGtypeblock={leader:V.t;block:V.tlist;succs:V.tlist;preds:V.tlist;}moduleD=Graph.Imperative.Digraph.ConcreteBidirectional(structtypet=blockletcompareb1b2=V.compareb1.leaderb2.leaderlethashb=V.hashb.leaderletequalb1b2=V.equalb1.leaderb2.leaderend)moduleL=Graph.Leaderlist.Make(G)moduleH=Hashtbl.Make(V)letget_predtv=matchpredtvwith[v]->Somev|_->Noneletget_succtv=matchsucctvwith[v]->Somev|_->Noneletreccompare_preds_succsgvpredsucc=match(pred,succ)with|None,None->assertfalse|Some_,None->-1|None,Some_->1|Somep,Somes->ifV.equalvpthen-1elseifV.equalvsthen1elsecompare_preds_succsgv(get_predgp)(get_succgs)letcompare_vertexgv1v2=ifG.V.equalv1v2then0elsecompare_preds_succsgv1(get_predgv2)(get_succgv2)letrecdifflst1lst2acc=match(lst1,lst2)with|ls,[]->List.rev_appendlsacc|[],_->acc|a1::ls1,a2::ls2->ifG.V.comparea1a2<0thendiffls1lst2(a1::acc)elseifG.V.comparea1a2>0thendifflst1ls2accelsediffls1ls2accletdifflst1lst2=List.rev(difflst1lst2[])letbuild_blockgblock=letsuccs,preds=List.fold_left(fun(succs,preds)v->(List.fold_left(funle->e::l)succs(succgv),List.fold_left(funle->e::l)preds(predgv)))([],[])blockinletblock=List.sort_uniqV.compareblockinletsuccs=diff(List.sort_uniqV.comparesuccs)blockinletpreds=diff(List.sort_uniqV.comparepreds)blockinletblock=List.sort_uniq(compare_vertexg)blockin{leader=List.hdblock;block;succs;preds}letbuild_block_graphcfgentry=letblocks=List.map(build_blockcfg)(L.leader_listscfgentry)inlethtbl=H.create17inList.iter(funb->List.iter(funv->H.addhtblvb)b.block)blocks;lett=D.create()inList.iter(funblock->letvertex=D.V.createblockinD.add_vertextvertex;List.iter(funsucc->D.add_edgetvertex(H.findhtblsucc))block.succs;List.iter(funpred->D.add_edget(H.findhtblpred)vertex)block.preds)blocks;tlethtml_blockcalleesblock=letopenFormatinletalign="align=\"left\""inletborder="border=\"1\""inletopenColorsinletcolor1=asprintf"bgcolor=\"%a\""ppFlatUI.greenseainletcolor2=asprintf"bgcolor=\"%a\""ppFlatUI.silverinletpp_mnemonicppfvert=matchV.instvertwith|None->()|Someinst->leta=Instruction.addressinstinletm=Instruction.mnemonicinstinifList.memacalleesthenfprintfppf"<font color=\"%a\">%a</font>"ppFlatUI.alizarinMnemonic.ppmelseMnemonic.ppppfminblock.block|>List.map(funvert->asprintf"<tr><td %s %s>%a</td><td %s %s %s>%a</td></tr>"bordercolor1Virtual_address.pp(V.addrvert)bordercolor2alignpp_mnemonicvert)|>String.concat"\n"|>sprintf"<table border=\"0\" cellspacing=\"0\">\n%s\n</table>"letoutput_graphcg~entryca=letg=build_block_graphgentryinletmoduleDot=structincludeGraph.Graphviz.Dot(structincludeDletgraph_attributes_=[]letdefault_vertex_attributes_=[`Shape`Plaintext]letvertex_nameb=Printf.sprintf"%i"(Hashtbl.hashb)letvertex_attributesb=[`HtmlLabel(html_blockcab)]letget_subgraph_=Noneletdefault_edge_attributes_=[]letedge_attributes_=[`Minlen1]end)endinDot.output_graphcgletdump_ococg=letmoduleDot=Graph.Graphviz.Dot(structincludeGletgraph_attributes_=[]letdefault_vertex_attributes_=[]letvertex_namev=Format.asprintf"\"%a %a\""Virtual_address.pp(V.addrv)(funppfv->letopenFormatinmatchV.instvwith|None->pp_print_stringppf""|Somei->fprintfppf"%a"Mnemonic.pp(Instruction.mnemonici))vletvertex_attributes_=[]letget_subgraph_=Noneletdefault_edge_attributes_=[]letedge_attributes_=[]end)inDot.output_graphocgletdump~filenameg=letoc=open_out_binfilenameindump_ococg;close_outocletordered_iter_vertex~compare(f:vertex->unit)g=(* It is way better to use arrays (and even lists) than trees *)letdummy_v=G.V.of_addr(Virtual_address.create0)inleta=Array.make(G.nb_vertexg)dummy_vinleti=ref0initer_vertex(funv->a.(!i)<-v;incri)g;Array.sortcomparea;Array.iterfaletiter_vertex_by_address=ordered_iter_vertex~compare:G.V.compareendmoduleS=structtypet=stringlethashs=Hashtbl.hashsletequals1s2=s1=s2endmoduleF=Make(S)includeF