?? decode.c
字號:
/* ----------------------------------------------------------------------------- * decode.c * * Copyright (c) 2005, 2006, Vivek Mohan <vivek@sig9.com> * All rights reserved. See LICENSE * ----------------------------------------------------------------------------- */#include "types.h"#include "itab.h"#include "input.h"#include "decode.h"#ifndef __UD_STANDALONE__# include <string.h>#endif /* __UD_STANDALONE__ *//* The max number of prefixes to an instruction */#define MAX_PREFIXES 15static struct ud_itab_entry ie_invalid = { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none };static struct ud_itab_entry ie_pause = { UD_Ipause, O_NONE, O_NONE, O_NONE, P_none };static struct ud_itab_entry ie_nop = { UD_Inop, O_NONE, O_NONE, O_NONE, P_none };/* Looks up mnemonic code in the mnemonic string table * Returns NULL if the mnemonic code is invalid */const char * ud_lookup_mnemonic( enum ud_mnemonic_code c ){ if ( c < UD_Id3vil ) return ud_mnemonics_str[ c ]; return NULL;}/* Extracts instruction prefixes. */static int get_prefixes( struct ud* u ){ unsigned int have_pfx = 1; unsigned int i; uint8_t curr; /* if in error state, bail out */ if ( u->error ) return -1; /* keep going as long as there are prefixes available */ for ( i = 0; have_pfx ; ++i ) { /* Get next byte. */ inp_next(u); if ( u->error ) return -1; curr = inp_curr( u ); /* rex prefixes in 64bit mode */ if ( u->dis_mode == 64 && ( curr & 0xF0 ) == 0x40 ) { u->pfx_rex = curr; } else { switch ( curr ) { case 0x2E : u->pfx_seg = UD_R_CS; u->pfx_rex = 0; break; case 0x36 : u->pfx_seg = UD_R_SS; u->pfx_rex = 0; break; case 0x3E : u->pfx_seg = UD_R_DS; u->pfx_rex = 0; break; case 0x26 : u->pfx_seg = UD_R_ES; u->pfx_rex = 0; break; case 0x64 : u->pfx_seg = UD_R_FS; u->pfx_rex = 0; break; case 0x65 : u->pfx_seg = UD_R_GS; u->pfx_rex = 0; break; case 0x67 : /* adress-size override prefix */ u->pfx_adr = 0x67; u->pfx_rex = 0; break; case 0xF0 : u->pfx_lock = 0xF0; u->pfx_rex = 0; break; case 0x66: /* the 0x66 sse prefix is only effective if no other sse prefix * has already been specified. */ if ( !u->pfx_insn ) u->pfx_insn = 0x66; u->pfx_opr = 0x66; u->pfx_rex = 0; break; case 0xF2: u->pfx_insn = 0xF2; u->pfx_repne = 0xF2; u->pfx_rex = 0; break; case 0xF3: u->pfx_insn = 0xF3; u->pfx_rep = 0xF3; u->pfx_repe = 0xF3; u->pfx_rex = 0; break; default : /* No more prefixes */ have_pfx = 0; break; } } /* check if we reached max instruction length */ if ( i + 1 == MAX_INSN_LENGTH ) { u->error = 1; break; } } /* return status */ if ( u->error ) return -1; /* rewind back one byte in stream, since the above loop * stops with a non-prefix byte. */ inp_back(u); /* speculatively determine the effective operand mode, * based on the prefixes and the current disassembly * mode. This may be inaccurate, but useful for mode * dependent decoding. */ if ( u->dis_mode == 64 ) { u->opr_mode = REX_W( u->pfx_rex ) ? 64 : ( ( u->pfx_opr ) ? 16 : 32 ) ; u->adr_mode = ( u->pfx_adr ) ? 32 : 64; } else if ( u->dis_mode == 32 ) { u->opr_mode = ( u->pfx_opr ) ? 16 : 32; u->adr_mode = ( u->pfx_adr ) ? 16 : 32; } else if ( u->dis_mode == 16 ) { u->opr_mode = ( u->pfx_opr ) ? 32 : 16; u->adr_mode = ( u->pfx_adr ) ? 32 : 16; } return 0;}/* Searches the instruction tables for the right entry. */static int search_itab( struct ud * u ){ struct ud_itab_entry * e = NULL; enum ud_itab_index table; uint8_t peek; uint8_t did_peek = 0; uint8_t curr; uint8_t index; /* if in state of error, return */ if ( u->error ) return -1; /* get first byte of opcode. */ inp_next(u); if ( u->error ) return -1; curr = inp_curr(u); /* resolve xchg, nop, pause crazyness */ if ( 0x90 == curr ) { if ( !( u->dis_mode == 64 && REX_B( u->pfx_rex ) ) ) { if ( u->pfx_rep ) { u->pfx_rep = 0; e = & ie_pause; } else { e = & ie_nop; } goto found_entry; } } /* get top-level table */ if ( 0x0F == curr ) { table = ITAB__0F; curr = inp_next(u); if ( u->error ) return -1; /* 2byte opcodes can be modified by 0x66, F3, and F2 prefixes */ if ( 0x66 == u->pfx_insn ) { if ( ud_itab_list[ ITAB__PFX_SSE66__0F ][ curr ].mnemonic != UD_Iinvalid ) { table = ITAB__PFX_SSE66__0F; u->pfx_opr = 0; } } else if ( 0xF2 == u->pfx_insn ) { if ( ud_itab_list[ ITAB__PFX_SSEF2__0F ][ curr ].mnemonic != UD_Iinvalid ) { table = ITAB__PFX_SSEF2__0F; u->pfx_repne = 0; } } else if ( 0xF3 == u->pfx_insn ) { if ( ud_itab_list[ ITAB__PFX_SSEF3__0F ][ curr ].mnemonic != UD_Iinvalid ) { table = ITAB__PFX_SSEF3__0F; u->pfx_repe = 0; u->pfx_rep = 0; } } /* pick an instruction from the 1byte table */ } else { table = ITAB__1BYTE; } index = curr;search: e = & ud_itab_list[ table ][ index ]; /* if mnemonic constant is a standard instruction constant * our search is over. */ if ( e->mnemonic < UD_Id3vil ) { if ( e->mnemonic == UD_Iinvalid ) { if ( did_peek ) { inp_next( u ); if ( u->error ) return -1; } goto found_entry; } goto found_entry; } table = e->prefix; switch ( e->mnemonic ) { case UD_Igrp_reg: peek = inp_peek( u ); did_peek = 1; index = MODRM_REG( peek ); break; case UD_Igrp_mod: peek = inp_peek( u ); did_peek = 1; index = MODRM_MOD( peek ); if ( index == 3 ) index = ITAB__MOD_INDX__11; else index = ITAB__MOD_INDX__NOT_11; break; case UD_Igrp_rm: curr = inp_next( u ); did_peek = 0; if ( u->error ) return -1; index = MODRM_RM( curr ); break; case UD_Igrp_x87: curr = inp_next( u ); did_peek = 0; if ( u->error ) return -1; index = curr - 0xC0; break; case UD_Igrp_3byte: curr = inp_next( u ); did_peek = 0; if (u->error) return -1; index = curr; break; case UD_Igrp_osize: if ( u->opr_mode == 64 ) index = ITAB__MODE_INDX__64; else if ( u->opr_mode == 32 ) index = ITAB__MODE_INDX__32; else index = ITAB__MODE_INDX__16; break; case UD_Igrp_asize: if ( u->adr_mode == 64 ) index = ITAB__MODE_INDX__64; else if ( u->adr_mode == 32 ) index = ITAB__MODE_INDX__32; else index = ITAB__MODE_INDX__16; break; case UD_Igrp_mode: if ( u->dis_mode == 64 ) index = ITAB__MODE_INDX__64; else if ( u->dis_mode == 32 ) index = ITAB__MODE_INDX__32; else index = ITAB__MODE_INDX__16; break; case UD_Igrp_vendor: if ( u->vendor == UD_VENDOR_INTEL ) index = ITAB__VENDOR_INDX__INTEL; else if ( u->vendor == UD_VENDOR_AMD ) index = ITAB__VENDOR_INDX__AMD; else if ( u->vendor == UD_VENDOR_ANY ) index = ITAB__VENDOR_INDX__ANY; else return -1; break; case UD_Id3vil: return -1; break; default: return -1; break; } goto search;found_entry: u->itab_entry = e; u->mnemonic = u->itab_entry->mnemonic; return 0;}static unsigned int resolve_operand_size( const struct ud * u, unsigned int s ){ switch ( s ) { case SZ_V: return ( u->opr_mode ); case SZ_Z: return ( u->opr_mode == 16 ) ? 16 : 32; case SZ_P: return ( u->opr_mode == 16 ) ? SZ_WP : SZ_DP; case SZ_MDQ: return ( u->opr_mode == 16 ) ? 32 : u->opr_mode; case SZ_RDQ: return ( u->dis_mode == 64 ) ? 64 : 32; default: return s; }}static int resolve_mnemonic( struct ud* u ){ /* far/near flags */ u->br_far = 0; u->br_near = 0; /* readjust operand sizes for call/jmp instrcutions */ if ( u->mnemonic == UD_Icall || u->mnemonic == UD_Ijmp ) { /* WP: 16bit pointer */ if ( u->operand[ 0 ].size == SZ_WP ) { u->operand[ 0 ].size = 16; u->br_far = 1; u->br_near= 0; /* DP: 32bit pointer */ } else if ( u->operand[ 0 ].size == SZ_DP ) { u->operand[ 0 ].size = 32; u->br_far = 1; u->br_near= 0; } else { u->br_far = 0; u->br_near= 1; } /* resolve 3dnow weirdness. */ } else if ( u->mnemonic == UD_I3dnow ) { u->mnemonic = ud_itab_list[ ITAB__3DNOW ][ inp_curr( u ) ].mnemonic; } /* SWAPGS is only valid in 64bits mode */ if ( u->mnemonic == UD_Iswapgs && u->dis_mode != 64 ) { u->error = 1; return -1; } return 0;}/* ----------------------------------------------------------------------------- * decode_a()- Decodes operands of the type seg:offset * ----------------------------------------------------------------------------- */
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -