?? x86dis.cc
字號:
/* * HT Editor * x86dis.cc * * Copyright (C) 1999-2002 Stefan Weyergraf * Copyright (C) 2005-2008 Sebastian Biallas (sb@biallas.net) * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */#include <cstdio>#include <cstring>#include "htdebug.h"#include "stream.h"#include "snprintf.h"#include "strtools.h"#include "tools.h"#include "vxd.h"#include "x86dis.h"#define mkscale mkmod#define mkbase mkrm#define rexw(rex) ((rex)&0x08)#define rexr(rex) ((rex)&0x04)#define rexx(rex) ((rex)&0x02)#define rexb(rex) ((rex)&0x01)#define drexdest(drex) ((drex)>>4)#define oc0(drex) (!!((drex)&8))#define vexw(vex) (!!((vex)&0x80))#define vexr(vex) (!((vex)&0x80))#define vexx(vex) (!((vex)&0x40))#define vexb(vex) (!((vex)&0x20))#define vexl(vex) (!!((vex)&0x04))#define vexmmmm(vex) ((vex)&0xf)#define vexvvvv(vex) (((~(vex))>>3)&0xf)#define vexpp(vex) ((vex)&0x3)static int modrm16_1[8] = { X86_REG_BX, X86_REG_BX, X86_REG_BP, X86_REG_BP, X86_REG_SI, X86_REG_DI, X86_REG_BP, X86_REG_BX};static int modrm16_2[8] = { X86_REG_SI, X86_REG_DI, X86_REG_SI, X86_REG_DI, X86_REG_NO, X86_REG_NO, X86_REG_NO, X86_REG_NO};static int sibscale[4] = {1, 2, 4, 8};/* * CLASS x86dis */x86dis::x86dis(X86OpSize aOpsize, X86AddrSize aAddrsize){ opsize = aOpsize; addrsize = aAddrsize; insn.invalid = true; x86_insns = &x86_32_insns;}void x86dis::checkInfo(x86opc_insn *xinsn){}dis_insn *x86dis::decode(byte *code, int Maxlen, CPU_ADDR Addr){ ocodep = code; codep = ocodep; maxlen = Maxlen; addr = Addr; modrm = -1; sib = -1; drex = -1; special_imm = -1; have_disp = false; memset(&insn, 0, sizeof insn); insn.invalid = false; insn.eopsize = opsize; insn.eaddrsize = addrsize; prefixes(); fixdisp = false; insn.opcode = c; decode_insn(&(*x86_insns)[insn.opcode]); if (insn.invalid) { insn.name = "db"; insn.size = 1; insn.op[0].type = X86_OPTYPE_IMM; insn.op[0].size = 1; insn.op[0].imm = *code; insn.opsizeprefix = X86_PREFIX_NO; insn.lockprefix = X86_PREFIX_NO; insn.repprefix = X86_PREFIX_NO; insn.segprefix = X86_PREFIX_NO; insn.rexprefix = 0; for (int i = 1; i < 5; i++) insn.op[i].type = X86_OPTYPE_EMPTY; } else { insn.size = codep - ocodep; if (fixdisp) { // ip-relativ addressing in PM64 for (int i = 0; i < 2; i++) { if (insn.op[i].type == X86_OPTYPE_MEM && insn.op[i].mem.hasdisp) { insn.op[i].mem.disp += getoffset() + insn.size; } } } } return &insn;}uint x86dis::mkmod(uint modrm){ return modrm>>6 & 0x03;}uint x86dis::mkreg(uint modrm){ return (modrm>>3 & 0x07) | !!rexr(insn.rexprefix) << 3;}uint x86dis::mkindex(uint sib){ return (sib>>3 & 0x07) | !!rexx(insn.rexprefix) << 3; }uint x86dis::mkrm(uint modrm){ return (modrm & 0x07) | !!rexb(insn.rexprefix) << 3; }static bool is_xmm_op(x86dis_insn *insn, char size){ if (insn->opsizeprefix == X86_PREFIX_OPSIZE && (size == SIZE_U || size == SIZE_Z)) { return true; } else { return false; }}void x86dis::decode_modrm(x86_insn_op *op, char size, bool allow_reg, bool allow_mem, bool mmx, bool xmm, bool ymm){ int modrm = getmodrm(); getdisp(); int mod = mkmod(modrm); int rm = mkrm(modrm); if (mod == 3) { /* reg */ if (!allow_reg) { invalidate(); return; } if (xmm || (mmx && is_xmm_op(&insn, size))) { op->type = X86_OPTYPE_XMM; op->xmm = rm; } else if (mmx) { op->type = X86_OPTYPE_MMX; op->mmx = rm; } else if (ymm) { op->type = X86_OPTYPE_YMM; op->xmm = rm; } else { op->type = X86_OPTYPE_REG; op->reg = rm; } op->size = esizeop(size); } else { /* mem */ if (!allow_mem) { invalidate(); return; } op->mem.addrsize = insn.eaddrsize; op->type = X86_OPTYPE_MEM; op->size = esizeop(size); op->mem.floatptr = isfloat(size); op->mem.addrptr = isaddr(size); if (insn.eaddrsize == X86_ADDRSIZE16) { if (mod == 0 && rm == 6) { op->mem.hasdisp = true; op->mem.disp = disp; op->mem.base = X86_REG_NO; op->mem.index = X86_REG_NO; op->mem.scale = 0; } else { op->mem.base = modrm16_1[rm]; op->mem.index = modrm16_2[rm]; op->mem.scale = 1; switch (mod) { case 0: op->mem.hasdisp = false; op->mem.disp = 0; break; case 1: op->mem.hasdisp = true; op->mem.disp = sint64(sint8(disp)); break; case 2: op->mem.hasdisp = true; op->mem.disp = sint64(sint16(disp)); break; } } } else { if (mod == 0 && rm == 5) { op->mem.hasdisp = true; op->mem.disp = disp; op->mem.base = X86_REG_NO; op->mem.index = X86_REG_NO; op->mem.scale = 0; } else if (rm == 4) { decode_sib(op, mod); } else { op->mem.base = rm; op->mem.index = X86_REG_NO; op->mem.scale = 1; switch (mod) { case 0: op->mem.hasdisp = false; op->mem.disp = 0; break; case 1: op->mem.hasdisp = true; op->mem.disp = sint64(sint8(disp)); break; case 2: op->mem.hasdisp = true; op->mem.disp = sint64(sint32(disp)); break; } } } }}void x86dis::decode_sib(x86_insn_op *op, int mod){ int sib = getsib(); int scale = mkscale(sib); int index = mkindex(sib); int base = mkbase(sib); int sdisp = mod; if ((base & 0x7) == 5 && mod == 0) { base = X86_REG_NO; sdisp = 2; } if (index == 4) { index = X86_REG_NO; } op->mem.base = base; op->mem.index = index; op->mem.scale = sibscale[scale]; switch (sdisp) { case 0: op->mem.hasdisp = false; op->mem.disp = 0; break; case 1: op->mem.hasdisp = true; op->mem.disp = sint64(sint8(disp)); break; case 2: op->mem.hasdisp = true; op->mem.disp = sint64(sint32(disp)); break; }}void x86dis::decode_vex_insn(x86opc_vex_insn *xinsn){ if (xinsn) { byte vex = (insn.vexprefix.w << 7) | (insn.vexprefix.l << 6) | (insn.vexprefix.mmmm << 4) | insn.vexprefix.pp; while (!xinsn->name && xinsn->op[0] == SPECIAL_TYPE_GROUP) { if (xinsn->vex == vex) { getdisp(); int m = mkreg(getmodrm()) & 0x7; xinsn = &x86_group_vex_insns[xinsn->op[1]][m]; if (!xinsn->name) { invalidate(); } else { insn.name = xinsn->name; for (int i = 0; i < 5; i++) { decode_op(&insn.op[i], &x86_op_type[xinsn->op[i]]); } return; } } xinsn++; } while (xinsn->name) { if (xinsn->vex == vex) { insn.name = xinsn->name; for (int i = 0; i < 5; i++) { x86opc_insn_op *op = &x86_op_type[xinsn->op[i]]; switch (op->type) { case TYPE_E: case TYPE_M: case TYPE_W: case TYPE_X: /* get whole modrm/sib/disp stuff first * (otherwise a TYPE_VI immediate might * get fetched fetched before the modrm stuff) */ getdisp(); } } for (int i = 0; i < 5; i++) { decode_op(&insn.op[i], &x86_op_type[xinsn->op[i]]); } return; } xinsn++; } } invalidate();}void x86dis::decode_insn(x86opc_insn *xinsn){ if (!xinsn->name) { byte specialtype = xinsn->op[0]; byte specialdata = xinsn->op[1]; switch (specialtype) { case SPECIAL_TYPE_INVALID: invalidate(); break; case SPECIAL_TYPE_PREFIX: switch (c) { case 0x0f: if (insn.opcodeclass == X86DIS_OPCODE_CLASS_STD) { insn.opcode = getbyte(); switch (insn.repprefix) { case X86_PREFIX_REPNZ: if (insn.opsizeprefix == X86_PREFIX_OPSIZE) { invalidate(); } else { insn.repprefix = X86_PREFIX_NO; insn.opcodeclass = X86DIS_OPCODE_CLASS_EXT_F2; decode_insn(&x86_insns_ext_f2[insn.opcode]); } break; case X86_PREFIX_REPZ: if (insn.opsizeprefix == X86_PREFIX_OPSIZE) { invalidate(); } else { insn.repprefix = X86_PREFIX_NO; insn.opcodeclass = X86DIS_OPCODE_CLASS_EXT_F3; decode_insn(&x86_insns_ext_f3[insn.opcode]); } break; default: if (insn.opsizeprefix == X86_PREFIX_NO) { insn.opcodeclass = X86DIS_OPCODE_CLASS_EXT; decode_insn(&x86_insns_ext[insn.opcode]); } else { insn.opcodeclass = X86DIS_OPCODE_CLASS_EXT_66; decode_insn(&x86_insns_ext_66[insn.opcode]); } } break; } invalidate(); break; case 0xc4: case 0xc5: { if (insn.opsizeprefix != X86_PREFIX_NO || insn.lockprefix != X86_PREFIX_NO || insn.repprefix != X86_PREFIX_NO || insn.rexprefix != 0) { invalidate(); break; } byte vex = getbyte(); if (addrsize != X86_ADDRSIZE64 && (vex & 0xc0) != 0xc0) { modrm = vex; decode_insn(c == 0xc4 ? &x86_les : &x86_lds); break; } insn.rexprefix = 0x40; insn.rexprefix = vexr(vex) << 2; if (c == 0xc4) { // 3 byte vex insn.rexprefix |= vexx(vex) << 1; insn.rexprefix |= vexb(vex); insn.vexprefix.mmmm = vexmmmm(vex); if (insn.vexprefix.mmmm == 0 || insn.vexprefix.mmmm > 3) { invalidate(); break; } vex = getbyte(); insn.vexprefix.w |= vexw(vex); } else { // 2 byte vex insn.vexprefix.mmmm = 1; } insn.vexprefix.vvvv = vexvvvv(vex); insn.vexprefix.l = vexl(vex); insn.vexprefix.pp = vexpp(vex); if (addrsize != X86_ADDRSIZE64) { insn.rexprefix = 0; } insn.opcode = getbyte(); decode_vex_insn(x86_vex_insns[insn.opcode]); break; } default: invalidate(); break; } break; case SPECIAL_TYPE_OPC_GROUP: { insn.opcodeclass = X86DIS_OPCODE_CLASS_EXT; insn.opcode = getbyte(); decode_insn(&x86_opc_group_insns[specialdata][insn.opcode]); break; } case SPECIAL_TYPE_GROUP: { int m = mkreg(getmodrm()) & 0x7; decode_insn(&x86_group_insns[specialdata][m]); break; } case SPECIAL_TYPE_SGROUP: { int m = getmodrm(); if (mkmod(m) != 3) { m = 8; } else { m = mkrm(m) & 0x7; } decode_insn(&x86_special_group_insns[specialdata][m]); break; } case SPECIAL_TYPE_FGROUP: { int m = getmodrm(); if (mkmod(m) == 3) { x86opc_finsn f = x86_float_group_insns[specialdata][mkreg(m) & 0x7];/* fprintf(stderr, "special.data=%d, m=%d, mkreg(m)=%d, mkrm(m)=%d\n", special.data, m, mkreg(m), mkrm(m));*/ if (f.group) { decode_insn(&f.group[mkrm(m) & 0x7]); } else if (f.insn.name) { decode_insn(&f.insn); } else invalidate(); } else { decode_insn(&x86_modfloat_group_insns[specialdata][mkreg(m) & 0x7]); } break; } } } else { checkInfo(xinsn); insn.name = xinsn->name; for (int i = 0; i < 4; i++) { decode_op(&insn.op[i], &x86_op_type[xinsn->op[i]]); } }}void x86dis::decode_op(x86_insn_op *op, x86opc_insn_op *xop){ switch (xop->type) { case TYPE_0: return; case TYPE_A: { /* direct address without ModR/M */ op->type = X86_OPTYPE_FARPTR; op->size = esizeop(xop->size); switch (op->size) { case 4: op->farptr.offset = getword(); op->farptr.seg = getword(); break; case 6: op->farptr.offset = getdword(); op->farptr.seg = getword(); break; } break; } case TYPE_C: { /* reg of ModR/M picks control register */ op->type = X86_OPTYPE_CRX; op->size = esizeop(xop->size); op->crx = mkreg(getmodrm()); break; } case TYPE_D: { /* reg of ModR/M picks debug register */ op->type = X86_OPTYPE_DRX; op->size = esizeop(xop->size); op->drx = mkreg(getmodrm()); break; } case TYPE_E: { /* ModR/M (general reg or memory) */ decode_modrm(op, xop->size, (xop->size != SIZE_P), true, false, false, false); break; } case TYPE_F: { /* r/m of ModR/M picks a fpu register */ op->type = X86_OPTYPE_STX; op->size = 10; op->stx = mkrm(getmodrm()); break; } case TYPE_Fx: { /* extra picks a fpu register */ op->type = X86_OPTYPE_STX; op->size = 10; op->stx = xop->extra; break; } case TYPE_G: { /* reg of ModR/M picks general register */ op->type = X86_OPTYPE_REG; op->size = esizeop(xop->size); op->reg = mkreg(getmodrm()); break; } case TYPE_Is: { /* signed immediate */ op->type = X86_OPTYPE_IMM; op->size = esizeop(xop->size); int s = esizeop_ex(xop->size); switch (s) { case 1: op->imm = sint64(sint8(getbyte())); break; case 2: op->imm = sint64(sint16(getword())); break; case 4: op->imm = sint64(sint32(getdword())); break; case 8: op->imm = getqword(); break; } switch (op->size) { case 1: op->imm &= 0xff; break; case 2: op->imm &= 0xffff; break; case 4: op->imm &= 0xffffffff; break; } break; } case TYPE_I: { /* unsigned immediate */ op->type = X86_OPTYPE_IMM; op->size = esizeop(xop->size); int s = esizeop_ex(xop->size); switch (s) { case 1: op->imm = getbyte(); break; case 2: op->imm = getword(); break; case 4: op->imm = sint64(sint32(getdword())); break; case 8: op->imm = getqword(); break; } switch (op->size) { case 1: op->imm &= 0xff; break; case 2: op->imm &= 0xffff; break; case 4: op->imm &= 0xffffffff; break; } break; } case TYPE_Ix: { /* fixed immediate */ op->type = X86_OPTYPE_IMM; op->size = esizeop(xop->size); op->imm = xop->extra; break; } case TYPE_I4: { /* 4 bit immediate (see TYPE_VI, TYPE_YI) */ op->type = X86_OPTYPE_IMM; op->size = 1; op->imm = getspecialimm() & 0xf; break; } case TYPE_J: { /* relative branch offset */ op->type = X86_OPTYPE_IMM; switch (addrsize) { case X86_ADDRSIZE16: op->size = 2; break; case X86_ADDRSIZE32: op->size = 4; break; case X86_ADDRSIZE64: op->size = 8; break;
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -