123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191(**************************************************************************)(* 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). *)(* *)(**************************************************************************)openBasic_types.IntegersopenFormatopenDisasm_options(* Disasembly worklists works on Caddresses *)moduleW=structincludeWorklist.Make(Virtual_address)letadd_listwll=List.fold_left(funwla->addawl)wllletof_list=add_listemptyletadd_setwls=Virtual_address.Set.foldaddswlletadd_filtered_setpwls=Virtual_address.Set.fold(funvwl->ifpvthenaddvwlelsewl)swlletof_sets=add_setemptysletof_filtered_setps=add_filtered_setpemptysletsingletonv=addvemptyletppppfwl=fprintfppf"@[<hov 0>{%a}@]"(funppfwl->iter(funa->fprintfppf"%a; "Virtual_address.ppa)wl)wlendletcompute_next_addresscurrent_instruction=letsize=Instruction.sizecurrent_instructioninifSize.Byte.is_zerosizethenNoneelseSome(Virtual_address.add_int(size:>int)(Instruction.addresscurrent_instruction))letdecode_at_addressdecodereaderaddress=letinstr=decodereaderaddressinifInstruction.is_decodedinstrthen(instr,compute_next_addressinstr)elseletdba_block=Dba.Instr.stop(SomeDba.KO)|>Dhunk.singletonin(Instruction.set_dba_blockinstrdba_block,None)moduleM=Hashtbl.Make(structtypet=Machine.tletequal=(=)lethash=Hashtbl.hashend)letdecoder_of_machine()=letisa=Kernel_options.Machine.get()intryDecoder.getisawithNot_found->(matchisawith|Unknown->failwith"Machine ISA set to unknown. Aborting. Did you forget to set an -isa \
switch on the command line ?"|_->letmsg=Format.asprintf"missing ISA %a"Machine.ppisainErrors.not_yet_implementedmsg)letdecode_fromreader(at:Virtual_address.t)=letdecoder=decoder_of_machine()indecode_at_addressdecoderreaderatletdecode?(img=Kernel_functions.get_img())(vaddress:Virtual_address.t)=decode_from(Reader.create~offset:(+)~get:(funimgpos->Uint8.to_char(Loader.read_addressimg(Virtual_address.add_intposvaddress)))~endianness:(Machine.ISA.endianness(Loader.Img.archimg))~start:0~stop:max_intimg)vaddressletdecode_binstream?(base=Virtual_address.zero)bs=tryletdecoder=decoder_of_machine()inletreader=Reader.of_binstream~endianness:(Kernel_options.Machine.endianness())bsindecode_at_addressdecoderreaderbasewithNot_found->Logger.error"@[<v 0>Could not decode opcode %a.@,\
The provided hexadecimal stream does not contain a recognized opcode.@,\
Check that you selected the correct ISA.@,\
Or maybe your input is too short or does not use the correct \
endianness.@]"Binstream.ppbs;exit2moduleSuccessors=structopenInstructionletrecursiveinstr=Logger.debug~level:5"@[<v 0>Computing recursive successors for block@ %a@]"Dhunk.ppinstr.dba_block;Dhunk.outer_jumpsinstr.dba_blockletlinearinstr=assert(not(Size.Byte.is_zeroinstr.size));lethwa=Virtual_address.add_int(instr.size:>int)instr.addressinVirtual_address.Set.singletonhwaletextended_linearinstr=letsuccs1=recursiveinstrinletsuccs2=linearinstrinVirtual_address.Set.unionsuccs1succs2letlinear_bytewiseinstr=letnext_byte_hwa=Virtual_address.succinstr.addressinVirtual_address.Set.addnext_byte_hwa(linearinstr)endmoduletypeIterable=sigvalsuccessors:Instruction.t->Virtual_address.Set.tendmoduleMake(I:Iterable)=structletfoldstep_funprogramworklist=letrecloopprogramworklist=ifW.is_emptyworklistthenprogramelseletaddress,addresses=W.popworklistinletp,wl=tryletinstr,_=decodeaddressin(* FIXME *)letsuccs=I.successorsinstrinstep_funprogramaddressesinstrsuccswithInvalid_argumentmsg->Disasm_options.Logger.warning"%s"msg;(program,addresses)inlooppwlinloopprogramworklistletiterstep_funworklist=letstep_fun'()wlinstrsuccs=((),step_funwlinstrsuccs)infoldstep_fun'()worklistend(* Iterators *)letfoldstep_funprogramworklist=letrecloopprogramworklist=ifW.is_emptyworklistthenprogramelseletaddress,addresses=W.popworklistinletinstr,_=decodeaddressin(* FIXME *)letfsuccs=matchDisassembly_mode.get()with|Linear->Successors.linear|Linear_byte_wise->Successors.linear_bytewise|Recursive->Successors.recursive|Extended_linear->Successors.extended_linearinletp,wl=step_funprogramaddressesinstr(fsuccsinstr)inlooppwlinloopprogramworklistletiterstep_funworklist=letstep_fun'()wlinstrsuccs=((),step_funwlinstrsuccs)infoldstep_fun'()worklist(* End iterators *)