OLD | NEW |
| (Empty) |
1 /* | |
2 * Copyright (c) 2011 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 * Captures instructions that zero extend 32 bit values. | |
9 * | |
10 * Extracted from table B-1 in AMD document 25494 - AMD64 Architecture | |
11 * Programmer's Manual, Volume 3: General-Purpose and System Instructions. | |
12 * | |
13 * Note: This is used by the x86-64 validator to decide what operations can | |
14 * be used to mask control/memory accesses. Therefore, not all instructions | |
15 * listed in table B-1 (above) are defined to zero-extend. In particular, | |
16 * this is a NaCl-specific flag that is used to whitelist instructions | |
17 * that can be used to zero-extend (mask) 32-bit addresses. As such, although | |
18 * some instruction can zero-extend, we don't necessarily allow them here. | |
19 */ | |
20 | |
21 #ifndef NACL_TRUSTED_BUT_NOT_TCB | |
22 #error("This file is not meant for use in the TCB") | |
23 #endif | |
24 | |
25 #include "native_client/src/trusted/validator/x86/decoder/generator/zero_extends
.h" | |
26 | |
27 #include "native_client/src/include/nacl_macros.h" | |
28 #include "native_client/src/trusted/validator/x86/decoder/generator/ncdecode_for
ms.h" | |
29 #include "native_client/src/trusted/validator/x86/decoder/generator/ncdecode_tab
legen.h" | |
30 | |
31 /* List of instruction mnemonics that zero extend 32 bit results. */ | |
32 static const NaClMnemonic kZeroExtend32Op[] = { | |
33 /* Note: The following instructions are listed in table B-1 (above), but are | |
34 * not included for the following reasons: | |
35 * | |
36 * Bsf and Bsr instructions are not included because they conditionally | |
37 * write the destination. See | |
38 * http://code.google.com/p/nativeclient/issues/detail?id=2010 | |
39 * | |
40 * Cmovcc instructions (0f40 through 0f4f) are not included out of caution. | |
41 * Table B-1 (above) states that these instrucitons always zero extends 32 bit | |
42 * register results to 64 bits, and that this occurs even if the condition | |
43 * is false. However, we decided to be safe and omit these instructions | |
44 * anyway. | |
45 * | |
46 * Cmpxchg is not included because it conditionally writes to | |
47 * different destinations. | |
48 * | |
49 * Bswap is not included because we don't really think that | |
50 * swapping the bottom bytes is a good thing to do to mask a memory | |
51 * reference. | |
52 * | |
53 * Bt, Btc, Btr, Bts, Rcl, Rcr, Rol, Rol, Sar, Shl, Shld, Shr, and | |
54 * Shrd instructions are not included out of caution. We assume that | |
55 * these instructions are used for bit manipulation rather than | |
56 * computing viable addresses. | |
57 * | |
58 * Adc and Sbb are not included since borrows/carries should not be | |
59 * need when calculating an address. | |
60 * | |
61 * Cpuid, In, and Lar instructions are not included just because they | |
62 * shouldn't be. | |
63 * | |
64 * Div, Idiv, and Mul instructions are not included because we never | |
65 * allowed them. | |
66 * | |
67 * Lfs, Lgs, Lss, and Lsl instructions are not included because segment | |
68 * addresses shouldn't be used. | |
69 * | |
70 * Lzcnt is not included because it is unlikely to be useful for | |
71 * computing an address based on the number of leading zeros of a value. | |
72 * | |
73 * Pextrb is not included because you shouldn't use MMX registers | |
74 * to hold addresses. | |
75 * | |
76 * Popcnt is not included because it is unlikely to be useful for computing | |
77 * an address based on the number of ones in a value. | |
78 * | |
79 * Rdmsr is not included, because you shouldn't be reading model specific | |
80 * registers. | |
81 * | |
82 * Rdpmc is not included because you shouldn't be basing addresses on | |
83 * the performance-monitor counter. | |
84 * | |
85 * Rdtsc and Rdtscp are not included because you shouldn't be basing | |
86 * addresses on the time-stamp counter or the processor id. | |
87 * | |
88 * Smsw is not included since you shouldn't be basing addresses on the | |
89 * machine status word. | |
90 */ | |
91 InstAdd, /* 01, 03, 05, 81/0, 83/0 */ | |
92 InstAnd, /* 21, 23, 25, 81/4, 83/4 */ | |
93 InstImul, /* f7/5 , 0f af , 69 , 6b */ | |
94 InstLea, /* 8D */ | |
95 InstMov, /* 89, 8b, c7, b8 through bf, a1 (moffset), | |
96 a3 (moffset) | |
97 */ | |
98 InstMovd, /* 0f 6e, 0f 7e */ | |
99 InstMovsx, /* 0f be, 0f bf */ | |
100 InstMovsxd, /* 63 */ | |
101 InstMovzx, /* 0f b6, 0f b7 */ | |
102 InstNeg, /* f7/3 */ | |
103 InstNot, /* f7/2 */ | |
104 InstOr, /* 09, 0b, 0d, 81/1, 83/1 */ | |
105 InstSub, /* 29, 2b, 2d, 81/5, 83/5 */ | |
106 InstXadd, /* 0f c1 */ | |
107 InstXchg, /* 87, 90 through 97 */ | |
108 InstXor, /* 31, 33, 35, 81/6, 83/6 */ | |
109 }; | |
110 | |
111 /* List of instruction nmemonics, for specific opcode sequences, that zero | |
112 * extend 32 bit results. | |
113 */ | |
114 static const NaClNameOpcodeSeq kZeroExtend32Opseq[] = { | |
115 { InstDec , { 0xFF , SL(1) , END_OPCODE_SEQ } }, | |
116 { InstInc , { 0xFF , SL(0) , END_OPCODE_SEQ } }, | |
117 }; | |
118 | |
119 /* Add OperandZeroExtends_v to instruction, if it can hold | |
120 * a 32 bit operand. | |
121 */ | |
122 static void AddZeroExtendToOpDestArgs(NaClModeledInst* inst) { | |
123 if (inst->flags & NACL_IFLAG(OperandSize_v)) { | |
124 int i; | |
125 for (i = 0; i < inst->num_operands; ++i) { | |
126 /* Note: we currently don't allow zero extends for | |
127 * implicit arguments. This is done just to be extra | |
128 * cautious on what we allow to be masks in the | |
129 * NaCl x64-64 validator. | |
130 */ | |
131 if ((inst->operands[i].flags & NACL_OPFLAG(OpSet)) && | |
132 (NACL_EMPTY_OPFLAGS == | |
133 (inst->operands[i].flags & NACL_OPFLAG(OpImplicit)))) { | |
134 NaClAddOpFlags(i, NACL_OPFLAG(OperandZeroExtends_v)); | |
135 } | |
136 } | |
137 } | |
138 } | |
139 | |
140 /* Add OperandZeroExtends_v instruction flag if applicable. */ | |
141 void NaClAddZeroExtend32FlagIfApplicable(void) { | |
142 if ((X86_64 == NACL_FLAGS_run_mode) && | |
143 NaClInInstructionSet(kZeroExtend32Op, | |
144 NACL_ARRAY_SIZE(kZeroExtend32Op), | |
145 kZeroExtend32Opseq, | |
146 NACL_ARRAY_SIZE(kZeroExtend32Opseq))) { | |
147 AddZeroExtendToOpDestArgs(NaClGetDefInst()); | |
148 } | |
149 } | |
OLD | NEW |