1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/toolkit/crashreporter/google-breakpad/src/third_party/libdisasm/ia32_invariant.c Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,313 @@ 1.4 +#include <stdlib.h> 1.5 +#include <string.h> 1.6 + 1.7 +#include "ia32_invariant.h" 1.8 +#include "ia32_insn.h" 1.9 +#include "ia32_settings.h" 1.10 + 1.11 +extern ia32_table_desc_t *ia32_tables; 1.12 +extern ia32_settings_t ia32_settings; 1.13 + 1.14 +extern size_t ia32_table_lookup( unsigned char *buf, size_t buf_len, 1.15 + unsigned int table, ia32_insn_t **raw_insn, 1.16 + unsigned int *prefixes ); 1.17 + 1.18 + 1.19 +/* -------------------------------- ModR/M, SIB */ 1.20 +/* Convenience flags */ 1.21 +#define MODRM_EA 1 /* ModR/M is an effective addr */ 1.22 +#define MODRM_reg 2 /* ModR/M is a register */ 1.23 + 1.24 +/* ModR/M flags */ 1.25 +#define MODRM_RM_SIB 0x04 /* R/M == 100 */ 1.26 +#define MODRM_RM_NOREG 0x05 /* R/B == 101 */ 1.27 +/* if (MODRM.MOD_NODISP && MODRM.RM_NOREG) then just disp32 */ 1.28 +#define MODRM_MOD_NODISP 0x00 /* mod == 00 */ 1.29 +#define MODRM_MOD_DISP8 0x01 /* mod == 01 */ 1.30 +#define MODRM_MOD_DISP32 0x02 /* mod == 10 */ 1.31 +#define MODRM_MOD_NOEA 0x03 /* mod == 11 */ 1.32 +/* 16-bit modrm flags */ 1.33 +#define MOD16_MOD_NODISP 0 1.34 +#define MOD16_MOD_DISP8 1 1.35 +#define MOD16_MOD_DISP16 2 1.36 +#define MOD16_MOD_REG 3 1.37 + 1.38 +#define MOD16_RM_BXSI 0 1.39 +#define MOD16_RM_BXDI 1 1.40 +#define MOD16_RM_BPSI 2 1.41 +#define MOD16_RM_BPDI 3 1.42 +#define MOD16_RM_SI 4 1.43 +#define MOD16_RM_DI 5 1.44 +#define MOD16_RM_BP 6 1.45 +#define MOD16_RM_BX 7 1.46 + 1.47 +/* SIB flags */ 1.48 +#define SIB_INDEX_NONE 0x04 1.49 +#define SIB_BASE_EBP 0x05 1.50 +#define SIB_SCALE_NOBASE 0x00 1.51 + 1.52 +/* Convenience struct for modR/M bitfield */ 1.53 +struct modRM_byte { 1.54 + unsigned int mod : 2; 1.55 + unsigned int reg : 3; 1.56 + unsigned int rm : 3; 1.57 +}; 1.58 + 1.59 +/* Convenience struct for SIB bitfield */ 1.60 +struct SIB_byte { 1.61 + unsigned int scale : 2; 1.62 + unsigned int index : 3; 1.63 + unsigned int base : 3; 1.64 +}; 1.65 + 1.66 +#ifdef WIN32 1.67 +static void byte_decode(unsigned char b, struct modRM_byte *modrm) { 1.68 +#else 1.69 +static inline void byte_decode(unsigned char b, struct modRM_byte *modrm) { 1.70 +#endif 1.71 + /* generic bitfield-packing routine */ 1.72 + 1.73 + modrm->mod = b >> 6; /* top 2 bits */ 1.74 + modrm->reg = (b & 56) >> 3; /* middle 3 bits */ 1.75 + modrm->rm = b & 7; /* bottom 3 bits */ 1.76 +} 1.77 +static int ia32_invariant_modrm( unsigned char *in, unsigned char *out, 1.78 + unsigned int mode_16, x86_invariant_op_t *op) { 1.79 + struct modRM_byte modrm; 1.80 + struct SIB_byte sib; 1.81 + unsigned char *c, *cin; 1.82 + unsigned short *s; 1.83 + unsigned int *i; 1.84 + int size = 0; /* modrm byte is already counted */ 1.85 + 1.86 + 1.87 + byte_decode(*in, &modrm); /* get bitfields */ 1.88 + 1.89 + out[0] = in[0]; /* save modrm byte */ 1.90 + cin = &in[1]; 1.91 + c = &out[1]; 1.92 + s = (unsigned short *)&out[1]; 1.93 + i = (unsigned int *)&out[1]; 1.94 + 1.95 + op->type = op_expression; 1.96 + op->flags |= op_pointer; 1.97 + if ( ! mode_16 && modrm.rm == MODRM_RM_SIB && 1.98 + modrm.mod != MODRM_MOD_NOEA ) { 1.99 + size ++; 1.100 + byte_decode(*cin, (struct modRM_byte *)(void*)&sib); 1.101 + 1.102 + out[1] = in[1]; /* save sib byte */ 1.103 + cin = &in[2]; 1.104 + c = &out[2]; 1.105 + s = (unsigned short *)&out[2]; 1.106 + i = (unsigned int *)&out[2]; 1.107 + 1.108 + if ( sib.base == SIB_BASE_EBP && ! modrm.mod ) { 1.109 + /* disp 32 is variant! */ 1.110 + memset( i, X86_WILDCARD_BYTE, 4 ); 1.111 + size += 4; 1.112 + } 1.113 + } 1.114 + 1.115 + if (! modrm.mod && modrm.rm == 101) { 1.116 + if ( mode_16 ) { /* straight RVA in disp */ 1.117 + memset( s, X86_WILDCARD_BYTE, 2 ); 1.118 + size += 2; 1.119 + } else { 1.120 + memset( i, X86_WILDCARD_BYTE, 2 ); 1.121 + size += 4; 1.122 + } 1.123 + } else if (modrm.mod && modrm.mod < 3) { 1.124 + if (modrm.mod == MODRM_MOD_DISP8) { /* offset in disp */ 1.125 + *c = *cin; 1.126 + size += 1; 1.127 + } else if ( mode_16 ) { 1.128 + *s = (* ((unsigned short *) cin)); 1.129 + size += 2; 1.130 + } else { 1.131 + *i = (*((unsigned int *) cin)); 1.132 + size += 4; 1.133 + } 1.134 + } else if ( modrm.mod == 3 ) { 1.135 + op->type = op_register; 1.136 + op->flags &= ~op_pointer; 1.137 + } 1.138 + 1.139 + return (size); 1.140 +} 1.141 + 1.142 + 1.143 +static int ia32_decode_invariant( unsigned char *buf, size_t buf_len, 1.144 + ia32_insn_t *t, unsigned char *out, 1.145 + unsigned int prefixes, x86_invariant_t *inv) { 1.146 + 1.147 + unsigned int addr_size, op_size, mode_16; 1.148 + unsigned int op_flags[3] = { t->dest_flag, t->src_flag, t->aux_flag }; 1.149 + int x, type, bytes = 0, size = 0, modrm = 0; 1.150 + 1.151 + /* set addressing mode */ 1.152 + if (ia32_settings.options & opt_16_bit) { 1.153 + op_size = ( prefixes & PREFIX_OP_SIZE ) ? 4 : 2; 1.154 + addr_size = ( prefixes & PREFIX_ADDR_SIZE ) ? 4 : 2; 1.155 + mode_16 = ( prefixes & PREFIX_ADDR_SIZE ) ? 0 : 1; 1.156 + } else { 1.157 + op_size = ( prefixes & PREFIX_OP_SIZE ) ? 2 : 4; 1.158 + addr_size = ( prefixes & PREFIX_ADDR_SIZE ) ? 2 : 4; 1.159 + mode_16 = ( prefixes & PREFIX_ADDR_SIZE ) ? 1 : 0; 1.160 + } 1.161 + 1.162 + for (x = 0; x < 3; x++) { 1.163 + inv->operands[x].access = (enum x86_op_access) 1.164 + OP_PERM(op_flags[x]); 1.165 + inv->operands[x].flags = (enum x86_op_flags) 1.166 + (OP_FLAGS(op_flags[x]) >> 12); 1.167 + 1.168 + switch (op_flags[x] & OPTYPE_MASK) { 1.169 + case OPTYPE_c: 1.170 + size = (op_size == 4) ? 2 : 1; 1.171 + break; 1.172 + case OPTYPE_a: case OPTYPE_v: 1.173 + size = (op_size == 4) ? 4 : 2; 1.174 + break; 1.175 + case OPTYPE_p: 1.176 + size = (op_size == 4) ? 6 : 4; 1.177 + break; 1.178 + case OPTYPE_b: 1.179 + size = 1; 1.180 + break; 1.181 + case OPTYPE_w: 1.182 + size = 2; 1.183 + break; 1.184 + case OPTYPE_d: case OPTYPE_fs: case OPTYPE_fd: 1.185 + case OPTYPE_fe: case OPTYPE_fb: case OPTYPE_fv: 1.186 + case OPTYPE_si: case OPTYPE_fx: 1.187 + size = 4; 1.188 + break; 1.189 + case OPTYPE_s: 1.190 + size = 6; 1.191 + break; 1.192 + case OPTYPE_q: case OPTYPE_pi: 1.193 + size = 8; 1.194 + break; 1.195 + case OPTYPE_dq: case OPTYPE_ps: case OPTYPE_ss: 1.196 + case OPTYPE_pd: case OPTYPE_sd: 1.197 + size = 16; 1.198 + break; 1.199 + case OPTYPE_m: 1.200 + size = (addr_size == 4) ? 4 : 2; 1.201 + break; 1.202 + default: 1.203 + break; 1.204 + } 1.205 + 1.206 + type = op_flags[x] & ADDRMETH_MASK; 1.207 + switch (type) { 1.208 + case ADDRMETH_E: case ADDRMETH_M: case ADDRMETH_Q: 1.209 + case ADDRMETH_R: case ADDRMETH_W: 1.210 + modrm = 1; 1.211 + bytes += ia32_invariant_modrm( buf, out, 1.212 + mode_16, &inv->operands[x]); 1.213 + break; 1.214 + case ADDRMETH_C: case ADDRMETH_D: case ADDRMETH_G: 1.215 + case ADDRMETH_P: case ADDRMETH_S: case ADDRMETH_T: 1.216 + case ADDRMETH_V: 1.217 + inv->operands[x].type = op_register; 1.218 + modrm = 1; 1.219 + break; 1.220 + case ADDRMETH_A: case ADDRMETH_O: 1.221 + /* pad with xF4's */ 1.222 + memset( &out[bytes + modrm], X86_WILDCARD_BYTE, 1.223 + size ); 1.224 + bytes += size; 1.225 + inv->operands[x].type = op_offset; 1.226 + if ( type == ADDRMETH_O ) { 1.227 + inv->operands[x].flags |= op_signed | 1.228 + op_pointer; 1.229 + } 1.230 + break; 1.231 + case ADDRMETH_I: case ADDRMETH_J: 1.232 + /* grab imm value */ 1.233 + if ((op_flags[x] & OPTYPE_MASK) == OPTYPE_v) { 1.234 + /* assume this is an address */ 1.235 + memset( &out[bytes + modrm], 1.236 + X86_WILDCARD_BYTE, size ); 1.237 + } else { 1.238 + memcpy( &out[bytes + modrm], 1.239 + &buf[bytes + modrm], size ); 1.240 + } 1.241 + 1.242 + bytes += size; 1.243 + if ( type == ADDRMETH_J ) { 1.244 + if ( size == 1 ) { 1.245 + inv->operands[x].type = 1.246 + op_relative_near; 1.247 + } else { 1.248 + inv->operands[x].type = 1.249 + op_relative_far; 1.250 + } 1.251 + inv->operands[x].flags |= op_signed; 1.252 + } else { 1.253 + inv->operands[x].type = op_immediate; 1.254 + } 1.255 + break; 1.256 + case ADDRMETH_F: 1.257 + inv->operands[x].type = op_register; 1.258 + break; 1.259 + case ADDRMETH_X: 1.260 + inv->operands[x].flags |= op_signed | 1.261 + op_pointer | op_ds_seg | op_string; 1.262 + break; 1.263 + case ADDRMETH_Y: 1.264 + inv->operands[x].flags |= op_signed | 1.265 + op_pointer | op_es_seg | op_string; 1.266 + break; 1.267 + case ADDRMETH_RR: 1.268 + inv->operands[x].type = op_register; 1.269 + break; 1.270 + case ADDRMETH_II: 1.271 + inv->operands[x].type = op_immediate; 1.272 + break; 1.273 + default: 1.274 + inv->operands[x].type = op_unused; 1.275 + break; 1.276 + } 1.277 + } 1.278 + 1.279 + return (bytes + modrm); 1.280 +} 1.281 + 1.282 +size_t ia32_disasm_invariant( unsigned char * buf, size_t buf_len, 1.283 + x86_invariant_t *inv ) { 1.284 + ia32_insn_t *raw_insn = NULL; 1.285 + unsigned int prefixes; 1.286 + unsigned int type; 1.287 + size_t size; 1.288 + 1.289 + /* Perform recursive table lookup starting with main table (0) */ 1.290 + size = ia32_table_lookup( buf, buf_len, 0, &raw_insn, &prefixes ); 1.291 + if ( size == INVALID_INSN || size > buf_len ) { 1.292 + /* TODO: set errno */ 1.293 + return 0; 1.294 + } 1.295 + 1.296 + /* copy opcode bytes to buffer */ 1.297 + memcpy( inv->bytes, buf, size ); 1.298 + 1.299 + /* set mnemonic type and group */ 1.300 + type = raw_insn->mnem_flag & ~INS_FLAG_MASK; 1.301 + inv->group = (enum x86_insn_group) (INS_GROUP(type)) >> 12; 1.302 + inv->type = (enum x86_insn_type) INS_TYPE(type); 1.303 + 1.304 + /* handle operands */ 1.305 + size += ia32_decode_invariant( buf + size, buf_len - size, raw_insn, 1.306 + &buf[size - 1], prefixes, inv ); 1.307 + 1.308 + inv->size = size; 1.309 + 1.310 + return size; /* return size of instruction in bytes */ 1.311 +} 1.312 + 1.313 +size_t ia32_disasm_size( unsigned char *buf, size_t buf_len ) { 1.314 + x86_invariant_t inv = { {0} }; 1.315 + return( ia32_disasm_invariant( buf, buf_len, &inv ) ); 1.316 +}