📄 x86asm.cc
字号:
case 0: mod = 0; dispsize = 0; break; case 1: mod = 1; dispsize = 1; break; case 2: case 4: case 8: mod = 2; dispsize = 4; break; default: return false; } if (base == X86_REG_NO) { base = 5; mod = 0; dispsize = 4; if (!mindispsize) *disp = 0; } else { if ((base & 7) == X86_REG_BP && mod == 0) { mod = 1; dispsize = 1; if (!mindispsize) *disp = 0; } } *_mod = mod; *_ss = ss; *_index = index; *_base = base; if (index & 8) rexprefix |= rexx; if (base & 8) rexprefix |= rexb; *_dispsize = dispsize; return 1;}int x86asm::esizeop(uint c, int size){ switch (c) { case SIZE_B: return 1; case SIZE_W: return 2; case SIZE_D: case SIZE_S: return 4; case SIZE_Q: case SIZE_L: return 8; case SIZE_O: return 16; case SIZE_T: return 10; case SIZE_V: case SIZE_BV: case SIZE_VV: switch (size) { case X86_OPSIZE16: return 2; case X86_OPSIZE32: return 4; case X86_OPSIZE64: return 8; }/* case SIZE_R: if (rexw(insn.rexprefix)) return 8; else return 4; case SIZE_U: if (insn.opsizeprefix == X86_PREFIX_OPSIZE) return 16; else return 8; case SIZE_Z: if (insn.opsizeprefix == X86_PREFIX_OPSIZE) return 8; else return 4;*/ case SIZE_P: if (size == X86_OPSIZE16) return 4; else return 6; } return 0;}int x86asm::esizeop_ex(uint c, int size){ switch (c) { case SIZE_BV: return 1; case SIZE_VV: switch (size) { case X86_OPSIZE16: return 2; case X86_OPSIZE32: case X86_OPSIZE64: return 4; } } return esizeop(c, size);}char x86asm::flsz2hsz(int size){ switch (size) { case 4: return SIZE_S; case 8: return SIZE_L; case 10: return SIZE_T; } return 0;}const char *x86asm::get_name(){ return "x86asm";}const char *x86asm::immlsz2hsz(int size, int opsize){ if (opsize == X86_OPSIZE16) { switch (size) { case 1: return immhsz8_16; case 2: return immhsz16_16; case 4: return immhsz32_16; case 8: return immhsz64_16; } } else if (opsize == X86_OPSIZE32) { switch (size) { case 1: return immhsz8_32; case 2: return immhsz16_32; case 4: return immhsz32_32; case 8: return immhsz64_32; } } else { switch (size) { case 1: return immhsz8_64; case 2: return immhsz16_64; case 4: return immhsz32_64; case 8: return immhsz64_64; } } return 0;}const char *x86asm::lsz2hsz(int size, int opsize){ if (opsize == X86_OPSIZE16) { switch (size) { case 1: return hsz8_16; case 2: return hsz16_16; case 4: return hsz32_16; case 6: return hsz48_16; case 8: return hsz64_16; case 16: return hsz128_16; case 32: return hsz256_16; } } else if (opsize == X86_OPSIZE32) { switch (size) { case 1: return hsz8_32; case 2: return hsz16_32; case 4: return hsz32_32; case 6: return hsz48_32; case 8: return hsz64_32; case 16: return hsz128_32; case 32: return hsz256_32; } } else { switch (size) { case 1: return hsz8_64; case 2: return hsz16_64; case 4: return hsz32_64; case 6: return hsz48_64; case 8: return hsz64_64; case 16: return hsz128_64; case 32: return hsz256_64; } } return 0;}#define MATCHTYPE_NOMATCH 0#define MATCHTYPE_MATCH 1#define MATCHTYPE_NOOPPREFIX 2#define MATCHTYPE_OPPREFIX 3int x86asm::match_type(x86_insn_op *op, x86opc_insn_op *xop, int addrsize){ if (op->type == X86_OPTYPE_EMPTY && xop->type == TYPE_0) return MATCHTYPE_MATCH; int r = MATCHTYPE_MATCH; if (op->type == X86_OPTYPE_MMX) { if ((xop->type == TYPE_P || xop->type == TYPE_PR || xop->type == TYPE_Q) && (xop->size == SIZE_U || xop->size == SIZE_Z)) { r = MATCHTYPE_NOOPPREFIX; } } const byte *hop = lop2hop[op->type]; while (*hop) { if (*hop == xop->type) { if (xop->type == TYPE_Rx) { if (xop->extra == (op->reg & 7)) return r; } else if (xop->type == TYPE_RXx) { if (xop->extra == op->reg) return r; } else if (xop->type == TYPE_Sx) { if (xop->extra == op->seg) return r; } else if (xop->type == TYPE_Ix) { if ((unsigned)xop->extra == op->imm) return r; } else if (xop->type == TYPE_Fx) { if (xop->extra == op->stx) return r; } else if (xop->type == TYPE_Vx) { if (xop->extra == op->xmm) return r; } else if (op->type == X86_OPTYPE_MEM) { if (op->mem.addrsize == addrsize || op->mem.addrsize == X86_ADDRSIZEUNKNOWN) return r; } else return r; } hop++; } // special xmm match of mmx operands if (op->type == X86_OPTYPE_XMM) { if ((xop->type == TYPE_P || xop->type == TYPE_PR || xop->type == TYPE_Q) && (xop->size == SIZE_U || xop->size == SIZE_Z)) { return MATCHTYPE_OPPREFIX; } } return MATCHTYPE_NOMATCH;}bool x86asm::match_size(x86_insn_op *op, x86opc_insn_op *xop, int opsize){ if (op->type == X86_OPTYPE_EMPTY && xop->type == TYPE_0) return true; if (!op->size && xop->type != TYPE_0) return true; const char *hsz = NULL; byte xopsize = xop->size; if (op->type == X86_OPTYPE_REG && xop->type == TYPE_MR) { xopsize = xop->extra; } if ((op->type == X86_OPTYPE_MEM && op->mem.floatptr) || op->type == X86_OPTYPE_STX) { return xop->size == flsz2hsz(op->size); } else if (op->type == X86_OPTYPE_IMM) { if (xop->type == TYPE_Is) { hsz = immlsz2hsz(simmsize(op->imm, esizeop(xop->size, opsize)), opsize); //XXX } else if (xop->type == TYPE_J) { int ssize = esizeop_ex(xop->size, opsize); int size = esizeop(xop->size, opsize); // FIXME: ?! hsz = immlsz2hsz(simmsize(op->imm - address - code.size - ssize, size), opsize); } else { hsz = immlsz2hsz(simmsize(op->imm, esizeop(xop->size, opsize)), opsize); //XXX } } else if (op->type == X86_OPTYPE_YMM || op->type == X86_OPTYPE_XMM || op->type == X86_OPTYPE_MMX) { return true; } else { hsz = lsz2hsz(op->size, opsize); } if (hsz) { while (*hsz) { if (*hsz == xopsize) return true; hsz++; } } return false;}int x86asm::match_allops(x86asm_insn *insn, byte *xop, int maxop, int opsize, int addrsize){ int m = 0; for (int i = 0; i < maxop; i++) { int m2 = match_type(&insn->op[i], &x86_op_type[xop[i]], addrsize); if (!m2 || (m && m != MATCHTYPE_MATCH && m2 != MATCHTYPE_MATCH && m != m2)) { return MATCHTYPE_NOMATCH; } else { if (m2 > m) m = m2; } if (!match_size(&insn->op[i], &x86_op_type[xop[i]], opsize)) return MATCHTYPE_NOMATCH; } return m;}static void pickname(char *result, const char *name, int n){ const char *s = name; do { name = s+1; s = strchr(name, '|'); if (!s) { strcpy(result, name); return; } } while (n--); ht_strlcpy(result, name, s-name+1);}int x86asm::match_opcode_name(const char *input_name, const char *opcodelist_name, int def_match){ if (opcodelist_name) { if (*opcodelist_name == '~') opcodelist_name++; char n1[32], n2[32], n3[32]; pickname(n1, opcodelist_name, 0); pickname(n2, opcodelist_name, 1); pickname(n3, opcodelist_name, 2); switch (opcodelist_name[0]) { case '|': case '&': if (strcmp(n1, input_name)==0) return def_match; if (strcmp(n2, input_name)==0) return def_match; if (strcmp(n3, input_name)==0) return def_match; break; case '?': if (strcmp(n1, input_name)==0) return MATCHOPNAME_MATCH_IF_OPSIZE16; if (strcmp(n2, input_name)==0) return MATCHOPNAME_MATCH_IF_OPSIZE32; if (strcmp(n3, input_name)==0) return MATCHOPNAME_MATCH_IF_OPSIZE64; break; case '*': if (strcmp(n1, input_name)==0) return MATCHOPNAME_MATCH_IF_ADDRSIZE16; if (strcmp(n2, input_name)==0) return MATCHOPNAME_MATCH_IF_ADDRSIZE32; if (strcmp(n3, input_name)==0) return MATCHOPNAME_MATCH_IF_ADDRSIZE64; break; default: if (strcmp(opcodelist_name, input_name)==0) return def_match; } } return MATCHOPNAME_NOMATCH;} static void swap(char &a, char &b){ char tmp = a; a = b; b = tmp;}void x86asm::match_opcode(x86opc_insn *opcode, x86asm_insn *insn, int prefix, byte opcodebyte, int additional_opcode, int def_match){ int n = match_opcode_name(insn->name, opcode->name, def_match); namefound |= n; if (n == MATCHOPNAME_NOMATCH) return; insn->opsizeprefix = X86_PREFIX_NO; char opsizes[] = {X86_OPSIZE16, X86_OPSIZE32, X86_OPSIZE64}; char addrsizes[] = {X86_ADDRSIZE16, X86_ADDRSIZE32, X86_ADDRSIZE64}; switch (addrsize) { case X86_ADDRSIZE32: swap(addrsizes[0], addrsizes[1]); break; case X86_ADDRSIZE64: swap(addrsizes[0], addrsizes[2]); break; case X86_ADDRSIZE16: case X86_ADDRSIZEUNKNOWN:; } bool done1 = false; int o = 0; /* * check all permutations of opsize and addrsize * if possible and necessary */ switch (n) { case MATCHOPNAME_MATCH_IF_OPSIZE16: done1 = true; break; case MATCHOPNAME_MATCH_IF_OPSIZE32: o = 1; done1 = true; break; case MATCHOPNAME_MATCH_IF_OPSIZE64: o = 2; done1 = true; break; } for (; o < 3; o++) { if (o == 2 && addrsize != X86_ADDRSIZE64) break; switch (def_match) { case MATCHOPNAME_MATCH_IF_OPPREFIX: if (opsize == X86_OPSIZE16 && o == 0) continue; if (opsize == X86_OPSIZE32 && o == 1) continue; break; case MATCHOPNAME_MATCH_IF_NOOPPREFIX: if (opsize == X86_OPSIZE16 && o == 1) continue; if (opsize == X86_OPSIZE32 && o == 0) continue; break; } for (int a=0; a < 2; a++) { char as = addrsizes[a]; bool done2 = false; switch (n) { case MATCHOPNAME_MATCH_IF_ADDRSIZE16: as = X86_ADDRSIZE16; done2 = true; break; case MATCHOPNAME_MATCH_IF_ADDRSIZE32: as = X86_ADDRSIZE32; done2 = true; break; case MATCHOPNAME_MATCH_IF_ADDRSIZE64: as = X86_ADDRSIZE64; done2 = true; break; } match_opcode_final(opcode, insn, prefix, opcodebyte, additional_opcode, opsizes[o], as, n); if (done2) break; } if (done1) break; }}void x86asm::match_vex_opcode(x86opc_vex_insn *opcode, x86asm_insn *insn, byte opcodebyte, int additional_opcode){ int n = match_opcode_name(insn->name, opcode->name, MATCHOPNAME_MATCH_IF_NOOPPREFIX); namefound |= n; if (n == MATCHOPNAME_NOMATCH) return; char addrsizes[] = {X86_ADDRSIZE16, X86_ADDRSIZE32, X86_ADDRSIZE64}; switch (addrsize) { case X86_ADDRSIZE32: swap(addrsizes[0], addrsizes[1]); break; case X86_ADDRSIZE64: swap(addrsizes[0], addrsizes[2]); break; case X86_ADDRSIZE16: case X86_ADDRSIZEUNKNOWN:; } for (int a=0; a < 2; a++) { char as = addrsizes[a]; match_vex_opcode_final(opcode, insn, opcodebyte, additional_opcode, opsize, as); }}int x86asm::match_opcode_final(x86opc_insn *opcode, x86asm_insn *insn, int prefix, byte opcodebyte, int additional_opcode, int opsize, int addrsize, int match){ switch (match_allops(insn, opcode->op, 4, opsize, addrsize)) { case MATCHTYPE_NOMATCH: return false; case MATCHTYPE_MATCH: if (match == MATCHOPNAME_MATCH_IF_OPPREFIX) { insn->opsizeprefix = X86_PREFIX_OPSIZE; } else if (match == MATCHOPNAME_MATCH_IF_NOOPPREFIX) { insn->opsizeprefix = X86_PREFIX_NOOPSIZE; } break; case MATCHTYPE_NOOPPREFIX: if (match == MATCHOPNAME_MATCH_IF_OPPREFIX) return false; insn->opsizeprefix = X86_PREFIX_NOOPSIZE; break; case MATCHTYPE_OPPREFIX: if (match == MATCHOPNAME_MATCH_IF_NOOPPREFIX) return false; insn->opsizeprefix = X86_PREFIX_OPSIZE; break; } if (encode_insn(insn, opcode, opcodebyte, additional_opcode, prefix, opsize, addrsize)) { pushcode(); newcode(); } return true;}int x86asm::match_vex_opcode_final(x86opc_vex_insn *opcode, x86asm_insn *insn, byte opcodebyte, int additional_opcode, int opsize, int addrsize){ if (match_allops(insn, opcode->op, 5, opsize, addrsize) == MATCHTYPE_NOMATCH) { return false; } if (encode_vex_insn(insn, opcode, opcodebyte, additional_opcode, opsize, addrsize)) { pushcode(); newcode(); } return true;}void x86asm::match_opcodes(x86opc_insn *opcodes, x86asm_insn *insn, int prefix, int def_match){ for (int i=0; i < 256; i++) { if (!opcodes[i].name) { byte specialtype = opcodes[i].op[0]; if (specialtype == SPECIAL_TYPE_GROUP) { byte specialdata = opcodes[i].op[1]; x86opc_insn *group = x86_group_insns[specialdata]; for (int g=0; g < 8; g++) { if (!group[g].name) { byte special2type = group[g].op[0]; if (special2type == SPECIAL_TYPE_SGROUP) { byte special2data = group[g].op[1]; x86opc_insn *group = x86_special_group_insns[special2data]; for (int h=0; h < 8; h++) { match_opcode(&group[h], insn, prefix, i, (h<<3) + g + 0x800, def_match); } match_opcode(&group[8], insn, prefix, i, -1, def_match); } } else { match_opcode(&group[g], insn, prefix, i, g, def_match); } } } } else { match_opcode(&opcodes[i], insn, prefix, i, -1, def_match); } }}void x86asm::match_vex_opcodes(x86asm_insn *insn){ for (int i=0; i < 256; i++) { x86opc_vex_insn *opcodes = x86_vex_insns[i]; if (!opcodes) continue; while (!opcodes->name && opcodes->op[0] == SPECIAL_TYPE_GROUP) { for (int j=0; j < 8; j++) { x86opc_vex_insn *group = &x86_group_vex_insns[opcodes->op[1]][j]; if (group->name) match_vex_opcode(group, insn, i, j); } opcodes++; } while (opcodes->name) { match_vex_opcode(opcodes, insn, i, -1); opcodes++; } }}void x86asm::match_fopcodes(x86asm_insn *insn){ /* try modrm fopcodes */ for (int i=0; i < 8; i++) { for (int j=0; j < 8; j++) { int n = match_opcode_name(insn->name, x86_modfloat_group_insns[i][j].name, MATCHOPNAME_MATCH); namefound |= n; if (n != MATCHOPNAME_NOMATCH) { int eaddrsize = addrsize; for (int k=0; k < 2; k++) { if (match_allops(insn, x86_modfloat_group_insns[i][j].op, 4, opsize, eaddrsize)) { if (encode_insn(insn, &x86_modfloat_group_insns[i][j], j<<3, -1, X86ASM_PREFIX_D8+i, opsize, eaddrsize)) { pushcode(); newcode(); } } switch (eaddrsize) { case X86_ADDRSIZE64: case X86_ADDRSIZE16: eaddrsize = X86_ADDRSIZE32; break; case X86_ADDRSIZE32: eaddrsize = X86_ADDRSIZE16; break; } } } } } /* try the rest */ for (int i=0; i<8; i++) { for (int j=0; j<8; j++) { if (x86_float_group_insns[i][j].group == 0) { int n = match_opcode_name(insn->name, x86_float_group_insns[i][j].insn.name, MATCHOPNAME_MATCH); namefound |= n; if (n != MATCHOPNAME_NOMATCH) { if (match_allops(insn, x86_float_group_insns[i][j].insn.op, 4, opsize, addrsize)) { if (encode_insn(insn, &x86_float_group_insns[i][j].insn, 0xc0 | j<<3, -1, X86ASM_PREFIX_D8+i, opsize, addrsize)) { pushcode(); newcode(); } if (error) return; } } } else { x86opc_insn *group=x86_float_group_insns[i][j].group; for (int k=0; k < 8; k++) { int n = match_opcode_name(insn->name, group[k].name, MATCHOPNAME_MATCH); namefound |= n; if (n != MATCHOPNAME_NOMATCH) { int eaddrsize = addrsize;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -