1 : /*
2 : * Copyright (c) 2012 The Native Client Authors. All rights reserved.
3 : * Use of this source code is governed by a BSD-style license that can be
4 : * found in the LICENSE file.
5 : */
6 :
7 : /*
8 : * Translates the recognized opcode (instruction) in the instruction state
9 : * into an opcode expression.
10 : */
11 :
12 : #include "native_client/src/trusted/validator/x86/decoder/nc_inst_trans.h"
13 :
14 : #include <stdio.h>
15 : #include <assert.h>
16 :
17 : #include "native_client/src/shared/platform/nacl_check.h"
18 : #include "native_client/src/shared/platform/nacl_log.h"
19 : #include "native_client/src/trusted/validator/x86/decoder/nc_inst_state.h"
20 : #include "native_client/src/trusted/validator/x86/decoder/nc_inst_state_internal.h"
21 : #include "native_client/src/trusted/validator/x86/decoder/ncop_exps.h"
22 : #include "native_client/src/trusted/validator/x86/nacl_regs.h"
23 :
24 : #include "native_client/src/trusted/validator/x86/decoder/ncop_exps_inl.c"
25 : #include "native_client/src/trusted/validator/x86/decoder/ncopcode_desc_inl.c"
26 : #include "native_client/src/trusted/validator/x86/x86_insts_inl.c"
27 :
28 : #if NACL_TARGET_SUBARCH == 64
29 : # include "native_client/src/trusted/validator/x86/decoder/gen/nc_subregs_64.h"
30 : #else
31 : # include "native_client/src/trusted/validator/x86/decoder/gen/nc_subregs_32.h"
32 : #endif
33 :
34 : /* To turn on debugging of instruction decoding, change value of
35 : * DEBUGGING to 1.
36 : */
37 : #define DEBUGGING 0
38 :
39 : #include "native_client/src/shared/utils/debugging.h"
40 :
41 : /* Return the segment register to use, based on prefix specification,
42 : * or reg_default if no prefix specified.
43 : */
44 : static NaClOpKind NaClGetSegmentPrefixReg(NaClInstState* state,
45 357 : NaClOpKind reg_default) {
46 : /* Note: We need to find the LAST segment prefix byte, since it overrides
47 : * other segment prefix bytes, if multiple segment prefixes are specified.
48 : */
49 : if (32 == NACL_TARGET_SUBARCH) {
50 357 : if (state->prefix_mask &
51 : (kPrefixSEGCS | kPrefixSEGSS | kPrefixSEGFS |
52 : kPrefixSEGGS | kPrefixSEGES | kPrefixSEGDS)) {
53 : int i;
54 14 : for (i = state->num_prefix_bytes - 1; (i >= 0); --i) {
55 14 : switch (state->bytes.byte[i]) {
56 : case kValueSEGCS:
57 0 : return RegCS;
58 : case kValueSEGSS:
59 0 : return RegSS;
60 : case kValueSEGFS:
61 4 : return RegFS;
62 : case kValueSEGGS:
63 6 : return RegGS;
64 : case kValueSEGES:
65 0 : return RegES;
66 : case kValueSEGDS:
67 0 : return RegDS;
68 : default:
69 : break;
70 : }
71 : }
72 : }
73 : } else if (state->prefix_mask &
74 : /* Only GS and FS matter in 64-bit mode. */
75 : (kPrefixSEGGS | kPrefixSEGFS)) {
76 : int i;
77 : for (i = state->num_prefix_bytes - 1; (i >= 0); --i) {
78 : /* for (i = 0; i < state->num_prefix_bytes; ++i) { */
79 : switch (state->bytes.byte[i]) {
80 : case kValueSEGFS:
81 : return RegFS;
82 : case kValueSEGGS:
83 : return RegGS;
84 : default:
85 : break;
86 : }
87 : }
88 : }
89 347 : return reg_default;
90 : }
91 :
92 : /* Return the segment register to use if DS is the default. */
93 148 : static INLINE NaClOpKind NaClGetDsSegmentReg(NaClInstState* state) {
94 148 : return NaClGetSegmentPrefixReg(state, RegDS);
95 : }
96 :
97 : /* Return the segment register to use if ES is the default. */
98 0 : static INLINE NaClOpKind NaClGetEsSegmentReg(NaClInstState* state) {
99 0 : return NaClGetSegmentPrefixReg(state, RegES);
100 : }
101 :
102 : /* Append the given expression node onto the given vector of expression
103 : * nodes. Returns the appended expression node.
104 : */
105 : static INLINE NaClExp* NaClAppendExp(NaClExpKind kind,
106 : uint64_t value,
107 : NaClExpFlags flags,
108 2692 : NaClExpVector* vector) {
109 : NaClExp* node;
110 2692 : assert(vector->number_expr_nodes < NACL_MAX_EXPS);
111 : /* If this is not a register expression, we should have specified a size. */
112 2692 : CHECK(ExprRegister == kind || (0 != (flags & (NACL_EFLAG(ExprSize8) |
113 : NACL_EFLAG(ExprSize16) |
114 : NACL_EFLAG(ExprSize32) |
115 : NACL_EFLAG(ExprSize64)))));
116 2692 : node = &vector->node[vector->number_expr_nodes++];
117 2692 : node->kind = kind;
118 2692 : node->value = value;
119 2692 : node->flags = flags;
120 2692 : return node;
121 : }
122 :
123 : /* Report the given message and quit because we don't know
124 : * how to recover.
125 : */
126 0 : static void NaClLost(const char* message) {
127 0 : NaClLog(LOG_ERROR, "FATAL: %s\n", message);
128 0 : exit(1);
129 : }
130 :
131 : /* An untranslateable error has been found. report and quit.
132 : * Use the state to give useful information on where the
133 : * translator was when the error occurred.
134 : * Note: returns NULL of type NaClExp* so that callers can
135 : * make control flow happy, for those cases where the compiler
136 : * doesn't recognize that this function never returns.
137 : */
138 : static NaClExp* NaClFatal(const char* message,
139 0 : NaClInstState* state) {
140 0 : NaClLog(LOG_ERROR,
141 : "FATAL: At %"NACL_PRIxNaClPcAddress", unable to translate: %s\n",
142 : NaClInstStatePrintableAddress(state), message);
143 0 : exit(1);
144 : /* NOT REACHED */
145 : return NULL;
146 : }
147 :
148 : /* Returns the segment register encoded in the corresponding
149 : * mnemonic name of the corresponding instruction.
150 : */
151 0 : static NaClOpKind NaClGetMnemonicSegmentRegister(NaClInstState* state) {
152 0 : const NaClInst* inst = NaClInstStateInst(state);
153 0 : switch (inst->name) {
154 : case InstLds:
155 0 : return RegDS;
156 : case InstLes:
157 0 : return RegES;
158 : case InstLfs:
159 0 : return RegFS;
160 : case InstLgs:
161 0 : return RegGS;
162 : case InstLss:
163 0 : return RegSS;
164 : default:
165 : break;
166 : }
167 0 : NaClFatal("Unable to determine segment regsiter from instruction name",
168 : state);
169 : /* NOT REACHED */
170 0 : return RegUnknown;
171 : }
172 :
173 : /* Append that we don't bother to translate the instruction argument,
174 : * since it is NaCl illegal. Used to handle cases where we don't implement
175 : * 16-bit modrm effective addresses.
176 : */
177 3 : static INLINE NaClExp* NaClAppendNaClIllegal(NaClInstState* state) {
178 3 : return NaClAppendExp(ExprNaClIllegal, 0,
179 : NACL_EFLAG(ExprSize16), &state->nodes);
180 : }
181 :
182 : /* Append the given constant onto the given vector of expression
183 : * nodes. Returns the appended expression node.
184 : */
185 : static INLINE NaClExp* NaClAppendConst(uint64_t value, NaClExpFlags flags,
186 538 : NaClExpVector* vector) {
187 : DEBUG(
188 : NaClLog(LOG_INFO, "Append constant %"NACL_PRIx64" : ", value);
189 : NaClPrintExpFlags(NaClLogGetGio(), flags);
190 : gprintf(NaClLogGetGio(), "\n"));
191 538 : return NaClAppendExp(ExprConstant, value, flags, vector);
192 : }
193 :
194 : /* Define a type corresponding to the arrays NaClRegTable8,
195 : * NaClRegTable16, NaClRegTable32, and NaClRegTable64.
196 : */
197 : typedef const NaClOpKind NaClRegTableGroup[NACL_REG_TABLE_SIZE];
198 :
199 0 : NaClOpKind NaClGet64For32BitReg(NaClOpKind reg32) {
200 : #if NACL_TARGET_SUBARCH == 64
201 : int i;
202 : for (i = 0; i < NACL_REG_TABLE_SIZE; ++i) {
203 : if (reg32 == NaClRegTable32[i]) {
204 : return NaClRegTable64[i];
205 : }
206 : }
207 : #endif
208 0 : return RegUnknown;
209 : }
210 :
211 0 : NaClOpKind NaClGet32For64BitReg(NaClOpKind reg64) {
212 0 : int index = NaClGpReg64Index[reg64];
213 0 : return (index == NACL_REGISTER_UNDEFINED)
214 : ? RegUnknown
215 : : NaClRegTable32[index];
216 : }
217 :
218 : Bool NaClIs64Subreg(NaClInstState* state,
219 0 : NaClOpKind subreg, NaClOpKind reg64) {
220 0 : int index = NaClGpSubregIndex[subreg];
221 0 : if (index == NACL_REGISTER_UNDEFINED) {
222 0 : return FALSE;
223 : } else {
224 0 : int index64 = NaClGpReg64Index[reg64];
225 0 : if (index64 == NACL_REGISTER_UNDEFINED) {
226 : /* This shouldn't happen, so fail! */
227 0 : return FALSE;
228 : } else {
229 0 : return index == index64;
230 : }
231 : }
232 : }
233 :
234 0 : Bool NaClIs32To64RegPair(NaClOpKind reg32, NaClOpKind reg64) {
235 0 : return reg64 == NaClGet64For32BitReg(reg32);
236 : }
237 :
238 : /* Define the set of available registers, categorized by size.
239 : * Note: The order is important, and is based on the indexing values used
240 : * in the ModRm and SIB bytes (and the REX prefix if appropriate).
241 : */
242 : static NaClRegTableGroup* const NaClRegTable[] = {
243 : &NaClRegTable8NoRex,
244 : &NaClRegTable16,
245 : &NaClRegTable32,
246 : &NaClRegTable64,
247 : &NaClRegTableMmx,
248 : &NaClRegTableXmm,
249 : &NaClRegTableC,
250 : &NaClRegTableD,
251 : };
252 :
253 : /* Define possible register categories. */
254 : typedef enum NaClRegKind {
255 : /* Note: the following all have register tables
256 : * for the corresponding general purpose registers.
257 : */
258 : RegSize8,
259 : RegSize16,
260 : RegSize32,
261 : RegSize64,
262 : RegMMX,
263 : RegXMM,
264 : RegC,
265 : RegD,
266 : /* Note: sizes below this point don't define general
267 : * purpose registers, and hence, don't have a lookup
268 : * value in the register tables.
269 : */
270 : RegSize128,
271 : RegSizeZ,
272 : RegUndefined, /* Always returns RegUnknown. */
273 : } NaClRegKind;
274 :
275 : static const char* const g_NaClRegKindName[] = {
276 : "RegSize8",
277 : "RegSize16",
278 : "RegSize32",
279 : "RegSize64",
280 : "RegMMX",
281 : "RegXMM",
282 : "RegC",
283 : "RegD",
284 : "RegSize128",
285 : "RegSizeZ",
286 : "RegUndefined"
287 : };
288 :
289 0 : const char* NaClRegKindName(NaClRegKind kind) {
290 0 : return g_NaClRegKindName[kind];
291 : }
292 :
293 : /* Define ModRm register categories. */
294 : typedef enum NaClModRmRegKind {
295 : ModRmGeneral,
296 : ModRmMmx,
297 : ModRmXmm,
298 : ModRmCreg,
299 : ModRmDreg,
300 : /* Don't allow top level registers in Effective address. */
301 : ModRmNoTopLevelRegisters
302 : } NaClModRmRegKind;
303 :
304 : static const char* const g_NaClModRmRegKindName[] = {
305 : "ModRmGeneral",
306 : "ModRmMmx",
307 : "ModRmXmm",
308 : "ModRmCreg",
309 : "ModRmDreg",
310 : "ModRmNoTopLevelRegisters"
311 : };
312 :
313 : /* Given an operand kind, return the size specification associated with
314 : * the operand kind.
315 : */
316 245 : static NaClRegKind NaClGetOpKindRegKind(NaClOpKind kind) {
317 245 : switch (kind) {
318 : case Eb_Operand:
319 : case Gb_Operand:
320 : case Ib_Operand:
321 : case Jb_Operand:
322 : case Mb_Operand:
323 : case Ob_Operand:
324 0 : return RegSize8;
325 : case Aw_Operand:
326 : case Ew_Operand:
327 : case Gw_Operand:
328 : case Iw_Operand:
329 : case Jw_Operand:
330 : case Mw_Operand:
331 : case Mpw_Operand:
332 : case Ow_Operand:
333 0 : return RegSize16;
334 : case Av_Operand:
335 : case Ev_Operand:
336 : case Gv_Operand:
337 : case Iv_Operand:
338 : case Jv_Operand:
339 : case Mv_Operand:
340 : case Mpv_Operand:
341 : case Ov_Operand:
342 : case Mmx_Gd_Operand:
343 0 : return RegSize32;
344 : case Ao_Operand:
345 : case Eo_Operand:
346 : case Go_Operand:
347 : case Io_Operand:
348 : case Mo_Operand:
349 : case Mpo_Operand:
350 : case Oo_Operand:
351 : case Xmm_Eo_Operand:
352 : case Xmm_Go_Operand:
353 : case Mmx_E_Operand:
354 : case Mmx_G_Operand:
355 0 : return RegSize64;
356 : case Edq_Operand:
357 : case Gdq_Operand:
358 : case Mdq_Operand:
359 : case Xmm_E_Operand:
360 : case Xmm_G_Operand:
361 0 : return RegSize128;
362 : case Seg_G_Operand:
363 0 : return RegSizeZ;
364 : default:
365 245 : return RegUndefined;
366 : }
367 : }
368 :
369 : static NaClOpKind NaClLookupReg(NaClInstState* state,
370 495 : NaClRegKind kind, int reg_index) {
371 : DEBUG(NaClLog(LOG_INFO,
372 : "Lookup register (rex=%"NACL_PRIx8") %s:%d\n",
373 : state->rexprefix, NaClRegKindName(kind), reg_index));
374 495 : if (32 == NACL_TARGET_SUBARCH && kind == RegSize64) {
375 0 : NaClLost("Architecture doesn't define 64 bit registers");
376 495 : } else if (RegSize128 <= kind) {
377 0 : return RegUnknown;
378 : }
379 : if (64 == NACL_TARGET_SUBARCH && kind == RegSize8 && state->rexprefix) {
380 : return NaClRegTable8Rex[reg_index];
381 : }
382 495 : return (*(NaClRegTable[kind]))[reg_index];
383 : }
384 :
385 : /* Returns the (NaClExpFlag) size of the given register. */
386 1014 : static NaClExpFlags NaClGetRegSize(NaClOpKind register_name) {
387 1014 : switch (register_name) {
388 : case RegAL:
389 : case RegBL:
390 : case RegCL:
391 : case RegDL:
392 : case RegAH:
393 : case RegBH:
394 : case RegCH:
395 : case RegDH:
396 : case RegDIL:
397 : case RegSIL:
398 : case RegBPL:
399 : case RegSPL:
400 : case RegR8B:
401 : case RegR9B:
402 : case RegR10B:
403 : case RegR11B:
404 : case RegR12B:
405 : case RegR13B:
406 : case RegR14B:
407 : case RegR15B:
408 45 : return NACL_EFLAG(ExprSize8);
409 : case RegAX:
410 : case RegBX:
411 : case RegCX:
412 : case RegDX:
413 : case RegSI:
414 : case RegDI:
415 : case RegBP:
416 : case RegSP:
417 : case RegR8W:
418 : case RegR9W:
419 : case RegR10W:
420 : case RegR11W:
421 : case RegR12W:
422 : case RegR13W:
423 : case RegR14W:
424 : case RegR15W:
425 29 : return NACL_EFLAG(ExprSize16);
426 : case RegEAX:
427 : case RegEBX:
428 : case RegECX:
429 : case RegEDX:
430 : case RegESI:
431 : case RegEDI:
432 : case RegEBP:
433 : case RegESP:
434 : case RegR8D:
435 : case RegR9D:
436 : case RegR10D:
437 : case RegR11D:
438 : case RegR12D:
439 : case RegR13D:
440 : case RegR14D:
441 : case RegR15D:
442 493 : return NACL_EFLAG(ExprSize32);
443 : case RegCS:
444 : case RegDS:
445 : case RegSS:
446 : case RegES:
447 : case RegFS:
448 : case RegGS:
449 199 : return NACL_EFLAG(ExprSize16);
450 : case RegEIP:
451 45 : return NACL_EFLAG(ExprSize32);
452 : case RegRIP:
453 0 : return NACL_EFLAG(ExprSize64);
454 : case RegRAX:
455 : case RegRBX:
456 : case RegRCX:
457 : case RegRDX:
458 : case RegRSI:
459 : case RegRDI:
460 : case RegRBP:
461 : case RegRSP:
462 : case RegR8:
463 : case RegR9:
464 : case RegR10:
465 : case RegR11:
466 : case RegR12:
467 : case RegR13:
468 : case RegR14:
469 : case RegR15:
470 0 : return NACL_EFLAG(ExprSize64);
471 : default:
472 203 : return 0;
473 : }
474 : }
475 :
476 : /* Appends the given kind of register onto the vector of expression nodes.
477 : * Returns the appended register.
478 : */
479 1014 : static INLINE NaClExp* NaClAppendReg(NaClOpKind r, NaClExpVector* vector) {
480 : NaClExp* node;
481 : DEBUG(NaClLog(LOG_INFO, "append register %s\n", NaClOpKindName(r)));
482 1014 : node = NaClAppendExp(ExprRegister, r, NaClGetRegSize(r), vector);
483 1014 : return node;
484 : }
485 :
486 : /* Given the given register kind, and the corresponding index, append
487 : * the appropriate register onto the vector of expression nodes.
488 : * Returns the appended register
489 : */
490 : static INLINE NaClExp* NaClAppendRegKind(NaClInstState* state,
491 251 : NaClRegKind kind, int reg_index) {
492 : DEBUG(NaClLog(LOG_INFO, "NaClAppendRegKind(%d, %d) = %s\n",
493 : (int) kind, reg_index, NaClRegKindName(kind)));
494 251 : return NaClAppendReg(NaClLookupReg(state, kind, reg_index), &state->nodes);
495 : }
496 :
497 : /* Given an operand of the corresponding opcode instruction of the
498 : * given state, return what kind of register should be used, based
499 : * on the operand size.
500 : */
501 : static NaClRegKind NaClExtractOpRegKind(NaClInstState* state,
502 245 : const NaClOp* operand) {
503 245 : NaClRegKind reg_kind = NaClGetOpKindRegKind(operand->kind);
504 245 : switch (reg_kind) {
505 : case RegSize8:
506 : case RegSize16:
507 : case RegSize32:
508 : case RegSize64:
509 0 : return reg_kind;
510 : case RegSizeZ:
511 0 : if (state->operand_size == 2) {
512 0 : return RegSize16;
513 : } else {
514 0 : return RegSize32;
515 : }
516 : default:
517 : /* Size not explicitly defined, pick up from operand size. */
518 245 : if (state->inst->flags & NACL_IFLAG(OperandSize_b)) {
519 32 : return RegSize8;
520 213 : } else if (state->operand_size == 1) {
521 0 : return RegSize8;
522 213 : } else if (state->operand_size == 4) {
523 199 : return RegSize32;
524 14 : } else if (state->operand_size == 2) {
525 14 : return RegSize16;
526 0 : } else if (state->operand_size == 8) {
527 0 : return RegSize64;
528 : } else {
529 0 : return RegSize32;
530 : }
531 : }
532 : }
533 :
534 : /* Given an address of the corresponding opcode instruction of the
535 : * given state, return what kind of register should be used.
536 : */
537 244 : static INLINE NaClRegKind NaClExtractAddressRegKind(NaClInstState* state) {
538 244 : if (state->address_size == 16) {
539 0 : return RegSize16;
540 244 : } else if (state->address_size == 64) {
541 0 : return RegSize64;
542 : } else {
543 244 : return RegSize32;
544 : }
545 : }
546 :
547 : /* Given we want to translate an operand (of the form G_Operand),
548 : * for the given register index, generate the corresponding register
549 : * expression, and append it to the vector of expression nodes.
550 : * Returns the appended register.
551 : */
552 : static NaClExp* NaClAppendOperandReg(
553 : NaClInstState* state,
554 : const NaClOp* operand,
555 : int reg_index,
556 217 : NaClModRmRegKind modrm_reg_kind) {
557 217 : NaClRegKind reg_kind = RegSize32;
558 : DEBUG(NaClLog(LOG_INFO, "modrm_reg_kind = %s\n",
559 : g_NaClModRmRegKindName[modrm_reg_kind]));
560 217 : switch (modrm_reg_kind) {
561 : default:
562 : case ModRmGeneral:
563 211 : reg_kind = NaClExtractOpRegKind(state, operand);
564 211 : break;
565 : case ModRmMmx:
566 0 : reg_kind = RegMMX;
567 0 : break;
568 : case ModRmXmm:
569 6 : reg_kind = RegXMM;
570 6 : break;
571 : case ModRmCreg:
572 0 : reg_kind = RegC;
573 0 : break;
574 : case ModRmDreg:
575 0 : reg_kind = RegD;
576 0 : break;
577 : case ModRmNoTopLevelRegisters:
578 0 : reg_kind = RegUndefined;
579 : }
580 : DEBUG(NaClLog(LOG_INFO, "Translate register %d, %s\n",
581 : reg_index, g_NaClRegKindName[reg_kind]));
582 217 : return NaClAppendRegKind(state, reg_kind, reg_index);
583 : }
584 :
585 : static NaClExpFlags NaClGetAddressExprSizeFlagsForState(NaClInstState* state);
586 :
587 198 : static NaClExp* NaClAppendSegmentAddress(NaClInstState* state) {
588 198 : NaClExpFlags flags = NaClGetAddressExprSizeFlagsForState(state);
589 198 : return NaClAppendExp(ExprSegmentAddress, 0, flags, &state->nodes);
590 : }
591 :
592 : /* Same as NaClAppendOperandReg, except that a segment register is combined with
593 : * the indexed register to define a segment address.
594 : */
595 : static NaClExp* NaClAppendSegmentOpReg(
596 : NaClInstState* state,
597 : const NaClOp* operand,
598 : NaClOpKind seg_register,
599 : int reg_index,
600 0 : NaClModRmRegKind modrm_reg_kind) {
601 0 : NaClExp* results = NaClAppendSegmentAddress(state);
602 0 : NaClAppendReg(seg_register, &state->nodes);
603 0 : NaClAppendOperandReg(state, operand, reg_index, modrm_reg_kind);
604 0 : return results;
605 : }
606 :
607 : /* Returns the corresponding segment register for the given index (0..7) */
608 0 : static NaClExp* NaClAppendModRmSegmentReg(NaClInstState* state) {
609 : static NaClOpKind seg[8] = {
610 : RegES,
611 : RegCS,
612 : RegSS,
613 : RegDS,
614 : RegFS,
615 : RegGS,
616 : /* These should not happen. */
617 : RegUnknown,
618 : RegUnknown
619 : };
620 0 : return NaClAppendReg(seg[modrm_regInline(state->modrm)], &state->nodes);
621 : }
622 :
623 : /* For the given instruction state, and the corresponding 3-bit specification
624 : * of a register, update it to a 4-bit specification, based on the REX.R bit.
625 : */
626 167 : static INLINE int NaClGetRexRReg(NaClInstState* state, int reg) {
627 : DEBUG(NaClLog(LOG_INFO, "Get GenRexRRegister %d\n", reg));
628 : if (NACL_TARGET_SUBARCH == 64 && (state->rexprefix & 0x4)) {
629 : reg += 8;
630 : }
631 167 : return reg;
632 : }
633 :
634 : /* For the given instruction state, and the corresponding 3-bit specification
635 : * of a register, update it to a 4-bit specification, based on the REX.X bit.
636 : */
637 65 : static INLINE int NaClGetRexXReg(NaClInstState* state, int reg) {
638 : DEBUG(NaClLog(LOG_INFO, "Get GenRexXRegister\n"));
639 : if (NACL_TARGET_SUBARCH == 64 && (state->rexprefix & 0x2)) {
640 : reg += 8;
641 : }
642 65 : return reg;
643 : }
644 :
645 : /* For the given instruction state, and the corresponding 3-bit specification
646 : * of a register, update it to a 4-bit specification, based on the REX.B bit.
647 : */
648 263 : static INLINE int NaClGetRexBReg(NaClInstState* state, int reg) {
649 : DEBUG(NaClLog(LOG_INFO, "Get GenRexBRegister\n"));
650 : if (NACL_TARGET_SUBARCH == 64 && (state->rexprefix & 0x1)) {
651 : DEBUG(NaClLog(LOG_INFO, "rexprefix == %02x\n", state->rexprefix));
652 : reg += 8;
653 : }
654 263 : return reg;
655 : }
656 :
657 : /* Return the general purpose register associated with the modrm.reg
658 : * field.
659 : */
660 167 : static INLINE int NaClGetGenRegRegister(NaClInstState* state) {
661 : DEBUG(NaClLog(LOG_INFO, "Get GenRegRegister\n"));
662 167 : return NaClGetRexRReg(state, modrm_regInline(state->modrm));
663 : }
664 :
665 : /* Return the general purpose register associated with the modrm.rm
666 : * field.
667 : */
668 174 : static INLINE int NaClGetGenRmRegister(NaClInstState* state) {
669 : DEBUG(NaClLog(LOG_INFO, "Get GenRmRegister\n"));
670 174 : return NaClGetRexBReg(state, modrm_rmInline(state->modrm));
671 : }
672 :
673 : /* Get the register index from the difference of the opcode, and
674 : * its opcode base.
675 : */
676 : static NaClExp* NaClAppendOpcodeBaseReg(
677 34 : NaClInstState* state, const NaClOp* operand) {
678 : int reg_index;
679 34 : reg_index = NaClGetOpcodePlusR(state->inst->opcode_ext);
680 34 : assert(reg_index >= 0 && reg_index < 8);
681 : DEBUG(NaClLog(LOG_INFO, "Translate opcode base register %d\n", reg_index));
682 34 : return NaClAppendRegKind(state, NaClExtractOpRegKind(state, operand),
683 : NaClGetRexBReg(state, reg_index));
684 : }
685 :
686 : /* Get the ST register defined from the difference of the opcode, and
687 : * its opcode base.
688 : */
689 0 : static NaClExp* NaClAppendStOpcodeBaseReg(NaClInstState* state) {
690 : int reg_index;
691 0 : reg_index = NaClGetOpcodePlusR(state->inst->opcode_ext);
692 0 : assert(reg_index >= 0 && reg_index < 8);
693 : DEBUG(NaClLog(LOG_INFO, "Translate opcode base register %d\n", reg_index));
694 0 : return NaClAppendReg(RegST0 + reg_index, &state->nodes);
695 : }
696 :
697 : /* Model the extraction of a displacement value and the associated flags. */
698 : typedef struct NaClDisplacement {
699 : uint64_t value;
700 : NaClExpFlags flags;
701 : } NaClDisplacement;
702 :
703 : static INLINE void NaClInitializeDisplacement(
704 : uint64_t value, NaClExpFlags flags,
705 117 : NaClDisplacement* displacement) {
706 117 : displacement->value = value;
707 117 : displacement->flags = flags;
708 117 : }
709 :
710 : /* Extract the binary value from the specified bytes of the instruction. */
711 : static uint64_t NaClExtractUnsignedBinaryValue(NaClInstState* state,
712 217 : int start_byte, int num_bytes) {
713 : int i;
714 217 : uint64_t value = 0;
715 709 : for (i = 0; i < num_bytes; ++i) {
716 492 : uint8_t byte = state->bytes.byte[start_byte + i];
717 492 : value += (((uint64_t) byte) << (i * 8));
718 : }
719 217 : return value;
720 : }
721 :
722 : static int64_t NaClExtractSignedBinaryValue(NaClInstState* state,
723 37 : int start_byte, int num_bytes) {
724 : /* Assumes little endian. */
725 37 : uint8_t* address = &state->bytes.byte[start_byte];
726 37 : switch (num_bytes) {
727 : case 1:
728 18 : return *(int8_t*) address;
729 : case 2:
730 0 : return *(int16_t*) address;
731 : case 4:
732 19 : return *(int32_t*) address;
733 : default:
734 0 : CHECK(0);
735 0 : return -1;
736 : }
737 : }
738 :
739 : /* Given the number of bytes for a literal constant, return the corresponding
740 : * expr node flags that represent the value of the parsed bytes.
741 : */
742 661 : static NaClExpFlags NaClGetExprSizeFlagForBytes(uint8_t num_bytes) {
743 661 : switch (num_bytes) {
744 : /* HACK a zero size immediate is generated for some addr16 instructions.
745 : * We don't allow these instructions, but we do test decompiling them.
746 : * TODO(ncbray) eliminate the bug or the test case.
747 : */
748 : case 0:
749 : case 1:
750 136 : return NACL_EFLAG(ExprSize8);
751 : case 2:
752 11 : return NACL_EFLAG(ExprSize16);
753 : case 4:
754 514 : return NACL_EFLAG(ExprSize32);
755 : case 8:
756 0 : return NACL_EFLAG(ExprSize64);
757 : default:
758 0 : CHECK(0);
759 0 : return 0;
760 : }
761 : }
762 :
763 : /* Return the expr flag for the address size associated with the state. */
764 407 : static NaClExpFlags NaClGetAddressExprSizeFlagsForState(NaClInstState* state) {
765 407 : uint8_t size = NaClInstStateAddressSize(state);
766 407 : return NaClGetExprSizeFlagForBytes(size / 8);
767 : }
768 :
769 : /* Given the corresponding instruction state, return the
770 : * corresponding displacement value, and any expression node
771 : * flags that should be associated with the displacement value.
772 : */
773 : static void NaClExtractDisplacement(NaClInstState* state,
774 : NaClDisplacement* displacement,
775 118 : NaClExpFlags flags) {
776 : DEBUG(NaClLog(LOG_INFO, "-> Extract displacement, flags = ");
777 : NaClPrintExpFlags(NaClLogGetGio(), flags);
778 : gprintf(NaClLogGetGio(), "\n"));
779 : /* First compute the displacement value. */
780 118 : displacement->value = NaClExtractUnsignedBinaryValue(state,
781 : state->first_disp_byte,
782 : state->num_disp_bytes);
783 :
784 : /* Now compute any appropriate flags to be associated with the value. */
785 118 : displacement->flags = flags |
786 : NaClGetExprSizeFlagForBytes(state->num_disp_bytes);
787 : DEBUG(NaClLog(LOG_INFO,
788 : "<- value = %"NACL_PRIx64", flags = ", displacement->value);
789 : NaClPrintExpFlags(NaClLogGetGio(), displacement->flags);
790 : gprintf(NaClLogGetGio(), "\n"));
791 118 : }
792 :
793 : /* Append the displacement value of the given instruction state
794 : * onto the vector of expression nodes. Returns the appended displacement
795 : * value.
796 : */
797 4 : static NaClExp* NaClAppendDisplacement(NaClInstState* state) {
798 : NaClDisplacement displacement;
799 : DEBUG(NaClLog(LOG_INFO, "append displacement\n"));
800 4 : NaClExtractDisplacement(state, &displacement, NACL_EFLAG(ExprSignedHex));
801 4 : return NaClAppendConst(displacement.value, displacement.flags, &state->nodes);
802 : }
803 :
804 : /* Get the binary value denoted by the immediate bytes of the state. */
805 99 : static uint64_t NaClExtractUnsignedImmediate(NaClInstState* state) {
806 99 : return NaClExtractUnsignedBinaryValue(state,
807 : state->first_imm_byte,
808 : state->num_imm_bytes);
809 : }
810 :
811 : /* Get the binary value denoted by the 2nd immediate bytes of the state. */
812 0 : static uint64_t NaClExtractUnsignedImmediate2(NaClInstState* state) {
813 0 : return NaClExtractUnsignedBinaryValue(
814 : state,
815 : state->first_imm_byte + state->num_imm_bytes,
816 : state->num_imm2_bytes);
817 : }
818 :
819 : /* Get the binary value denoted by the immediate bytes of the state. */
820 37 : static int64_t NaClExtractSignedImmediate(NaClInstState* state) {
821 37 : return NaClExtractSignedBinaryValue(state,
822 : state->first_imm_byte,
823 : state->num_imm_bytes);
824 : }
825 :
826 : /* Append the immediate value of the given instruction state onto
827 : * The vector of expression nodes. Returns the appended immediate value.
828 : */
829 79 : static NaClExp* NaClAppendImmed(NaClInstState* state) {
830 : NaClExpFlags flags;
831 :
832 : /* First compute the immediate value. */
833 : uint64_t value;
834 : DEBUG(NaClLog(LOG_INFO, "append immediate\n"));
835 79 : value = NaClExtractUnsignedImmediate(state);
836 :
837 : /* Now compute any appropriate flags to be associated with the immediate
838 : * value.
839 : */
840 79 : flags = NACL_EFLAG(ExprUnsignedHex) |
841 : NaClGetExprSizeFlagForBytes(state->num_imm_bytes);
842 :
843 : /* Append the generated immediate value onto the vector. */
844 79 : return NaClAppendConst(value, flags, &state->nodes);
845 : }
846 :
847 : /* Append the second immediate value of the given instruction state onto
848 : * the vector of expression nodes. Returns the appended immediate value.
849 : */
850 0 : static NaClExp* NaClAppendImmed2(NaClInstState* state) {
851 : NaClExpFlags flags;
852 :
853 : /* First compute the immedaite value. */
854 : uint64_t value;
855 : DEBUG(NaClLog(LOG_INFO, "append 2nd immediate\n"));
856 :
857 0 : value = NaClExtractUnsignedImmediate2(state);
858 :
859 : /* Now compute any appropriate flags to be associated with the immediate
860 : * value.
861 : */
862 0 : flags =
863 : NACL_EFLAG(ExprUnsignedHex) |
864 : NaClGetExprSizeFlagForBytes(state->num_imm2_bytes);
865 :
866 : /* Append the generated immediate value onto the vector. */
867 0 : return NaClAppendConst(value, flags, &state->nodes);
868 : }
869 :
870 : /* Append an ExprMemOffset node for the given state, and return
871 : * the appended ndoe.
872 : */
873 209 : static NaClExp* NaClAppendMemOffsetNode(NaClInstState* state) {
874 209 : NaClExpFlags flags = NaClGetAddressExprSizeFlagsForState(state);
875 209 : NaClExp* root = NaClAppendExp(ExprMemOffset, 0, flags, &state->nodes);
876 : DEBUG(NaClLog(LOG_INFO, "Build memoffset, flags = ");
877 : NaClPrintExpFlags(NaClLogGetGio(), flags);
878 : gprintf(NaClLogGetGio(), "\n"));
879 209 : return root;
880 : }
881 :
882 : /* Returns the segment register prefix node, or NULL if no such node is
883 : * added.
884 : */
885 : static NaClExp* NaClAppendSegmentAddressNode(NaClInstState* state,
886 209 : NaClOpKind reg_default) {
887 209 : NaClExp* root = NULL;
888 209 : NaClOpKind seg_reg = NaClGetSegmentPrefixReg(state, reg_default);
889 209 : if (seg_reg != RegUnknown) {
890 : NaClExp* n;
891 197 : root = NaClAppendSegmentAddress(state);
892 197 : n = NaClAppendReg(seg_reg, &state->nodes);
893 197 : n->flags |= NACL_EFLAG(ExprUsed);
894 : }
895 209 : return root;
896 : }
897 :
898 : /* Append the immediate value of the given instruction as the displacement
899 : * of a memory offset.
900 : */
901 20 : static NaClExp* NaClAppendMemoryOffsetImmed(NaClInstState* state) {
902 : NaClExpFlags flags;
903 : uint64_t value;
904 : NaClExp* root;
905 : DEBUG(NaClLog(LOG_INFO, "append memory offset immediate\n"));
906 20 : root = NaClAppendSegmentAddressNode(state, RegUnknown);
907 20 : if (root == NULL) {
908 12 : root = NaClAppendMemOffsetNode(state);
909 : } else {
910 8 : NaClAppendMemOffsetNode(state);
911 : }
912 20 : NaClAppendReg(RegUnknown, &state->nodes);
913 20 : NaClAppendReg(RegUnknown, &state->nodes);
914 20 : NaClAppendConst(1, NACL_EFLAG(ExprSize8), &state->nodes);
915 20 : value = NaClExtractUnsignedImmediate(state);
916 : DEBUG(NaClLog(LOG_INFO, "value = 0x%016"NACL_PRIx64"\n", value));
917 20 : flags = NACL_EFLAG(ExprUnsignedHex) |
918 : NaClGetExprSizeFlagForBytes(state->num_imm_bytes);
919 20 : NaClAppendConst(value, flags, &state->nodes);
920 20 : return root;
921 : }
922 :
923 37 : static NaClExp* NaClAppendRelativeImmed(NaClInstState* state) {
924 37 : NaClPcNumber jump_offset = (NaClPcNumber) NaClExtractSignedImmediate(state);
925 : DEBUG(NaClLog(LOG_INFO, "append relative immediate\n"));
926 37 : return NaClAppendConst(jump_offset,
927 : NACL_EFLAG(ExprSignedHex) |
928 : NaClGetExprSizeFlagForBytes(state->num_imm_bytes) |
929 : NACL_EFLAG(ExprJumpTarget),
930 : &state->nodes);
931 : }
932 :
933 : /* Append a memory offset for the given memory offset defined by
934 : * the formula "base + index*scale + displacement". If no index
935 : * is used, its value should be RegUnknown. Argument displacement_flags
936 : * are flags that should be associated with the generated displacement
937 : * value
938 : */
939 : static NaClExp* NaClAppendMemoryOffset(NaClInstState* state,
940 : NaClOpKind base,
941 : NaClOpKind index,
942 : uint8_t scale,
943 189 : NaClDisplacement* displacement) {
944 189 : NaClExp* root = NULL;
945 : NaClOpKind seg_reg_default;
946 : NaClExp* n;
947 :
948 : DEBUG(NaClLog(LOG_INFO,
949 : "memory offset(%s + %s * %d + %"NACL_PRId64
950 : " : %"NACL_PRIx32")\n",
951 : NaClOpKindName(base),
952 : NaClOpKindName(index),
953 : scale,
954 : displacement->value,
955 : displacement->flags));
956 :
957 : if (32 == NACL_TARGET_SUBARCH) {
958 189 : seg_reg_default = ((base == RegBP || base == RegEBP)
959 : ? RegSS : NaClGetDsSegmentReg(state));
960 : } else {
961 : seg_reg_default = RegUnknown;
962 : }
963 189 : root = NaClAppendSegmentAddressNode(state, seg_reg_default);
964 189 : if (NULL == root) {
965 0 : root = NaClAppendMemOffsetNode(state);
966 : } else {
967 189 : NaClAppendMemOffsetNode(state);
968 : }
969 189 : n = NaClAppendReg(base, &state->nodes);
970 189 : if (base != RegUnknown) {
971 180 : n->flags |= NACL_EFLAG(ExprUsed);
972 : }
973 189 : n = NaClAppendReg(index, &state->nodes);
974 189 : if (index == RegUnknown) {
975 : /* Scale not applicable, check that value is 1. */
976 124 : assert(scale == 1);
977 : } else {
978 65 : n->flags |= NACL_EFLAG(ExprUsed);
979 : }
980 189 : NaClAppendConst(scale, NACL_EFLAG(ExprSize8), &state->nodes);
981 189 : NaClAppendConst(displacement->value, displacement->flags, &state->nodes);
982 : DEBUG(NaClLog(LOG_INFO, "finished appending memory offset:\n"));
983 : DEBUG(NaClExpVectorPrint(NaClLogGetGio(), state));
984 189 : return root;
985 : }
986 :
987 : /* Extract the base register from the SIB byte. */
988 65 : static NaClOpKind NaClGetSibBase(NaClInstState* state) {
989 65 : int base = sib_base(state->sib);
990 65 : NaClOpKind base_reg = RegUnknown;
991 65 : if (0x5 == base) {
992 10 : switch (modrm_modInline(state->modrm)) {
993 : case 0:
994 9 : break;
995 : case 1:
996 : case 2:
997 : if (NACL_TARGET_SUBARCH == 64) {
998 : if (state->rexprefix & 0x1) {
999 : base_reg = RegR13;
1000 : } else {
1001 : base_reg = RegRBP;
1002 : }
1003 : } else {
1004 1 : base_reg = RegEBP;
1005 : }
1006 1 : break;
1007 : default:
1008 0 : NaClFatal("SIB value", state);
1009 : }
1010 : } else {
1011 55 : NaClRegKind kind = NaClExtractAddressRegKind(state);
1012 55 : base_reg = NaClLookupReg(state, kind, NaClGetRexBReg(state, base));
1013 : }
1014 65 : return base_reg;
1015 : }
1016 :
1017 : /* Define the possible scaling factors that can be defined in the
1018 : * SIB byte of the parsed instruction.
1019 : */
1020 : static uint8_t nacl_sib_scale[4] = { 1, 2, 4, 8 };
1021 :
1022 : /* Extract out the expression defined by the SIB byte of the instruction
1023 : * in the given instruction state, and append it to the vector of
1024 : * expression nodes. Return the corresponding expression node that
1025 : * is the root of the appended expression.
1026 : */
1027 65 : static NaClExp* NaClAppendSib(NaClInstState* state) {
1028 65 : int index = sib_index(state->sib);
1029 65 : int scale = 1;
1030 65 : NaClRegKind kind = NaClExtractAddressRegKind(state);
1031 : NaClOpKind base_reg;
1032 65 : NaClOpKind index_reg = RegUnknown;
1033 : NaClDisplacement displacement;
1034 : DEBUG(NaClLog(LOG_INFO, "append sib: %02x\n", state->sib));
1035 65 : NaClInitializeDisplacement(0, 0, &displacement);
1036 65 : base_reg = NaClGetSibBase(state);
1037 : if (0x4 != index || NACL_TARGET_SUBARCH != 64 || (state->rexprefix & 0x2)) {
1038 65 : index_reg = NaClLookupReg(state, kind, NaClGetRexXReg(state, index));
1039 65 : scale = nacl_sib_scale[sib_ss(state->sib)];
1040 : }
1041 65 : if (state->num_disp_bytes > 0) {
1042 42 : NaClExtractDisplacement(state, &displacement,
1043 : NACL_EFLAG(ExprSignedHex));
1044 : } else {
1045 23 : displacement.flags = NACL_EFLAG(ExprSize8);
1046 : }
1047 65 : return NaClAppendMemoryOffset(state, base_reg, index_reg,
1048 : scale, &displacement);
1049 : }
1050 :
1051 0 : static void NaClAppendEDI(NaClInstState* state) {
1052 0 : switch (state->address_size) {
1053 : case 16:
1054 0 : NaClAppendReg(RegDI, &state->nodes);
1055 0 : break;
1056 : case 32:
1057 0 : NaClAppendReg(RegEDI, &state->nodes);
1058 0 : break;
1059 : case 64:
1060 0 : NaClAppendReg(RegRDI, &state->nodes);
1061 0 : break;
1062 : default:
1063 0 : NaClFatal("Address size for %EDI not correctly defined",
1064 : state);
1065 : break;
1066 : }
1067 0 : }
1068 :
1069 0 : static void NaClAppendESI(NaClInstState* state) {
1070 0 : switch (state->address_size) {
1071 : case 16:
1072 0 : NaClAppendReg(RegSI, &state->nodes);
1073 0 : break;
1074 : case 32:
1075 0 : NaClAppendReg(RegESI, &state->nodes);
1076 0 : break;
1077 : case 64:
1078 0 : NaClAppendReg(RegRSI, &state->nodes);
1079 0 : break;
1080 : default:
1081 0 : NaClFatal("Address size for %ESI not correctly defined", state);
1082 : break;
1083 : }
1084 0 : }
1085 :
1086 1 : static void NaClAppendEBX(NaClInstState* state) {
1087 1 : switch (state->address_size) {
1088 : case 16:
1089 0 : NaClAppendReg(RegBX, &state->nodes);
1090 0 : break;
1091 : case 32:
1092 1 : NaClAppendReg(RegEBX, &state->nodes);
1093 1 : break;
1094 : case 64:
1095 0 : NaClAppendReg(RegRBX, &state->nodes);
1096 0 : break;
1097 : default:
1098 0 : NaClFatal("Address size for %EBX not correctly defined", state);
1099 : break;
1100 : }
1101 1 : }
1102 :
1103 0 : static NaClExp* NaClAppendDS_EDI(NaClInstState* state) {
1104 0 : NaClExp* results = NaClAppendSegmentAddress(state);
1105 0 : results->flags |= NACL_EFLAG(ExprDSrCase);
1106 0 : NaClAppendReg(NaClGetDsSegmentReg(state), &state->nodes);
1107 0 : NaClAppendEDI(state);
1108 0 : return results;
1109 : }
1110 :
1111 0 : static NaClExp* NaClAppendDS_ESI(NaClInstState* state) {
1112 0 : NaClExp* results = NaClAppendSegmentAddress(state);
1113 0 : results->flags |= NACL_EFLAG(ExprDSrCase);
1114 0 : NaClAppendReg(NaClGetDsSegmentReg(state), &state->nodes);
1115 0 : NaClAppendESI(state);
1116 0 : return results;
1117 : }
1118 :
1119 1 : static NaClExp* NaClAppendDS_EBX(NaClInstState* state) {
1120 1 : NaClExp* results = NaClAppendSegmentAddress(state);
1121 1 : results->flags |= NACL_EFLAG(ExprDSrCase);
1122 1 : NaClAppendReg(NaClGetDsSegmentReg(state), &state->nodes);
1123 1 : NaClAppendEBX(state);
1124 1 : return results;
1125 : }
1126 :
1127 0 : static NaClExp* NaClAppendES_EDI(NaClInstState* state) {
1128 0 : NaClExp* results = NaClAppendSegmentAddress(state);
1129 0 : results->flags |= NACL_EFLAG(ExprESrCase);
1130 0 : NaClAppendReg(NaClGetEsSegmentReg(state), &state->nodes);
1131 0 : NaClAppendEDI(state);
1132 0 : return results;
1133 : }
1134 :
1135 : /* Get the Effective address in the mod/rm byte, if the modrm.mod field
1136 : * is 00, and append it to the vector of expression nodes. Operand is
1137 : * the corresponding operand of the opcode associated with the instruction
1138 : * of the given state that corresponds to the effective address. Returns
1139 : * the root of the appended effective address.
1140 : */
1141 : static NaClExp* NaClAppendMod00EffectiveAddress(
1142 90 : NaClInstState* state, const NaClOp* operand) {
1143 : DEBUG(NaClLog(LOG_INFO, "Translate modrm(%02x).mod == 00\n", state->modrm));
1144 90 : if ((32 == NACL_TARGET_SUBARCH) &&
1145 : NaClHasBit(state->prefix_mask, kPrefixADDR16)) {
1146 : /* This code doesn't know how to translate 16-bit modrm effective addresses.
1147 : * However, such arguments are not nacl legal. Communicate this explicitly.
1148 : */
1149 2 : return NaClAppendNaClIllegal(state);
1150 : }
1151 88 : switch (modrm_rmInline(state->modrm)) {
1152 : case 4:
1153 32 : return NaClAppendSib(state);
1154 : case 5:
1155 : if (NACL_TARGET_SUBARCH == 64) {
1156 : NaClDisplacement displacement;
1157 : NaClExtractDisplacement(state, &displacement,
1158 : NACL_EFLAG(ExprSignedHex));
1159 : return NaClAppendMemoryOffset(state,
1160 : RegRIP,
1161 : RegUnknown,
1162 : 1,
1163 : &displacement);
1164 : } else {
1165 4 : return NaClAppendDisplacement(state);
1166 : }
1167 : default: {
1168 : NaClDisplacement displacement;
1169 52 : NaClInitializeDisplacement(0, NACL_EFLAG(ExprSize8), &displacement);
1170 52 : return NaClAppendMemoryOffset(state,
1171 : NaClLookupReg(
1172 : state,
1173 : NaClExtractAddressRegKind(state),
1174 : NaClGetGenRmRegister(state)),
1175 : RegUnknown,
1176 : 1,
1177 : &displacement);
1178 : }
1179 : }
1180 : /* NOT REACHED */
1181 : return NULL;
1182 : }
1183 :
1184 : /* Get the Effective address in the mod/rm byte, if the modrm.mod field
1185 : * is 01, and append it to the vector of expression nodes. Operand is
1186 : * the corresponding operand of the opcode associated with the instruction
1187 : * of the given state that corresponds to the effective address. Returns
1188 : * the root of the appended effective address.
1189 : */
1190 : static NaClExp* NaClAppendMod01EffectiveAddress(
1191 77 : NaClInstState* state, const NaClOp* operand) {
1192 : DEBUG(NaClLog(LOG_INFO, "Translate modrm(%02x).mod == 01\n", state->modrm));
1193 77 : if ((32 == NACL_TARGET_SUBARCH) &&
1194 : NaClHasBit(state->prefix_mask, kPrefixADDR16)) {
1195 : /* This code doesn't know how to translate 16-bit modrm effective addresses.
1196 : * However, such arguments are not nacl legal. Communicate this explicitly.
1197 : */
1198 1 : return NaClAppendNaClIllegal(state);
1199 : }
1200 76 : if (4 == modrm_rmInline(state->modrm)) {
1201 21 : return NaClAppendSib(state);
1202 : } else {
1203 : NaClDisplacement displacement;
1204 55 : NaClExtractDisplacement(state, &displacement, NACL_EFLAG(ExprSignedHex));
1205 55 : return NaClAppendMemoryOffset(state,
1206 : NaClLookupReg(
1207 : state,
1208 : NaClExtractAddressRegKind(state),
1209 : NaClGetGenRmRegister(state)),
1210 : RegUnknown,
1211 : 1,
1212 : &displacement);
1213 : }
1214 : }
1215 :
1216 : /* Get the Effective address in the mod/rm byte, if the modrm.mod field
1217 : * is 10, and append it to the vector of expression nodes. Operand is
1218 : * the corresponding operand of the opcode associated with the instruction
1219 : * of the given state that corresponds to the effective address. Returns
1220 : * the root of the appended effective address.
1221 : */
1222 : static NaClExp* NaClAppendMod10EffectiveAddress(
1223 29 : NaClInstState* state, const NaClOp* operand) {
1224 : DEBUG(NaClLog(LOG_INFO, "Translate modrm(%02x).mod == 10\n", state->modrm));
1225 29 : if ((32 == NACL_TARGET_SUBARCH) &&
1226 : NaClHasBit(state->prefix_mask, kPrefixADDR16)) {
1227 : /* This code doesn't know how to translate 16-bit modrm effective addresses.
1228 : * However, such arguments are not nacl legal. Communicate this explicitly.
1229 : */
1230 0 : return NaClAppendNaClIllegal(state);
1231 : }
1232 29 : if (4 == modrm_rmInline(state->modrm)) {
1233 12 : return NaClAppendSib(state);
1234 : } else {
1235 : NaClDisplacement displacement;
1236 : NaClOpKind base =
1237 : NaClLookupReg(state,
1238 : NaClExtractAddressRegKind(state),
1239 17 : NaClGetGenRmRegister(state));
1240 17 : NaClExtractDisplacement(state, &displacement, NACL_EFLAG(ExprSignedHex));
1241 17 : return NaClAppendMemoryOffset(state, base, RegUnknown, 1, &displacement);
1242 : }
1243 : }
1244 :
1245 : /* Get the Effective address in the mod/rm byte, if the modrm.mod field
1246 : * is 11, and append it to the vector of expression nodes. Operand is
1247 : * the corresponding operand of the opcode associated with the instruction
1248 : * of the given state that corresponds to the effective address. Returns
1249 : * the root of the appended effective address.
1250 : */
1251 : static NaClExp* NaClAppendMod11EffectiveAddress(
1252 : NaClInstState* state, const NaClOp* operand,
1253 50 : NaClModRmRegKind modrm_reg_kind) {
1254 : DEBUG(NaClLog(LOG_INFO, "Translate modrm(%02x).mod == 11, %s\n",
1255 : state->modrm, g_NaClModRmRegKindName[modrm_reg_kind]));
1256 50 : return NaClAppendOperandReg(state,
1257 : operand,
1258 : NaClGetGenRmRegister(state), modrm_reg_kind);
1259 : }
1260 :
1261 : static NaClExp* NaClAppendBasedOnSize(NaClOpKind reg_2b,
1262 : NaClOpKind reg_4b,
1263 : NaClOpKind reg_8b,
1264 18 : NaClInstState* state) {
1265 18 : switch (state->operand_size) {
1266 : case 2:
1267 8 : return NaClAppendReg(reg_2b, &state->nodes);
1268 : case 4:
1269 10 : return NaClAppendReg(reg_4b, &state->nodes);
1270 : case 8:
1271 0 : return NaClAppendReg(reg_8b, &state->nodes);
1272 : default:
1273 0 : return NaClFatal("can't translate register group: operand size not valid",
1274 : state);
1275 : }
1276 : }
1277 :
1278 : static NaClExp* NaClAppendBasedOnAddressSize(NaClOpKind reg_2b,
1279 : NaClOpKind reg_4b,
1280 : NaClOpKind reg_8b,
1281 0 : NaClInstState* state) {
1282 0 : switch (state->address_size) {
1283 : case 16:
1284 0 : return NaClAppendReg(reg_2b, &state->nodes);
1285 : case 32:
1286 0 : return NaClAppendReg(reg_4b, &state->nodes);
1287 : case 64:
1288 0 : return NaClAppendReg(reg_8b, &state->nodes);
1289 : default:
1290 0 : return NaClFatal("can't translate register group: address size not valid",
1291 : state);
1292 : }
1293 : }
1294 :
1295 : /* Compute the effect address using the Mod/Rm and SIB bytes. */
1296 : static NaClExp* NaClAppendEffectiveAddress(
1297 : NaClInstState* state, const NaClOp* operand,
1298 246 : NaClModRmRegKind modrm_reg_kind) {
1299 246 : switch(modrm_modInline(state->modrm)) {
1300 : case 0:
1301 90 : return NaClAppendMod00EffectiveAddress(state, operand);
1302 : case 1:
1303 77 : return NaClAppendMod01EffectiveAddress(state, operand);
1304 : case 2:
1305 29 : return NaClAppendMod10EffectiveAddress(state, operand);
1306 : case 3:
1307 50 : return NaClAppendMod11EffectiveAddress(state, operand, modrm_reg_kind);
1308 : default:
1309 : break;
1310 : }
1311 0 : return NaClFatal("Operand", state);
1312 : }
1313 :
1314 : /* Given the corresponding operand of the opcode associated with the
1315 : * instruction of the given state, append the corresponding expression
1316 : * nodes that it corresponds to. Returns the root of the corresponding
1317 : * appended expression tree.
1318 : */
1319 : static NaClExp* NaClAppendOperand(NaClInstState* state,
1320 730 : const NaClOp* operand) {
1321 : DEBUG(NaClLog(LOG_INFO,
1322 : "append operand %s\n", NaClOpKindName(operand->kind)));
1323 730 : switch (operand->kind) {
1324 : case E_Operand:
1325 : case Eb_Operand:
1326 : case Ew_Operand:
1327 : case Ev_Operand:
1328 : case Eo_Operand:
1329 : case Edq_Operand:
1330 : /* TODO(karl) Should we add limitations that simple registers
1331 : * not allowed in M_Operand cases?
1332 : */
1333 : case M_Operand:
1334 : case Mb_Operand:
1335 : case Mw_Operand:
1336 : case Mv_Operand:
1337 : case Mo_Operand:
1338 : case Mdq_Operand: {
1339 : NaClExp* address =
1340 244 : NaClAppendEffectiveAddress(state, operand, ModRmGeneral);
1341 : /* Near operands are jump addresses. Mark them as such. */
1342 244 : if (operand->flags & NACL_OPFLAG(OperandNear)) {
1343 5 : address->flags |= NACL_EFLAG(ExprJumpTarget);
1344 : }
1345 244 : return address;
1346 : }
1347 : break;
1348 : case G_Operand:
1349 : case Gb_Operand:
1350 : case Gw_Operand:
1351 : case Gv_Operand:
1352 : case Go_Operand:
1353 : case Gdq_Operand:
1354 163 : return NaClAppendOperandReg(state, operand, NaClGetGenRegRegister(state),
1355 : ModRmGeneral);
1356 : case Seg_G_Operand:
1357 0 : return NaClAppendSegmentOpReg(
1358 : state, operand, NaClGetMnemonicSegmentRegister(state),
1359 : NaClGetGenRegRegister(state), ModRmGeneral);
1360 : case G_OpcodeBase:
1361 34 : return NaClAppendOpcodeBaseReg(state, operand);
1362 : case I_Operand:
1363 : case Ib_Operand:
1364 : case Iw_Operand:
1365 : case Iv_Operand:
1366 : case Io_Operand:
1367 79 : return NaClAppendImmed(state);
1368 : case I2_Operand:
1369 0 : return NaClAppendImmed2(state);
1370 : case J_Operand:
1371 : case Jb_Operand:
1372 : case Jw_Operand:
1373 : case Jv_Operand:
1374 : /* TODO(karl) use operand flags OperandNear and OperandRelative to decide
1375 : * how to process the J operand (see Intel manual for call statement).
1376 : */
1377 37 : return NaClAppendRelativeImmed(state);
1378 : case Mmx_Gd_Operand:
1379 : case Mmx_G_Operand:
1380 0 : return NaClAppendOperandReg(state, operand, NaClGetGenRegRegister(state),
1381 : ModRmMmx);
1382 : case Mmx_E_Operand:
1383 0 : return NaClAppendEffectiveAddress(state, operand, ModRmMmx);
1384 : case Xmm_G_Operand:
1385 : case Xmm_Go_Operand:
1386 4 : return NaClAppendOperandReg(state, operand, NaClGetGenRegRegister(state),
1387 : ModRmXmm);
1388 : case Xmm_E_Operand:
1389 : case Xmm_Eo_Operand:
1390 2 : return NaClAppendEffectiveAddress(state, operand, ModRmXmm);
1391 : case C_Operand:
1392 0 : return NaClAppendEffectiveAddress(state, operand, ModRmCreg);
1393 : case D_Operand:
1394 0 : return NaClAppendEffectiveAddress(state, operand, ModRmDreg);
1395 : case O_Operand:
1396 : case Ob_Operand:
1397 : case Ow_Operand:
1398 : case Ov_Operand:
1399 : case Oo_Operand:
1400 20 : return NaClAppendMemoryOffsetImmed(state);
1401 : case St_Operand:
1402 0 : return NaClAppendStOpcodeBaseReg(state);
1403 : case RegUnknown:
1404 : case RegAL:
1405 : case RegBL:
1406 : case RegCL:
1407 : case RegDL:
1408 : case RegAH:
1409 : case RegBH:
1410 : case RegCH:
1411 : case RegDH:
1412 : case RegDIL:
1413 : case RegSIL:
1414 : case RegBPL:
1415 : case RegSPL:
1416 : case RegR8B:
1417 : case RegR9B:
1418 : case RegR10B:
1419 : case RegR11B:
1420 : case RegR12B:
1421 : case RegR13B:
1422 : case RegR14B:
1423 : case RegR15B:
1424 : case RegAX:
1425 : case RegBX:
1426 : case RegCX:
1427 : case RegDX:
1428 : case RegSI:
1429 : case RegDI:
1430 : case RegBP:
1431 : case RegSP:
1432 : case RegR8W:
1433 : case RegR9W:
1434 : case RegR10W:
1435 : case RegR11W:
1436 : case RegR12W:
1437 : case RegR13W:
1438 : case RegR14W:
1439 : case RegR15W:
1440 : case RegEAX:
1441 : case RegEBX:
1442 : case RegECX:
1443 : case RegEDX:
1444 : case RegESI:
1445 : case RegEDI:
1446 : case RegEBP:
1447 : case RegESP:
1448 : case RegR8D:
1449 : case RegR9D:
1450 : case RegR10D:
1451 : case RegR11D:
1452 : case RegR12D:
1453 : case RegR13D:
1454 : case RegR14D:
1455 : case RegR15D:
1456 : case RegCS:
1457 : case RegDS:
1458 : case RegSS:
1459 : case RegES:
1460 : case RegFS:
1461 : case RegGS:
1462 : case RegCR0:
1463 : case RegCR1:
1464 : case RegCR2:
1465 : case RegCR3:
1466 : case RegCR4:
1467 : case RegCR5:
1468 : case RegCR6:
1469 : case RegCR7:
1470 : case RegCR8:
1471 : case RegCR9:
1472 : case RegCR10:
1473 : case RegCR11:
1474 : case RegCR12:
1475 : case RegCR13:
1476 : case RegCR14:
1477 : case RegCR15:
1478 : case RegDR0:
1479 : case RegDR1:
1480 : case RegDR2:
1481 : case RegDR3:
1482 : case RegDR4:
1483 : case RegDR5:
1484 : case RegDR6:
1485 : case RegDR7:
1486 : case RegDR8:
1487 : case RegDR9:
1488 : case RegDR10:
1489 : case RegDR11:
1490 : case RegDR12:
1491 : case RegDR13:
1492 : case RegDR14:
1493 : case RegDR15:
1494 : case RegEFLAGS:
1495 : case RegRFLAGS:
1496 : case RegEIP:
1497 : case RegRIP:
1498 : case RegRAX:
1499 : case RegRBX:
1500 : case RegRCX:
1501 : case RegRDX:
1502 : case RegRSI:
1503 : case RegRDI:
1504 : case RegRBP:
1505 : case RegRSP:
1506 : case RegR8:
1507 : case RegR9:
1508 : case RegR10:
1509 : case RegR11:
1510 : case RegR12:
1511 : case RegR13:
1512 : case RegR14:
1513 : case RegR15:
1514 : case RegST0:
1515 : case RegST1:
1516 : case RegST2:
1517 : case RegST3:
1518 : case RegST4:
1519 : case RegST5:
1520 : case RegST6:
1521 : case RegST7:
1522 : case RegMMX1:
1523 : case RegMMX2:
1524 : case RegMMX3:
1525 : case RegMMX4:
1526 : case RegMMX5:
1527 : case RegMMX6:
1528 : case RegMMX7:
1529 : case RegXMM0:
1530 : case RegXMM1:
1531 : case RegXMM2:
1532 : case RegXMM3:
1533 : case RegXMM4:
1534 : case RegXMM5:
1535 : case RegXMM6:
1536 : case RegXMM7:
1537 : case RegXMM8:
1538 : case RegXMM9:
1539 : case RegXMM10:
1540 : case RegXMM11:
1541 : case RegXMM12:
1542 : case RegXMM13:
1543 : case RegXMM14:
1544 : case RegXMM15:
1545 128 : return NaClAppendReg(operand->kind, &state->nodes);
1546 : case RegREIP:
1547 0 : return NaClAppendReg(state->address_size == 64 ? RegRIP : RegEIP,
1548 : &state->nodes);
1549 :
1550 : case RegREAX:
1551 17 : return NaClAppendBasedOnSize(RegAX, RegEAX, RegRAX, state);
1552 : case RegREBX:
1553 0 : return NaClAppendBasedOnSize(RegBX, RegEBX, RegRBX, state);
1554 : case RegRECX:
1555 0 : return NaClAppendBasedOnSize(RegCX, RegECX, RegRCX, state);
1556 : case RegREDX:
1557 0 : return NaClAppendBasedOnSize(RegDX, RegEDX, RegRDX, state);
1558 : case RegRESP:
1559 1 : return NaClAppendBasedOnSize(RegSP, RegESP, RegRSP, state);
1560 : case RegREBP:
1561 0 : return NaClAppendBasedOnSize(RegBP, RegEBP, RegRBP, state);
1562 : case RegRESI:
1563 0 : return NaClAppendBasedOnSize(RegSI, RegESI, RegRSI, state);
1564 : case RegREDI:
1565 0 : return NaClAppendBasedOnSize(RegDI, RegEDI, RegRSI, state);
1566 : case RegREAXa:
1567 0 : return NaClAppendBasedOnAddressSize(RegAX, RegEAX, RegRAX, state);
1568 :
1569 : case RegDS_ESI:
1570 0 : return NaClAppendDS_ESI(state);
1571 : case RegDS_EDI:
1572 0 : return NaClAppendDS_EDI(state);
1573 : case RegDS_EBX:
1574 1 : return NaClAppendDS_EBX(state);
1575 : case RegES_EDI:
1576 0 : return NaClAppendES_EDI(state);
1577 :
1578 : case S_Operand:
1579 0 : return NaClAppendModRmSegmentReg(state);
1580 :
1581 : case Const_1:
1582 0 : return NaClAppendConst(1,
1583 : NACL_EFLAG(ExprSize8) | NACL_EFLAG(ExprUnsignedHex),
1584 : &state->nodes);
1585 : default:
1586 : /* Give up, use the default of undefined. */
1587 : break;
1588 : }
1589 0 : return NaClFatal("Operand", state);
1590 : }
1591 :
1592 : /* Given that the given expression node is the root of the expression
1593 : * tree generated by translating the given operand, transfer over
1594 : * any appropriate flags (such as set/use information).
1595 : */
1596 730 : static NaClExp* NaClAddOpSetUse(NaClExp* node, const NaClOp* operand) {
1597 730 : if (operand->flags & NACL_OPFLAG(OpSet)) {
1598 362 : node->flags |= NACL_EFLAG(ExprSet);
1599 : }
1600 730 : if (operand->flags & NACL_OPFLAG(OpDest)) {
1601 226 : node->flags |= NACL_EFLAG(ExprDest);
1602 : }
1603 730 : if (operand->flags & NACL_OPFLAG(OpUse)) {
1604 452 : node->flags |= NACL_EFLAG(ExprUsed);
1605 : }
1606 730 : if (operand->flags & NACL_OPFLAG(OpAddress)) {
1607 48 : node->flags |= NACL_EFLAG(ExprAddress);
1608 : }
1609 730 : return node;
1610 : }
1611 :
1612 727 : void NaClBuildExpVector(struct NaClInstState* state) {
1613 : uint8_t i;
1614 : uint8_t num_ops;
1615 : DEBUG(NaClLog(LOG_INFO,
1616 : "building expression vector for pc = %"NACL_PRIxNaClPcAddress
1617 : ":\n", state->inst_addr));
1618 727 : num_ops = NaClGetInstNumberOperandsInline(state->inst);
1619 1457 : for (i = 0; i < num_ops; i++) {
1620 : NaClExp* n;
1621 : const NaClOp* op = NaClGetInstOperandInline(state->decoder_tables,
1622 730 : state->inst, i);
1623 : DEBUG(NaClLog(LOG_INFO, "translating operand %d:\n", i));
1624 730 : n = NaClAppendExp(OperandReference, i,
1625 : NACL_EFLAG(ExprSize8) | NACL_EFLAG(ExprUnsignedInt),
1626 : &state->nodes);
1627 730 : if (op->flags & NACL_OPFLAG(OpImplicit)) {
1628 95 : n->flags |= NACL_EFLAG(ExprImplicit);
1629 : }
1630 730 : NaClAddOpSetUse(NaClAppendOperand(state, op), op);
1631 : DEBUG(NaClExpVectorPrint(NaClLogGetGio(), state));
1632 : }
1633 727 : }
|