| OLD | NEW |
| (Empty) |
| 1 #include <stdlib.h> | |
| 2 #include <string.h> | |
| 3 | |
| 4 #include "ia32_invariant.h" | |
| 5 #include "ia32_insn.h" | |
| 6 #include "ia32_settings.h" | |
| 7 | |
| 8 extern ia32_table_desc_t *ia32_tables; | |
| 9 extern ia32_settings_t ia32_settings; | |
| 10 | |
| 11 extern size_t ia32_table_lookup( unsigned char *buf, size_t buf_len, | |
| 12 unsigned int table, ia32_insn_t **raw_insn, | |
| 13 unsigned int *prefixes ); | |
| 14 | |
| 15 | |
| 16 /* -------------------------------- ModR/M, SIB */ | |
| 17 /* Convenience flags */ | |
| 18 #define MODRM_EA 1 /* ModR/M is an effective addr */ | |
| 19 #define MODRM_reg 2 /* ModR/M is a register */ | |
| 20 | |
| 21 /* ModR/M flags */ | |
| 22 #define MODRM_RM_SIB 0x04 /* R/M == 100 */ | |
| 23 #define MODRM_RM_NOREG 0x05 /* R/B == 101 */ | |
| 24 /* if (MODRM.MOD_NODISP && MODRM.RM_NOREG) then just disp32 */ | |
| 25 #define MODRM_MOD_NODISP 0x00 /* mod == 00 */ | |
| 26 #define MODRM_MOD_DISP8 0x01 /* mod == 01 */ | |
| 27 #define MODRM_MOD_DISP32 0x02 /* mod == 10 */ | |
| 28 #define MODRM_MOD_NOEA 0x03 /* mod == 11 */ | |
| 29 /* 16-bit modrm flags */ | |
| 30 #define MOD16_MOD_NODISP 0 | |
| 31 #define MOD16_MOD_DISP8 1 | |
| 32 #define MOD16_MOD_DISP16 2 | |
| 33 #define MOD16_MOD_REG 3 | |
| 34 | |
| 35 #define MOD16_RM_BXSI 0 | |
| 36 #define MOD16_RM_BXDI 1 | |
| 37 #define MOD16_RM_BPSI 2 | |
| 38 #define MOD16_RM_BPDI 3 | |
| 39 #define MOD16_RM_SI 4 | |
| 40 #define MOD16_RM_DI 5 | |
| 41 #define MOD16_RM_BP 6 | |
| 42 #define MOD16_RM_BX 7 | |
| 43 | |
| 44 /* SIB flags */ | |
| 45 #define SIB_INDEX_NONE 0x04 | |
| 46 #define SIB_BASE_EBP 0x05 | |
| 47 #define SIB_SCALE_NOBASE 0x00 | |
| 48 | |
| 49 /* Convenience struct for modR/M bitfield */ | |
| 50 struct modRM_byte { | |
| 51 unsigned int mod : 2; | |
| 52 unsigned int reg : 3; | |
| 53 unsigned int rm : 3; | |
| 54 }; | |
| 55 | |
| 56 /* Convenience struct for SIB bitfield */ | |
| 57 struct SIB_byte { | |
| 58 unsigned int scale : 2; | |
| 59 unsigned int index : 3; | |
| 60 unsigned int base : 3; | |
| 61 }; | |
| 62 | |
| 63 #ifdef WIN32 | |
| 64 static void byte_decode(unsigned char b, struct modRM_byte *modrm) { | |
| 65 #else | |
| 66 static inline void byte_decode(unsigned char b, struct modRM_byte *modrm) { | |
| 67 #endif | |
| 68 /* generic bitfield-packing routine */ | |
| 69 | |
| 70 modrm->mod = b >> 6; /* top 2 bits */ | |
| 71 modrm->reg = (b & 56) >> 3; /* middle 3 bits */ | |
| 72 modrm->rm = b & 7; /* bottom 3 bits */ | |
| 73 } | |
| 74 static int ia32_invariant_modrm( unsigned char *in, unsigned char *out, | |
| 75 unsigned int mode_16, x86_invariant_op_t *op) { | |
| 76 struct modRM_byte modrm; | |
| 77 struct SIB_byte sib; | |
| 78 unsigned char *c, *cin; | |
| 79 unsigned short *s; | |
| 80 unsigned int *i; | |
| 81 int size = 0; /* modrm byte is already counted */ | |
| 82 | |
| 83 | |
| 84 byte_decode(*in, &modrm); /* get bitfields */ | |
| 85 | |
| 86 out[0] = in[0]; /* save modrm byte */ | |
| 87 cin = &in[1]; | |
| 88 c = &out[1]; | |
| 89 s = (unsigned short *)&out[1]; | |
| 90 i = (unsigned int *)&out[1]; | |
| 91 | |
| 92 op->type = op_expression; | |
| 93 op->flags |= op_pointer; | |
| 94 if ( ! mode_16 && modrm.rm == MODRM_RM_SIB && | |
| 95 modrm.mod != MODRM_MOD_NOEA ) { | |
| 96 size ++; | |
| 97 byte_decode(*cin, (struct modRM_byte *)(void*)&sib); | |
| 98 | |
| 99 out[1] = in[1]; /* save sib byte */ | |
| 100 cin = &in[2]; | |
| 101 c = &out[2]; | |
| 102 s = (unsigned short *)&out[2]; | |
| 103 i = (unsigned int *)&out[2]; | |
| 104 | |
| 105 if ( sib.base == SIB_BASE_EBP && ! modrm.mod ) { | |
| 106 /* disp 32 is variant! */ | |
| 107 memset( i, X86_WILDCARD_BYTE, 4 ); | |
| 108 size += 4; | |
| 109 } | |
| 110 } | |
| 111 | |
| 112 if (! modrm.mod && modrm.rm == 101) { | |
| 113 if ( mode_16 ) { /* straight RVA in disp */ | |
| 114 memset( s, X86_WILDCARD_BYTE, 2 ); | |
| 115 size += 2; | |
| 116 } else { | |
| 117 memset( i, X86_WILDCARD_BYTE, 2 ); | |
| 118 size += 4; | |
| 119 } | |
| 120 } else if (modrm.mod && modrm.mod < 3) { | |
| 121 if (modrm.mod == MODRM_MOD_DISP8) { /* offset in disp */ | |
| 122 *c = *cin; | |
| 123 size += 1; | |
| 124 } else if ( mode_16 ) { | |
| 125 *s = (* ((unsigned short *) cin)); | |
| 126 size += 2; | |
| 127 } else { | |
| 128 *i = (*((unsigned int *) cin)); | |
| 129 size += 4; | |
| 130 } | |
| 131 } else if ( modrm.mod == 3 ) { | |
| 132 op->type = op_register; | |
| 133 op->flags &= ~op_pointer; | |
| 134 } | |
| 135 | |
| 136 return (size); | |
| 137 } | |
| 138 | |
| 139 | |
| 140 static int ia32_decode_invariant( unsigned char *buf, size_t buf_len, | |
| 141 ia32_insn_t *t, unsigned char *out, | |
| 142 unsigned int prefixes, x86_invariant_t *inv) { | |
| 143 | |
| 144 unsigned int addr_size, op_size, mode_16; | |
| 145 unsigned int op_flags[3] = { t->dest_flag, t->src_flag, t->aux_flag }; | |
| 146 int x, type, bytes = 0, size = 0, modrm = 0; | |
| 147 | |
| 148 /* set addressing mode */ | |
| 149 if (ia32_settings.options & opt_16_bit) { | |
| 150 op_size = ( prefixes & PREFIX_OP_SIZE ) ? 4 : 2; | |
| 151 addr_size = ( prefixes & PREFIX_ADDR_SIZE ) ? 4 : 2; | |
| 152 mode_16 = ( prefixes & PREFIX_ADDR_SIZE ) ? 0 : 1; | |
| 153 } else { | |
| 154 op_size = ( prefixes & PREFIX_OP_SIZE ) ? 2 : 4; | |
| 155 addr_size = ( prefixes & PREFIX_ADDR_SIZE ) ? 2 : 4; | |
| 156 mode_16 = ( prefixes & PREFIX_ADDR_SIZE ) ? 1 : 0; | |
| 157 } | |
| 158 | |
| 159 for (x = 0; x < 3; x++) { | |
| 160 inv->operands[x].access = (enum x86_op_access) | |
| 161 OP_PERM(op_flags[x]); | |
| 162 inv->operands[x].flags = (enum x86_op_flags) | |
| 163 (OP_FLAGS(op_flags[x]) >> 12); | |
| 164 | |
| 165 switch (op_flags[x] & OPTYPE_MASK) { | |
| 166 case OPTYPE_c: | |
| 167 size = (op_size == 4) ? 2 : 1; | |
| 168 break; | |
| 169 case OPTYPE_a: case OPTYPE_v: | |
| 170 size = (op_size == 4) ? 4 : 2; | |
| 171 break; | |
| 172 case OPTYPE_p: | |
| 173 size = (op_size == 4) ? 6 : 4; | |
| 174 break; | |
| 175 case OPTYPE_b: | |
| 176 size = 1; | |
| 177 break; | |
| 178 case OPTYPE_w: | |
| 179 size = 2; | |
| 180 break; | |
| 181 case OPTYPE_d: case OPTYPE_fs: case OPTYPE_fd: | |
| 182 case OPTYPE_fe: case OPTYPE_fb: case OPTYPE_fv: | |
| 183 case OPTYPE_si: case OPTYPE_fx: | |
| 184 size = 4; | |
| 185 break; | |
| 186 case OPTYPE_s: | |
| 187 size = 6; | |
| 188 break; | |
| 189 case OPTYPE_q: case OPTYPE_pi: | |
| 190 size = 8; | |
| 191 break; | |
| 192 case OPTYPE_dq: case OPTYPE_ps: case OPTYPE_ss: | |
| 193 case OPTYPE_pd: case OPTYPE_sd: | |
| 194 size = 16; | |
| 195 break; | |
| 196 case OPTYPE_m: | |
| 197 size = (addr_size == 4) ? 4 : 2; | |
| 198 break; | |
| 199 default: | |
| 200 break; | |
| 201 } | |
| 202 | |
| 203 type = op_flags[x] & ADDRMETH_MASK; | |
| 204 switch (type) { | |
| 205 case ADDRMETH_E: case ADDRMETH_M: case ADDRMETH_Q: | |
| 206 case ADDRMETH_R: case ADDRMETH_W: | |
| 207 modrm = 1; | |
| 208 bytes += ia32_invariant_modrm( buf, out, | |
| 209 mode_16, &inv->operands[x]); | |
| 210 break; | |
| 211 case ADDRMETH_C: case ADDRMETH_D: case ADDRMETH_G: | |
| 212 case ADDRMETH_P: case ADDRMETH_S: case ADDRMETH_T: | |
| 213 case ADDRMETH_V: | |
| 214 inv->operands[x].type = op_register; | |
| 215 modrm = 1; | |
| 216 break; | |
| 217 case ADDRMETH_A: case ADDRMETH_O: | |
| 218 /* pad with xF4's */ | |
| 219 memset( &out[bytes + modrm], X86_WILDCARD_BYTE, | |
| 220 size ); | |
| 221 bytes += size; | |
| 222 inv->operands[x].type = op_offset; | |
| 223 if ( type == ADDRMETH_O ) { | |
| 224 inv->operands[x].flags |= op_signed | | |
| 225 op_pointer; | |
| 226 } | |
| 227 break; | |
| 228 case ADDRMETH_I: case ADDRMETH_J: | |
| 229 /* grab imm value */ | |
| 230 if ((op_flags[x] & OPTYPE_MASK) == OPTYPE_v) { | |
| 231 /* assume this is an address */ | |
| 232 memset( &out[bytes + modrm], | |
| 233 X86_WILDCARD_BYTE, size ); | |
| 234 } else { | |
| 235 memcpy( &out[bytes + modrm], | |
| 236 &buf[bytes + modrm], size ); | |
| 237 } | |
| 238 | |
| 239 bytes += size; | |
| 240 if ( type == ADDRMETH_J ) { | |
| 241 if ( size == 1 ) { | |
| 242 inv->operands[x].type = | |
| 243 op_relative_near; | |
| 244 } else { | |
| 245 inv->operands[x].type = | |
| 246 op_relative_far; | |
| 247 } | |
| 248 inv->operands[x].flags |= op_signed; | |
| 249 } else { | |
| 250 inv->operands[x].type = op_immediate; | |
| 251 } | |
| 252 break; | |
| 253 case ADDRMETH_F: | |
| 254 inv->operands[x].type = op_register; | |
| 255 break; | |
| 256 case ADDRMETH_X: | |
| 257 inv->operands[x].flags |= op_signed | | |
| 258 op_pointer | op_ds_seg | op_string; | |
| 259 break; | |
| 260 case ADDRMETH_Y: | |
| 261 inv->operands[x].flags |= op_signed | | |
| 262 op_pointer | op_es_seg | op_string; | |
| 263 break; | |
| 264 case ADDRMETH_RR: | |
| 265 inv->operands[x].type = op_register; | |
| 266 break; | |
| 267 case ADDRMETH_II: | |
| 268 inv->operands[x].type = op_immediate; | |
| 269 break; | |
| 270 default: | |
| 271 inv->operands[x].type = op_unused; | |
| 272 break; | |
| 273 } | |
| 274 } | |
| 275 | |
| 276 return (bytes + modrm); | |
| 277 } | |
| 278 | |
| 279 size_t ia32_disasm_invariant( unsigned char * buf, size_t buf_len, | |
| 280 x86_invariant_t *inv ) { | |
| 281 ia32_insn_t *raw_insn = NULL; | |
| 282 unsigned int prefixes; | |
| 283 unsigned int type; | |
| 284 size_t size; | |
| 285 | |
| 286 /* Perform recursive table lookup starting with main table (0) */ | |
| 287 size = ia32_table_lookup( buf, buf_len, 0, &raw_insn, &prefixes ); | |
| 288 if ( size == INVALID_INSN || size > buf_len ) { | |
| 289 /* TODO: set errno */ | |
| 290 return 0; | |
| 291 } | |
| 292 | |
| 293 /* copy opcode bytes to buffer */ | |
| 294 memcpy( inv->bytes, buf, size ); | |
| 295 | |
| 296 /* set mnemonic type and group */ | |
| 297 type = raw_insn->mnem_flag & ~INS_FLAG_MASK; | |
| 298 inv->group = (enum x86_insn_group) (INS_GROUP(type)) >> 12; | |
| 299 inv->type = (enum x86_insn_type) INS_TYPE(type); | |
| 300 | |
| 301 /* handle operands */ | |
| 302 size += ia32_decode_invariant( buf + size, buf_len - size, raw_insn, | |
| 303 &buf[size - 1], prefixes, inv ); | |
| 304 | |
| 305 inv->size = size; | |
| 306 | |
| 307 return size; /* return size of instruction in bytes */ | |
| 308 } | |
| 309 | |
| 310 size_t ia32_disasm_size( unsigned char *buf, size_t buf_len ) { | |
| 311 x86_invariant_t inv = { {0} }; | |
| 312 return( ia32_disasm_invariant( buf, buf_len, &inv ) ); | |
| 313 } | |
| OLD | NEW |