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 } 314