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