⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 decode.c

📁 Ksplice is practical technology for updating the Linux kernel without rebooting. It enables you to a
💻 C
📖 第 1 页 / 共 3 页
字号:
/* ----------------------------------------------------------------------------- * 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 + -