toolkit/crashreporter/google-breakpad/src/third_party/libdisasm/ia32_invariant.c

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

     1 #include <stdlib.h>
     2 #include <string.h>
     4 #include "ia32_invariant.h"
     5 #include "ia32_insn.h"
     6 #include "ia32_settings.h"
     8 extern ia32_table_desc_t *ia32_tables;
     9 extern ia32_settings_t ia32_settings;
    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 );
    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 */
    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
    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
    44 /* SIB flags */
    45 #define SIB_INDEX_NONE       0x04
    46 #define SIB_BASE_EBP       0x05
    47 #define SIB_SCALE_NOBASE    0x00
    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 };
    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 };
    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 */
    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 */
    84 	byte_decode(*in, &modrm);	/* get bitfields */
    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];
    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);
    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];
   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 	}
   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 	}
   136 	return (size);
   137 }
   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) {
   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;
   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 	}
   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);
   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 		}
   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 				}
   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 	}
   276 	return (bytes + modrm);
   277 }
   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;
   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 	}
   293 	/* copy opcode bytes to buffer */
   294 	memcpy( inv->bytes, buf, size );
   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);
   301 	/* handle operands */
   302 	size += ia32_decode_invariant( buf + size, buf_len - size, raw_insn, 
   303 					&buf[size - 1], prefixes, inv );
   305 	inv->size = size;
   307 	return size;		/* return size of instruction in bytes */
   308 }
   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 }

mercurial