123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820(**************************************************************************)(* Copyright (c) 2005, Regents of the University of California *)(* All rights reserved. *)(* *)(* Author: Adam Chlipala *)(* you can redistribute it and/or modify it under the terms of the GNU *)(* Redistribution and use in source and binary forms, with or without *)(* modification, are permitted provided that the following conditions *)(* are met: *)(* *)(* - Redistributions of source code must retain the above copyright *)(* notice, this list of conditions and the following disclaimer. *)(* - Redistributions in binary form must reproduce the above copyright *)(* notice, this list of conditions and the following disclaimer in *)(* the documentation and/or other materials provided with the *)(* distribution. *)(* - Neither the name of the University of California, Berkeley nor *)(* the names of its contributors may be used to endorse or promote *)(* products derived from this software without specific prior *)(* written permission. *)(* *)(* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *)(* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT *)(* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS *)(* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE *)(* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, *)(* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, *)(* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; *)(* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER *)(* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT *)(* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN *)(* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE *)(* POSSIBILITY OF SUCH DAMAGE. *)(* *)(* *)(* Modified for BINSEC *)(* *)(**************************************************************************)(* Utility functions *)openBasic_types.IntegersopenX86Typesletbitsize_of_xmm_mm=functionXMM->128|MM->64letbytesize_of_xmm_mm=functionXMM->16|MM->8letbytesize_of_simd_size=function|S32->Size.Byte.create4|S64->Size.Byte.create8|S128->Size.Byte.create16letbitsize_of_simd_sizesimd_size=bytesize_of_simd_sizesimd_size|>Size.Byte.to_bitsizeletbytesize_of_szmode=function|`M8->Size.Byte.create1|`M16->Size.Byte.create2|`M32->Size.Byte.create4letbitsize_of_szmodemode=bytesize_of_szmodemode|>Size.Byte.to_bitsizeletbytesize_of_mode=function|`M16->Size.Byte.create2|`M32->Size.Byte.create4letbitsize_of_modemode=bytesize_of_modemode|>Size.Byte.to_bitsizeletbytesize_of_address_mode=function|A32->Size.Byte.create4|A16->Size.Byte.create2letbitsize_of_address_modemode=bytesize_of_address_modemode|>Size.Byte.to_bitsizeletreg8_to_int=function|AL->0|CL->1|DL->2|BL->3|AH->4|CH->5|DH->6|BH->7letreg8_to_string=function|AL->"al"|CL->"cl"|DL->"dl"|BL->"bl"|AH->"ah"|CH->"ch"|DH->"dh"|BH->"bh"letint_to_reg8=function|0->AL|1->CL|2->DL|3->BL|4->AH|5->CH|6->DH|7->BH|_->raise(Invalid_argument"int_to_reg8")let_reg16_to_int=function|AX->0|CX->1|DX->2|BX->3|SP->4|BP->5|SI->6|DI->7letreg16_to_reg32=function|AX->EAX|CX->ECX|DX->EDX|BX->EBX|SP->ESP|BP->EBP|SI->ESI|DI->EDIletreg16_to_string=function|AX->"ax"|CX->"cx"|DX->"dx"|BX->"bx"|SP->"sp"|BP->"bp"|SI->"si"|DI->"di"letint_to_reg16=function|0->AX|1->CX|2->DX|3->BX|4->SP|5->BP|6->SI|7->DI|_->raise(Invalid_argument"int_to_ret16")let_reg32_to_int=function|EAX->0|ECX->1|EDX->2|EBX->3|ESP->4|EBP->5|ESI->6|EDI->7letreg32_to_string=function|EAX->"eax"|ECX->"ecx"|EDX->"edx"|EBX->"ebx"|ESP->"esp"|EBP->"ebp"|ESI->"esi"|EDI->"edi"letreg32_to_string_8=function|EAX->"al"|ECX->"cl"|EDX->"dl"|EBX->"bl"|ESP->"ah"|EBP->"ch"|ESI->"dh"|EDI->"bh"letreg32_to_string_16=function|EAX->"ax"|ECX->"cx"|EDX->"dx"|EBX->"bx"|ESP->"sp"|EBP->"bp"|ESI->"si"|EDI->"di"letxmm_reg_to_mm_reg=function|XMM0->MM0|XMM1->MM1|XMM2->MM2|XMM3->MM3|XMM4->MM4|XMM5->MM5|XMM6->MM6|XMM7->MM7letxmm_reg_to_string=function|XMM0->"xmm0"|XMM1->"xmm1"|XMM2->"xmm2"|XMM3->"xmm3"|XMM4->"xmm4"|XMM5->"xmm5"|XMM6->"xmm6"|XMM7->"xmm7"letmm_reg_to_string=function|MM0->"mm0"|MM1->"mm1"|MM2->"mm2"|MM3->"mm3"|MM4->"mm4"|MM5->"mm5"|MM6->"mm6"|MM7->"mm7"letint_to_reg32=function|0->EAX|1->ECX|2->EDX|3->EBX|4->ESP|5->EBP|6->ESI|7->EDI|n->X86logger.debug"n = %d\n"n;raise(Invalid_argument"int_to_reg32\n")let_segment_reg_to_int=function|ES->0|CS->1|SS->2|DS->3|FS->4|GS->5letsegment_reg_to_string=function|ES->"es"|CS->"cs"|SS->"ss"|DS->"ds"|FS->"fs"|GS->"gs"letsegments=[FS;GS;CS;SS;DS;ES]letsegment_of_stringstring=matchString.lowercase_asciistringwith|"fs"->SomeX86Types.FS|"gs"->SomeX86Types.GS|"cs"->SomeX86Types.CS|"ss"->SomeX86Types.SS|"ds"->SomeX86Types.DS|"es"->SomeX86Types.ES|_->X86logger.info"Ignoring unknown segment %s"string;Noneletint_to_segment_reg=function|0->ES|1->CS|2->SS|3->DS|4->FS|5->GS|n->letmsg=Format.sprintf"int_to_segment_reg %d"ninraise(Invalid_argumentmsg)let_float_reg_to_int=function|ST0->0|ST1->1|ST2->2|ST3->3|ST4->4|ST5->5|ST6->6|ST7->7letfloat_reg_to_string=function|ST0->"st0"|ST1->"st1"|ST2->"st2"|ST3->"st3"|ST4->"st4"|ST5->"st5"|ST6->"st6"|ST7->"st7"letint_to_float_reg=function|0->ST0|1->ST1|2->ST2|3->ST3|4->ST4|5->ST5|6->ST6|7->ST7|_->raise(Invalid_argument"int_to_float_reg")let_mmx_reg_to_int=function|MM0->0|MM1->1|MM2->2|MM3->3|MM4->4|MM5->5|MM6->6|MM7->7letmmx_reg_to_string=function|MM0->"MM0"|MM1->"MM1"|MM2->"MM2"|MM3->"MM3"|MM4->"MM4"|MM5->"MM5"|MM6->"MM6"|MM7->"MM7"letint_to_mmx_reg=function|0->MM0|1->MM1|2->MM2|3->MM3|4->MM4|5->MM5|6->MM6|7->MM7|_->raise(Invalid_argument"int_to_mmx_reg")letint_to_xmm_reg=function|0->XMM0|1->XMM1|2->XMM2|3->XMM3|4->XMM4|5->XMM5|6->XMM6|7->XMM7|_->raise(Invalid_argument"int_to_mmx_reg")let_control_reg_to_int=functionCR0->0|CR2->2|CR3->3|CR4->4letcontrol_reg_to_string=function|CR0->"CR0"|CR2->"CR2"|CR3->"CR3"|CR4->"CR4"letint_to_control_reg=function|0->CR0|2->CR2|3->CR3|4->CR4|_->raise(Invalid_argument"int_to_control_reg")let_debug_reg_to_int=function|DR0->0|DR1->1|DR2->2|DR3->3|DR6->6|DR7->7letdebug_reg_to_string=function|DR0->"DR0"|DR1->"DR1"|DR2->"DR2"|DR3->"DR3"|DR6->"DR6"|DR7->"DR7"letint_to_debug_reg=function|0->DR0|1->DR1|2->DR2|3->DR3|6->DR6|7->DR7|_->raise(Invalid_argument"int_to_debug_reg")let_test_reg_to_int=function|TR3->3|TR4->4|TR5->5|TR6->6|TR7->7lettest_reg_to_string=function|TR3->"TR3"|TR4->"TR4"|TR5->"TR5"|TR6->"TR6"|TR7->"TR7"letint_to_test_reg=function|3->TR3|4->TR4|5->TR5|6->TR6|7->TR7|_->raise(Invalid_argument"int_to_test_reg")letflag_to_string=function|ID->"ID"|VIP->"VIP"|VIF->"VIF"|AC->"AC"|VM->"VM"|RF->"RF"|NT->"NT"|IOPL->"IOPL"|OF->"OF"|DF->"DF"|IF->"IF"|TF->"TF"|SF->"SF"|ZF->"ZF"|AF->"AF"|PF->"PF"|CF->"CF"letflag_to_offset=function(* following the order in the eflags register *)|ID->21|VIP->20|VIF->19|AC->18|VM->17|RF->16|NT->14|IOPL->12|OF->11|DF->10|IF->9|TF->8|SF->7|ZF->6|AF->4|PF->2|CF->0letget_flag_valueflageflag=letpos=flag_to_offsetflaginletmask=Int64.shift_leftInt64.oneposinletvalue=Int64.logandeflagmaskinInt64.shift_right_logicalvalueposletcc_to_stringcc=match(cc.truth_value,cc.condition)with|true,O->"o"|false,O->"no"|true,B->"b"|false,B->"ae"|true,Z->"z"|false,Z->"nz"|true,BE->"be"|false,BE->"a"|true,S->"s"|false,S->"ns"|true,P->"p"|false,P->"np"|true,L->"l"|false,L->"ge"|true,LE->"le"|false,LE->"g"letcondition_to_stringcondition=cc_to_string{truth_value=true;condition}letint_to_condition=function|0->O|2->B|4->Z|6->BE|8->S|10->P|12->L|14->LE|n->X86logger.debug"n = %d\n"n;raise(Invalid_argument"int_to_condition\n")letint_to_ccn=ifnmod2=0then{truth_value=true;condition=int_to_conditionn}else{truth_value=false;condition=int_to_condition(n-1)}let_sse_to_int=function|SseEQ->0|SseLT->1|SseLE->2|SseUNORD->3|SseNEQ->4|SseNLT->5|SseNLE->6|SseORD->7letsse_to_string=function|SseEQ->"eq"|SseLT->"lt"|SseLE->"le"|SseUNORD->"unord"|SseNEQ->"neq"|SseNLT->"nlt"|SseNLE->"nle"|SseORD->"ord"letint_to_sse=function|0->SseEQ|1->SseLT|2->SseLE|3->SseUNORD|4->SseNEQ|5->SseNLT|6->SseNLE|7->SseORD|_->raise(Invalid_argument"int_to_sse")letscale_to_size=function|Scale1->1|Scale2->2|Scale4->4|Scale8->8let_scale_to_int=function|Scale1->0|Scale2->1|Scale4->2|Scale8->3letscale_to_stringscale=string_of_int(scale_to_sizescale)letint_to_scale=function|0->Scale1|1->Scale2|2->Scale4|3->Scale8|_->raise(Invalid_argument"scale_from_int")letarith_op_to_string=function|Add->"add"|Adc->"adc"|And->"and"|Or->"or"|Xor->"xor"|Sub->"sub"|Sbb->"sbb"let_arith_op_to_int=function|Add->0|Or->1|Adc->2|Sbb->3|And->4|Sub->5|Xor->6letint_to_arith_op=function|0->Add|1->Or|2->Adc|3->Sbb|4->And|5->Sub|6->Xor|7->Sub|n->X86logger.debug"n = %d\n"n;raise(Invalid_argument"int_to_arith_op\n")letshift_op_to_string=functionShl->"shl"|Shr->"shr"|Sar->"sar"letrotate_op_to_string=function|Rol->"rol"|Ror->"ror"|Rcl->"rcl"|Rcr->"rcr"letshiftd_op_to_string=functionShld->"shld"|Shrd->"shrd"let_rotate_op_to_in=functionRol->0|Ror->1|Rcl->2|Rcr->3let_shift_op_to_int=functionShl->4|Shr->5|Sar->7letint_to_rotate_op=function|0->Rol|1->Ror|2->Rcl|3->Rcr|n->X86logger.debug"n = %d\n"n;raise(Invalid_argument"int_to_rotate_op\n")letint_to_shift_op=function|4->Shl|5->Shr|7->Sar|n->X86logger.debug"n = %d\n"n;raise(Invalid_argument"int_to_shift_op\n")typemodrm_byte={rm:int;modb:int;reg:int}letmask3=7letmask2=3letread_modrm_bytebyte=X86logger.debug~level:5"mod/rm byte : %x"byte;{rm=bytelandmask3;reg=(bytelsr3)landmask3;modb=(bytelsr6)landmask2;}letpeek_sparelr=let{reg;_}=read_modrm_byte@@Uint8.to_int@@Reader.Peek.u8lrinregletpp_modrmppfmodrm_byte=Format.fprintfppf"@[<h>rm : %d; modb : %d; reg : %d@]"modrm_byte.rmmodrm_byte.modbmodrm_byte.reg(*let read_modrm_byte bits =
let rm, bits = read_uint bits 3 in
let reg, bits = read_uint bits 3 in
let modb, bits = read_uint bits 2 in
{ rm; reg; modb; }, bits
*)typesib_byte={base:int;scale:int;index:int}letread_sib_bytebyte=X86logger.debug~level:5"sib byte : %x"byte;{base=bytelandmask3;index=(bytelsr3)landmask3;scale=(bytelsr6)landmask2;}letmk_address_64?(address_mode=A32)?(address_base=None)?(address_index=None)disp=Address{addrMode=address_mode;addrDisp=disp;addrBase=address_base;addrIndex=address_index;}letmk_address_32?address_mode?address_base?address_indexdisp=mk_address_64?address_mode?address_base?address_index(Int64.of_int32disp)letmk_address?address_mode?address_base?address_indexdisp=mk_address_64?address_mode?address_base?address_index(Int64.of_intdisp)letread_rm16_with_spareint_to_reglr=letbyte=Uint8.to_int@@Reader.Read.u8lrinletmodrm_byte=read_modrm_bytebytein(* X86logger.debug "modb = %d, rm = %d" modb rm; *)letget_base_index=function|0->(SomeEBX,Some(Scale1,ESI))|1->(SomeEBX,Some(Scale1,EDI))|2->(SomeEBP,Some(Scale1,ESI))|3->(SomeEBP,Some(Scale1,EDI))|4->(SomeESI,None)|5->(SomeEDI,None)|6->(SomeEBP,None)|7->(SomeEBX,None)|_->failwith"Unexpected ModR/M byte (rm > 7) !"inmatchmodrm_bytewith|{modb=0;rm=6;reg}->letdisp=Int16.to_int@@Reader.Read.i16lrin(mk_address~address_mode:A16disp,reg)|{modb;rm;reg}->(letaddress_base,address_index=get_base_indexrminmatchmodbwith|0->letdisp=0in(mk_address~address_mode:A16disp~address_base~address_index,reg)|1->letdisp=Int8.to_int@@Reader.Read.i8lrin(* let disp, bits = read_uint32_extend bits 8 in *)(mk_address~address_mode:A16disp~address_base~address_index,reg)|2->letbase=int_to_reg32rminletdisp=Int16.to_int@@Reader.Read.i16lrin(mk_address~address_mode:A16disp~address_base:(Somebase)~address_index,reg)|3->(Reg(int_to_regrm),reg)|_->failwith"Unexpected ModR/M byte (mod > 3) !")letread_rm32_with_spareint_to_reglr=letbyte=Uint8.to_int@@Reader.Read.u8lrinletmodrm_byte=read_modrm_bytebyteinX86logger.debug~level:4"%a"pp_modrmmodrm_byte;matchmodrm_bytewith|{modb=0;rm=5;reg}->letdisp=Reader.Read.i32lrin(mk_address_32disp,reg)|{modb=3;rm;reg}->(Reg(int_to_regrm),reg)|{modb;rm=4;reg}->letbyte=Uint8.to_int@@Reader.Read.u8lrinletsib_byte=read_sib_bytebyteinletdisp=matchmodbwith|0->Int64.zero|1->Int8.to_int64(Reader.Read.i8lr)(* read_uint32_extend bits 8 *)|2->Int64.of_int32(Reader.Read.i32lr)|3->failwith"Impossible: matched above."|_->letmsg=Format.sprintf"Impossible: 2-bit value for modb : %d"modbinfailwithmsginletscale=int_to_scalesib_byte.scaleinletaddress_index=matchint_to_reg32sib_byte.indexwith|ESP->None|index->Some(scale,index)inifsib_byte.base=5&&modb=0then(* TODO : modb = 1, modb = 2 *)letdisp=Reader.Read.i32lrin(* TODO : size := size + size + 4 *)(mk_address_32disp~address_index,reg)elseletbase=int_to_reg32sib_byte.baseinletaddr=mk_address_64~address_mode:A32disp~address_base:(Somebase)~address_indexin(addr,reg)|{modb=0;rm;reg}->letbase=int_to_reg32rmin(mk_address~address_mode:A320~address_base:(Somebase),reg)|{modb=1;rm;reg}->letbase=int_to_reg32rminletdisp=Int8.to_int@@Reader.Read.i8lrin(mk_address~address_mode:A32disp~address_base:(Somebase),reg)|{modb=2;rm;reg}->letbase=int_to_reg32rminletdisp=Reader.Read.i32lrin(mk_address_32~address_mode:A32disp~address_base:(Somebase),reg)|_->failwith"Unexpected ModR/M byte"letread_modrmaddress_modelr=letread_rm=matchaddress_modewith|A32->read_rm32_with_spare|A16->read_rm16_with_spareinread_rmint_to_reg32lrletread_modrm_xmmaddress_modelr=letread_rm=matchaddress_modewith|A32->read_rm32_with_spare|A16->read_rm16_with_spareinread_rmint_to_xmm_reglrletread_rm8_with_spare=read_rm32_with_spareint_to_reg8letread_rm16_with_spare=read_rm32_with_spareint_to_reg16letstring_of_register_restrictnamelowhigh=matchnamewith|"eax"|"ebx"|"ecx"|"edx"->(matchhigh-low+1with|32->name|16->String_utils.lchop1name|8->iflow=0thenString.make1(String.getname1)^"l"elseString.make1(String.getname1)^"h"|_->name(* Does not resolve the name so return it as is *))|_->nameletreg_to_extract(name:string):string*int*int=matchnamewith|"eax"->("eax",0,31)|"ax"->("eax",0,15)|"al"->("eax",0,7)|"ah"->("eax",8,15)|"ebx"->("ebx",0,31)|"bx"->("ebx",0,15)|"bl"->("ebx",0,7)|"bh"->("ebx",8,15)|"ecx"->("ecx",0,31)|"cx"->("ecx",0,15)|"cl"->("ecx",0,7)|"ch"->("ecx",8,15)|"edx"->("edx",0,31)|"dx"->("edx",0,15)|"dl"->("edx",0,7)|"dh"->("edx",8,15)|"ebp"->("ebp",0,31)|"bp"->("ebp",0,15)|"bpl"->("ebx",0,7)|"esi"->("esi",0,31)|"si"->("esi",0,15)|"sil"->("esi",0,7)|"esp"->("esp",0,31)|"sp"->("esp",0,15)|"spl"->("esp",0,8)|"edi"->("edi",0,31)(* Added for genericity *)|"CF"->("CF",0,0)|"DF"->("DF",0,0)|"ZF"->("ZF",0,0)|"OF"->("OF",0,0)|"SF"->("SF",0,0)|"AF"->("AF",0,0)|"PF"->("PF",0,0)|_->failwith("reg_to_extract unknown register: "^name)letswitch_default_data_mode=function`M16->`M32|`M32->`M16letswitch_address_mode=functionA16->A32|A32->A16