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