toolkit/crashreporter/google-breakpad/src/third_party/libdisasm/ia32_implicit.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>
     3 #include "ia32_implicit.h"
     4 #include "ia32_insn.h"
     5 #include "ia32_reg.h"
     6 #include "x86_operand_list.h"
     8 /* Conventions: Register operands which are aliases of another register 
     9  *   operand (e.g. AX in one operand and AL in another) assume that the
    10  *   operands are different registers and that alias tracking will resolve
    11  *   data flow. This means that something like
    12  *   	mov ax, al
    13  *   would have 'write only' access for AX and 'read only' access for AL,
    14  *   even though both AL and AX are read and written */
    15 typedef struct {
    16 	uint32_t type;
    17 	uint32_t operand;
    18 } op_implicit_list_t;
    20 static op_implicit_list_t list_aaa[] = 
    21 	/* 37 : AAA : rw AL */
    22 	/* 3F : AAS : rw AL */
    23 	{{ OP_R | OP_W, REG_BYTE_OFFSET }, {0}};	/* aaa */
    25 static op_implicit_list_t list_aad[] = 
    26 	/* D5 0A, D5 (ib) : AAD : rw AX */
    27 	/* D4 0A, D4 (ib) : AAM : rw AX */
    28 	{{ OP_R | OP_W, REG_WORD_OFFSET }, {0}};	/* aad */
    30 static op_implicit_list_t list_call[] = 
    31 	/* E8, FF, 9A, FF : CALL : rw ESP, rw EIP */
    32 	/* C2, C3, CA, CB : RET  : rw ESP, rw EIP */
    33 	{{ OP_R | OP_W, REG_EIP_INDEX }, 
    34 	 { OP_R | OP_W, REG_ESP_INDEX }, {0}};	/* call, ret */
    36 static op_implicit_list_t list_cbw[] = 
    37 	/* 98 : CBW : r AL, rw AX */
    38 	{{ OP_R | OP_W, REG_WORD_OFFSET },
    39 	 { OP_R, REG_BYTE_OFFSET}, {0}};		/* cbw */
    41 static op_implicit_list_t list_cwde[] = 
    42 	/* 98 : CWDE : r AX, rw EAX */
    43 	{{ OP_R | OP_W, REG_DWORD_OFFSET },
    44 	 { OP_R, REG_WORD_OFFSET }, {0}};		/* cwde */
    46 static op_implicit_list_t list_clts[] = 
    47 	/* 0F 06 : CLTS : rw CR0 */
    48 	{{ OP_R | OP_W, REG_CTRL_OFFSET}, {0}};	/* clts */
    50 static op_implicit_list_t list_cmpxchg[] = 
    51 	/* 0F B0 : CMPXCHG : rw AL */
    52 	{{ OP_R | OP_W, REG_BYTE_OFFSET }, {0}};	/* cmpxchg */
    54 static op_implicit_list_t list_cmpxchgb[] = 
    55 	/* 0F B1 : CMPXCHG : rw EAX */
    56 	{{ OP_R | OP_W, REG_DWORD_OFFSET }, {0}};	/* cmpxchg */
    58 static op_implicit_list_t list_cmpxchg8b[] = 
    59 	/* 0F C7 : CMPXCHG8B : rw EDX, rw EAX, r ECX, r EBX */
    60 	{{ OP_R | OP_W, REG_DWORD_OFFSET }, 
    61 	 { OP_R | OP_W, REG_DWORD_OFFSET + 2 }, 
    62 	 { OP_R, REG_DWORD_OFFSET + 1 }, 
    63 	 { OP_R, REG_DWORD_OFFSET + 3 }, {0}};	/* cmpxchg8b */
    65 static op_implicit_list_t list_cpuid[] = 
    66 	/* 0F A2 : CPUID : rw EAX, w EBX, w ECX, w EDX */
    67 	{{ OP_R | OP_W, REG_DWORD_OFFSET }, 
    68 	 { OP_W, REG_DWORD_OFFSET + 1 }, 
    69 	 { OP_W, REG_DWORD_OFFSET + 2 }, 
    70 	 { OP_W, REG_DWORD_OFFSET + 3 }, {0}};	/* cpuid */
    72 static op_implicit_list_t list_cwd[] = 
    73 	/* 99 : CWD/CWQ : rw EAX, w EDX */
    74 	{{ OP_R | OP_W, REG_DWORD_OFFSET }, 
    75 	 { OP_W, REG_DWORD_OFFSET + 2 }, {0}};	/* cwd */
    77 static op_implicit_list_t list_daa[] = 
    78 	/* 27 : DAA : rw AL */
    79 	/* 2F : DAS : rw AL */
    80 	{{ OP_R | OP_W, REG_BYTE_OFFSET }, {0}};	/* daa */
    82 static op_implicit_list_t list_idiv[] = 
    83 	/* F6 : DIV, IDIV : r AX, w AL, w AH */
    84 	/* FIXED: first op was EAX, not Aw. TODO: verify! */
    85 	{{ OP_R, REG_WORD_OFFSET }, 
    86 	  { OP_W, REG_BYTE_OFFSET },
    87 	  { OP_W, REG_BYTE_OFFSET + 4 }, {0}};	/* div */
    89 static op_implicit_list_t list_div[] = 
    90 	/* F7 : DIV, IDIV : rw EDX, rw EAX */
    91 	{{ OP_R | OP_W, REG_DWORD_OFFSET + 2 }, 
    92 	  { OP_R | OP_W, REG_DWORD_OFFSET }, {0}};	/* div */
    94 static op_implicit_list_t list_enter[] = 
    95 	/* C8 : ENTER : rw ESP w EBP */
    96 	{{ OP_R | OP_W, REG_DWORD_OFFSET + 4 }, 
    97 	 { OP_R, REG_DWORD_OFFSET + 5 }, {0}};	/* enter */
    99 static op_implicit_list_t list_f2xm1[] = 
   100 	/* D9 F0 : F2XM1 : rw ST(0) */
   101 	/* D9 E1 : FABS : rw ST(0) */
   102 	/* D9 E0 : FCHS : rw ST(0) */
   103 	/* D9 FF : FCOS : rw ST(0)*/
   104 	/* D8, DA : FDIV : rw ST(0) */
   105 	/* D8, DA : FDIVR : rw ST(0) */
   106 	/* D9 F2 : FPTAN : rw ST(0) */
   107 	/* D9 FC : FRNDINT : rw ST(0) */
   108 	/* D9 FB : FSINCOS : rw ST(0) */
   109 	/* D9 FE : FSIN : rw ST(0) */
   110 	/* D9 FA : FSQRT : rw ST(0) */
   111 	/* D9 F4 : FXTRACT : rw ST(0) */
   112 	{{ OP_R | OP_W, REG_FPU_OFFSET }, {0}};	/* f2xm1 */
   114 static op_implicit_list_t list_fcom[] = 
   115 	/* D8, DC, DE D9 : FCOM : r ST(0) */
   116 	/* DE, DA : FICOM : r ST(0) */
   117 	/* DF, D8 : FIST : r ST(0) */
   118 	/* D9 E4 : FTST : r ST(0) */
   119 	/* D9 E5 : FXAM : r ST(0) */
   120 	{{ OP_R, REG_FPU_OFFSET }, {0}};		/* fcom */
   122 static op_implicit_list_t list_fpatan[] = 
   123 	/* D9 F3 : FPATAN : r ST(0), rw ST(1) */
   124 	{{ OP_R, REG_FPU_OFFSET }, {0}};		/* fpatan */
   126 static op_implicit_list_t list_fprem[] = 
   127 	/* D9 F8, D9 F5 : FPREM : rw ST(0) r ST(1) */
   128 	/* D9 FD : FSCALE : rw ST(0), r ST(1) */
   129 	{{ OP_R | OP_W, REG_FPU_OFFSET }, 	
   130 	 { OP_R, REG_FPU_OFFSET + 1 }, {0}};	/* fprem */
   132 static op_implicit_list_t list_faddp[] = 
   133 	/* DE C1 : FADDP : r ST(0), rw ST(1) */
   134 	/* DE E9 : FSUBP : r ST(0), rw ST(1) */
   135 	/* D9 F1 : FYL2X : r ST(0), rw ST(1) */
   136 	/* D9 F9 : FYL2XP1 : r ST(0), rw ST(1) */
   137 	{{ OP_R, REG_FPU_OFFSET },
   138 	 { OP_R | OP_W, REG_FPU_OFFSET + 1 }, {0}};	/* faddp */
   140 static op_implicit_list_t list_fucompp[] = 
   141 	/* DA E9 : FUCOMPP : r ST(0), r ST(1) */
   142 	{{ OP_R, REG_FPU_OFFSET },
   143 	 { OP_R, REG_FPU_OFFSET + 1 }, {0}};	/* fucompp */
   145 static op_implicit_list_t list_imul[] = 
   146 	/* F6 : IMUL : r AL, w AX */
   147 	/* F6 : MUL : r AL, w AX */
   148 	{{ OP_R, REG_BYTE_OFFSET },
   149 	 { OP_W, REG_WORD_OFFSET }, {0}};		/* imul */
   151 static op_implicit_list_t list_mul[] = 
   152 	/* F7 : IMUL : rw EAX, w EDX */
   153 	/* F7 : MUL : rw EAX, w EDX */
   154 	{{ OP_R | OP_W, REG_DWORD_OFFSET },
   155 	 { OP_W, REG_DWORD_OFFSET + 2 }, {0}};	/* imul */
   157 static op_implicit_list_t list_lahf[] = 
   158 	/* 9F : LAHF : r EFLAGS, w AH */
   159 	{{ OP_R, REG_FLAGS_INDEX },
   160 	 { OP_W, REG_BYTE_OFFSET + 4 }, {0}};	/* lahf */
   162 static op_implicit_list_t list_ldmxcsr[] = 
   163 	/* 0F AE : LDMXCSR : w MXCSR SSE Control Status Reg */
   164 	{{ OP_W, REG_MXCSG_INDEX }, {0}};		/* ldmxcsr */
   166 static op_implicit_list_t list_leave[] = 
   167 	/* C9 : LEAVE :  rw ESP, w EBP */
   168 	{{ OP_R | OP_W, REG_ESP_INDEX },
   169 	 { OP_W, REG_DWORD_OFFSET + 5 }, {0}};	/* leave */
   171 static op_implicit_list_t list_lgdt[] = 
   172 	/* 0F 01 : LGDT : w GDTR */
   173 	{{ OP_W, REG_GDTR_INDEX }, {0}};		/* lgdt */
   175 static op_implicit_list_t list_lidt[] = 
   176 	/* 0F 01 : LIDT : w IDTR */
   177 	{{ OP_W, REG_IDTR_INDEX }, {0}};		/* lidt */
   179 static op_implicit_list_t list_lldt[] = 
   180 	/* 0F 00 : LLDT : w LDTR */
   181 	{{ OP_W, REG_LDTR_INDEX }, {0}};		/* lldt */
   183 static op_implicit_list_t list_lmsw[] = 
   184 	/* 0F 01 : LMSW : w CR0 */
   185 	{{ OP_W, REG_CTRL_OFFSET }, {0}};		/* lmsw */
   187 static op_implicit_list_t list_loop[] = 
   188 	/* E0, E1, E2 : LOOP : rw ECX */
   189 	{{ OP_R | OP_W, REG_DWORD_OFFSET + 1 }, {0}};/* loop */
   191 static op_implicit_list_t list_ltr[] = 
   192 	/* 0F 00 : LTR : w Task Register */
   193 	{{ OP_W, REG_TR_INDEX }, {0}};		/* ltr */
   195 static op_implicit_list_t list_pop[] = 
   196 	/* 8F, 58, 1F, 07, 17, 0F A1, 0F A9 : POP : rw ESP */
   197 	/* FF, 50, 6A, 68, 0E, 16, 1E, 06, 0F A0, 0F A8 : PUSH : rw ESP */
   198 	{{ OP_R | OP_W, REG_ESP_INDEX }, {0}};	/* pop, push */
   200 static op_implicit_list_t list_popad[] = 
   201 	/* 61 : POPAD : rw esp, w edi esi ebp ebx edx ecx eax */
   202 	{{ OP_R | OP_W, REG_ESP_INDEX },
   203 	 { OP_W, REG_DWORD_OFFSET + 7 },
   204 	 { OP_W, REG_DWORD_OFFSET + 6 },
   205 	 { OP_W, REG_DWORD_OFFSET + 5 },
   206 	 { OP_W, REG_DWORD_OFFSET + 3 },
   207 	 { OP_W, REG_DWORD_OFFSET + 2 },
   208 	 { OP_W, REG_DWORD_OFFSET + 1 },
   209 	 { OP_W, REG_DWORD_OFFSET }, {0}};		/* popad */
   211 static op_implicit_list_t list_popfd[] = 
   212 	/* 9D : POPFD : rw esp, w eflags */
   213 	{{ OP_R | OP_W, REG_ESP_INDEX },
   214 	 { OP_W, REG_FLAGS_INDEX }, {0}};		/* popfd */
   216 static op_implicit_list_t list_pushad[] = 
   217 	/* FF, 50, 6A, 68, 0E, 16, 1E, 06, 0F A0, 0F A8 : PUSH : rw ESP */
   218 	/* 60 : PUSHAD : rw esp, r eax ecx edx ebx esp ebp esi edi */
   219 	{{ OP_R | OP_W, REG_ESP_INDEX },
   220 	 { OP_R, REG_DWORD_OFFSET },
   221 	 { OP_R, REG_DWORD_OFFSET + 1 },
   222 	 { OP_R, REG_DWORD_OFFSET + 2 },
   223 	 { OP_R, REG_DWORD_OFFSET + 3 },
   224 	 { OP_R, REG_DWORD_OFFSET + 5 },
   225 	 { OP_R, REG_DWORD_OFFSET + 6 },
   226 	 { OP_R, REG_DWORD_OFFSET + 7 }, {0}};	/* pushad */
   228 static op_implicit_list_t list_pushfd[] = 
   229 	/* 9C : PUSHFD : rw esp, r eflags */
   230 	{{ OP_R | OP_W, REG_ESP_INDEX },
   231 	 { OP_R, REG_FLAGS_INDEX }, {0}};		/* pushfd */
   233 static op_implicit_list_t list_rdmsr[] = 
   234 	/* 0F 32 : RDMSR : r ECX, w EDX, w EAX */
   235 	{{ OP_R, REG_DWORD_OFFSET + 1 },
   236 	 { OP_W, REG_DWORD_OFFSET + 2 },
   237 	 { OP_W, REG_DWORD_OFFSET }, {0}};	/* rdmsr */
   239 static op_implicit_list_t list_rdpmc[] = 
   240 	/* 0F 33 : RDPMC : r ECX, w EDX, w EAX */
   241 	{{ OP_R, REG_DWORD_OFFSET + 1 },
   242 	 { OP_W, REG_DWORD_OFFSET + 2 },
   243 	 { OP_W, REG_DWORD_OFFSET }, {0}};		/* rdpmc */
   245 static op_implicit_list_t list_rdtsc[] = 
   246 	/* 0F 31 : RDTSC : rw EDX, rw EAX */
   247 	{{ OP_R | OP_W, REG_DWORD_OFFSET + 2 },
   248 	 { OP_R | OP_W, REG_DWORD_OFFSET }, {0}};	/* rdtsc */
   250 static op_implicit_list_t list_rep[] = 
   251 	/* F3, F2 ... : REP : rw ECX */
   252 	{{ OP_R | OP_W, REG_DWORD_OFFSET + 1 }, {0}};/* rep */
   254 static op_implicit_list_t list_rsm[] = 
   255 	/* 0F AA : RSM : r CR4, r CR0 */
   256 	{{ OP_R, REG_CTRL_OFFSET + 4 }, 
   257 	 { OP_R, REG_CTRL_OFFSET }, {0}};		/* rsm */
   259 static op_implicit_list_t list_sahf[] = 
   260 	/* 9E : SAHF : r ah, rw eflags (set SF ZF AF PF CF) */
   261 	{{ OP_R, REG_DWORD_OFFSET }, {0}};		/* sahf */
   263 static op_implicit_list_t list_sgdt[] = 
   264 	/* 0F : SGDT : r gdtr */
   265 	/* TODO: finish this! */
   266 	{{ OP_R, REG_DWORD_OFFSET }, {0}};		/* sgdt */
   268 static op_implicit_list_t list_sidt[] = 
   269 	/* 0F : SIDT : r idtr */
   270 	/* TODO: finish this! */
   271 	{{ OP_R, REG_DWORD_OFFSET }, {0}};		/* sidt */
   273 static op_implicit_list_t list_sldt[] = 
   274 	/* 0F : SLDT : r ldtr */
   275 	/* TODO: finish this! */
   276 	{{ OP_R, REG_DWORD_OFFSET }, {0}};		/* sldt */
   278 static op_implicit_list_t list_smsw[] = 
   279 	/* 0F : SMSW : r CR0 */
   280 	/* TODO: finish this! */
   281 	{{ OP_R, REG_DWORD_OFFSET }, {0}};		/* smsw */
   283 static op_implicit_list_t list_stmxcsr[] = 
   284 	/* 0F AE : STMXCSR : r MXCSR */
   285 	/* TODO: finish this! */
   286 	{{ OP_R, REG_DWORD_OFFSET }, {0}};		/* stmxcsr */
   288 static op_implicit_list_t list_str[] = 
   289 	/* 0F 00 : STR : r TR (task register) */
   290 	/* TODO: finish this! */
   291 	{{ OP_R, REG_DWORD_OFFSET }, {0}};		/* str */
   293 static op_implicit_list_t list_sysenter[] = 
   294 	/* 0F 34 : SYSENTER : w cs, w eip, w ss, w esp, r CR0, w eflags
   295 	 *         r sysenter_cs_msr, sysenter_esp_msr, sysenter_eip_msr */
   296 	/* TODO: finish this! */
   297 	{{ OP_R, REG_DWORD_OFFSET }, {0}};		/* sysenter */
   299 static op_implicit_list_t list_sysexit[] = 
   300 	/* 0F 35 : SYSEXIT : r edx, r ecx, w cs, w eip, w ss, w esp
   301 	 * 	   r sysenter_cs_msr */
   302 	/* TODO: finish this! */
   303 	{{ OP_R, REG_DWORD_OFFSET }, {0}};		/* sysexit */
   305 static op_implicit_list_t list_wrmsr[] = 
   306 	/* 0F 30 : WRMST : r edx, r eax, r ecx */
   307 	/* TODO: finish this! */
   308 	{{ OP_R, REG_DWORD_OFFSET }, {0}};		/* wrmsr */
   310 static op_implicit_list_t list_xlat[] = 
   311 	/* D7 : XLAT : rw al r ebx (ptr) */
   312 	/* TODO: finish this! */
   313 	{{ OP_R, REG_DWORD_OFFSET }, {0}};		/* xlat */
   314 /* TODO:
   315  * monitor 0f 01 c8 eax OP_R ecx OP_R edx OP_R
   316  * mwait 0f 01 c9 eax OP_R ecx OP_R
   317  */
   318 static op_implicit_list_t list_monitor[] = 
   319 	{{ OP_R, REG_DWORD_OFFSET }, {0}};		/* monitor */
   320 static op_implicit_list_t list_mwait[] = 
   321 	{{ OP_R, REG_DWORD_OFFSET }, {0}};		/* mwait */
   323 op_implicit_list_t *op_implicit_list[] = {
   324 	/* This is a list of implicit operands which are read/written by
   325 	 * various x86 instructions. Note that modifications to the stack
   326 	 * register are mentioned here, but that additional information on
   327 	 * the effect an instruction has on the stack is contained in the
   328 	 * x86_insn_t 'stack_mod' and 'stack_mod_val' fields. Use of the
   329 	 * eflags register, i.e. setting, clearing, and testing flags, is
   330 	 * not recorded here but rather in the flags_set and flags_tested
   331 	 * fields of the x86_insn_t.*/
   332 	NULL,
   333 	list_aaa, list_aad, list_call, list_cbw,		/* 1 - 4 */
   334 	list_cwde, list_clts, list_cmpxchg, list_cmpxchgb,	/* 5 - 8 */
   335 	list_cmpxchg8b, list_cpuid, list_cwd, list_daa,		/* 9 - 12 */
   336 	list_idiv, list_div, list_enter, list_f2xm1,		/* 13 - 16 */
   337 	list_fcom, list_fpatan, list_fprem, list_faddp,		/* 17 - 20 */
   338 	list_fucompp, list_imul, list_mul, list_lahf,		/* 21 - 24 */
   339 	list_ldmxcsr, list_leave, list_lgdt, list_lidt,		/* 25 - 28 */
   340 	list_lldt, list_lmsw, list_loop, list_ltr,		/* 29 - 32 */
   341 	list_pop, list_popad, list_popfd, list_pushad,		/* 33 - 36 */
   342 	list_pushfd, list_rdmsr, list_rdpmc, list_rdtsc,	/* 37 - 40 */
   343 	/* NOTE: 'REP' is a hack since it is a prefix: if its position
   344 	 * in the table changes, then change IDX_IMPLICIT_REP in the .h */
   345 	list_rep, list_rsm, list_sahf, list_sgdt,		/* 41 - 44 */
   346 	list_sidt, list_sldt, list_smsw, list_stmxcsr,		/* 45 - 48 */
   347 	list_str, list_sysenter, list_sysexit, list_wrmsr,	/* 49 - 52 */
   348 	list_xlat, list_monitor, list_mwait,			/* 53 - 55*/
   349 	NULL						/* end of list */
   350  };
   352 #define LAST_IMPL_IDX 55
   354 static void handle_impl_reg( x86_op_t *op, uint32_t val ) {
   355 	x86_reg_t *reg = &op->data.reg;
   356 	op->type = op_register;
   357 	ia32_handle_register( reg, (unsigned int) val );
   358 	switch (reg->size) {
   359 		case 1:
   360 			op->datatype = op_byte; break;
   361 		case 2:
   362 			op->datatype = op_word; break;
   363 		case 4:
   364 			op->datatype = op_dword; break;
   365 		case 8:
   366 			op->datatype = op_qword; break;
   367 		case 10:
   368 			op->datatype = op_extreal; break;
   369 		case 16:
   370 			op->datatype = op_dqword; break;
   371 	}
   372 	return;
   373 }
   375 /* 'impl_idx' is the value from the opcode table: between 1 and LAST_IMPL_IDX */
   376 /* returns number of operands added */
   377 unsigned int ia32_insn_implicit_ops( x86_insn_t *insn, unsigned int impl_idx ) {
   378 	op_implicit_list_t *list;
   379 	x86_op_t *op;
   380 	unsigned int num = 0;
   382 	if (! impl_idx || impl_idx > LAST_IMPL_IDX ) {
   383 		return 0;
   384 	}
   386 	for ( list = op_implicit_list[impl_idx]; list->type; list++, num++ ) {
   387 		enum x86_op_access access = (enum x86_op_access) OP_PERM(list->type);
   388 		enum x86_op_flags  flags  = (enum x86_op_flags) (OP_FLAGS(list->type) >> 12);
   390 		op = NULL;
   391 		/* In some cases (MUL), EAX is an implicit operand hardcoded in
   392                  * the instruction without being explicitly listed in assembly.
   393                  * For this situation, find the hardcoded operand and add the
   394                  * implied flag rather than adding a new implicit operand. */
   395 		x86_oplist_t * existing;
   396 		if (ia32_true_register_id(list->operand) == REG_DWORD_OFFSET) {
   397 			for ( existing = insn->operands; existing; existing = existing->next ) {
   398 				if (existing->op.type == op_register &&
   399 	                            existing->op.data.reg.id == list->operand) {
   400 					op = &existing->op;
   401 					break;
   402 				}
   403 			}
   404 		}
   405 		if (!op) {
   406 			op = x86_operand_new( insn );
   407 			/* all implicit operands are registers */
   408 			handle_impl_reg( op, list->operand );
   409 			/* decrement the 'explicit count' incremented by default in
   410 			 * x86_operand_new */
   411 			insn->explicit_count = insn->explicit_count -1;
   412 		}
   413 		if (!op) {
   414 			return num;	/* gah! return early */
   415 		}
   416 		op->access |= access;
   417 		op->flags |= flags;
   418 		op->flags |= op_implied;
   419 	}
   421 	return num;
   422 }

mercurial