Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(607)

Side by Side Diff: src/trusted/validator_ragel/validator_x86_64.rl

Issue 11000033: Move validator_x86_XX.rl out of unreviewed. (Closed) Base URL: svn://svn.chromium.org/native_client/trunk/src/native_client/
Patch Set: Created 8 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 /* 1 /*
2 * Copyright (c) 2012 The Native Client Authors. All rights reserved. 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 3 * Use of this source code is governed by a BSD-style license that can be
4 * found in the LICENSE file. 4 * found in the LICENSE file.
5 */ 5 */
6 6
7 /*
8 * This is the core of amd64-mode validator. Please note that this file
9 * combines ragel machine description and C language actions. Please read
10 * validator_internals.html first to understand how the whole thing is built:
11 * it explains how the byte sequences are constructed, what constructs like
12 * “@{}” or “REX_WRX?” mean, etc.
13 */
14
7 #include <assert.h> 15 #include <assert.h>
8 #include <errno.h> 16 #include <errno.h>
9 #include <stddef.h> 17 #include <stddef.h>
10 #include <stdio.h> 18 #include <stdio.h>
11 #include <stdlib.h> 19 #include <stdlib.h>
12 #include <string.h> 20 #include <string.h>
13 21
14 #include "native_client/src/trusted/validator_ragel/unreviewed/validator_interna l.h" 22 #include "native_client/src/trusted/validator_ragel/validator_internal.h"
15 23
16 %%{ 24 %%{
17 machine x86_64_validator; 25 machine x86_64_validator;
18 alphtype unsigned char; 26 alphtype unsigned char;
19 variable p current_position; 27 variable p current_position;
20 variable pe end_of_bundle; 28 variable pe end_of_bundle;
21 variable eof end_of_bundle; 29 variable eof end_of_bundle;
22 variable cs current_state; 30 variable cs current_state;
23 31
24 include byte_machine "byte_machines.rl"; 32 include byte_machine "byte_machines.rl";
(...skipping 17 matching lines...) Expand all
42 include modrm_actions_amd64 50 include modrm_actions_amd64
43 "native_client/src/trusted/validator_ragel/unreviewed/parse_instruction.rl"; 51 "native_client/src/trusted/validator_ragel/unreviewed/parse_instruction.rl";
44 include modrm_parsing_amd64 52 include modrm_parsing_amd64
45 "native_client/src/trusted/validator_ragel/unreviewed/parse_instruction.rl"; 53 "native_client/src/trusted/validator_ragel/unreviewed/parse_instruction.rl";
46 include operand_actions_amd64 54 include operand_actions_amd64
47 "native_client/src/trusted/validator_ragel/unreviewed/parse_instruction.rl"; 55 "native_client/src/trusted/validator_ragel/unreviewed/parse_instruction.rl";
48 include immediate_fields_actions 56 include immediate_fields_actions
49 "native_client/src/trusted/validator_ragel/unreviewed/parse_instruction.rl"; 57 "native_client/src/trusted/validator_ragel/unreviewed/parse_instruction.rl";
50 include immediate_fields_parsing_amd64 58 include immediate_fields_parsing_amd64
51 "native_client/src/trusted/validator_ragel/unreviewed/parse_instruction.rl"; 59 "native_client/src/trusted/validator_ragel/unreviewed/parse_instruction.rl";
60 # rel8 actions are used in relative jumps with 8-bit offset.
52 action rel8_operand { 61 action rel8_operand {
53 rel8_operand(current_position + 1, data, jump_dests, size, 62 rel8_operand(current_position + 1, data, jump_dests, size,
54 &instruction_info_collected); 63 &instruction_info_collected);
55 } 64 }
65 # rel16 actions are used in relative jums with 16-bit offset.
66 #
67 # Such instructions should be included in the validator's DFA, but we can not
68 # just exlude them because they are refenced in relative_fields_parsing ragel
69 # machine. Ensure compilations error in case of usage.
56 action rel16_operand { 70 action rel16_operand {
57 #error rel16_operand should never be used in nacl 71 #error rel16_operand should never be used in nacl
58 } 72 }
73 # rel32 actions are used in relative calls and jumps with 32-bit offset.
59 action rel32_operand { 74 action rel32_operand {
60 rel32_operand(current_position + 1, data, jump_dests, size, 75 rel32_operand(current_position + 1, data, jump_dests, size,
61 &instruction_info_collected); 76 &instruction_info_collected);
62 } 77 }
63 include relative_fields_parsing 78 include relative_fields_parsing
64 "native_client/src/trusted/validator_ragel/unreviewed/parse_instruction.rl"; 79 "native_client/src/trusted/validator_ragel/unreviewed/parse_instruction.rl";
65 include cpuid_actions 80 include cpuid_actions
66 "native_client/src/trusted/validator_ragel/unreviewed/parse_instruction.rl"; 81 "native_client/src/trusted/validator_ragel/unreviewed/parse_instruction.rl";
67 82
68 action check_access { 83 action check_access {
69 check_access(instruction_start - data, base, index, restricted_register, 84 check_access(instruction_start - data, base, index, restricted_register,
70 valid_targets, &instruction_info_collected); 85 valid_targets, &instruction_info_collected);
71 } 86 }
72 87
73 action last_byte_is_not_immediate { 88 action last_byte_is_not_immediate {
74 instruction_info_collected |= LAST_BYTE_IS_NOT_IMMEDIATE; 89 instruction_info_collected |= LAST_BYTE_IS_NOT_IMMEDIATE;
75 } 90 }
76 91
77 action modifiable_instruction { 92 action modifiable_instruction {
78 instruction_info_collected |= MODIFIABLE_INSTRUCTION; 93 instruction_info_collected |= MODIFIABLE_INSTRUCTION;
79 } 94 }
80 95
81 action process_0_operands { 96 action process_0_operands {
82 process_0_operands(&restricted_register, &instruction_info_collected); 97 Process0Operands(&restricted_register, &instruction_info_collected);
83 } 98 }
84 action process_1_operand { 99 action process_1_operand {
85 process_1_operand(&restricted_register, &instruction_info_collected, 100 Process1Operand(&restricted_register, &instruction_info_collected,
86 rex_prefix, operand_states); 101 rex_prefix, operand_states);
87 } 102 }
88 action process_1_operand_zero_extends { 103 action process_1_operand_zero_extends {
89 process_1_operand_zero_extends(&restricted_register, 104 Process1OperandZeroExtends(&restricted_register,
90 &instruction_info_collected, rex_prefix, 105 &instruction_info_collected, rex_prefix,
91 operand_states); 106 operand_states);
92 } 107 }
93 action process_2_operands { 108 action process_2_operands {
94 process_2_operands(&restricted_register, &instruction_info_collected, 109 Process2Operands(&restricted_register, &instruction_info_collected,
95 rex_prefix, operand_states); 110 rex_prefix, operand_states);
96 } 111 }
97 action process_2_operands_zero_extends { 112 action process_2_operands_zero_extends {
98 process_2_operands_zero_extends(&restricted_register, 113 Process2OperandsZeroExtends(&restricted_register,
99 &instruction_info_collected, rex_prefix, 114 &instruction_info_collected, rex_prefix,
100 operand_states); 115 operand_states);
101 } 116 }
102 117
103 include decode_x86_64 "validator_x86_64_instruction.rl"; 118 include decode_x86_64 "validator_x86_64_instruction.rl";
104 119
105 data16condrep = (data16 | condrep data16 | data16 condrep); 120 data16condrep = (data16 | condrep data16 | data16 condrep);
106 data16rep = (data16 | rep data16 | data16 rep); 121 data16rep = (data16 | rep data16 | data16 rep);
107 122
108 # Special %rbp modifications without required sandboxing 123 # Special %rbp modifications—the ones which don't need a sandboxing.
124 #
125 # Note that there are two different opcodes for “mov”: “mov” with opcode
126 # “0x89” moves from “A” to “B” while “mov” with opcode “0x8b” moves from
127 # “B” to “A”.
109 rbp_modifications = 128 rbp_modifications =
110 (b_0100_10x0 0x89 0xe5) | # mov %rsp,%rbp 129 (b_0100_10x0 0x89 0xe5) | # mov %rsp,%rbp
111 (b_0100_10x0 0x8b 0xec) # | mov %rsp,%rbp 130 (b_0100_10x0 0x8b 0xec) # mov %rsp,%rbp
112 #(b_0100_1xx0 0x81 0xe5 any{3} (0x80 .. 0xff)) | # and $XXX,%rbp
113 #(b_0100_1xx0 0x83 0xe5 (0x80 .. 0xff)) # and $XXX,%rbp
114 @process_0_operands; 131 @process_0_operands;
115 132
116 # Special instructions used for %rbp sandboxing 133 # Special instructions used for %rbp sandboxing.
134 #
135 # This is the “second half” of the %rbp sandboxing. Any zero-extending
136 # instruction which stores the data in %ebp can be first part, but unlike
137 # the situation with other “normal” registers you can not just write to
138 # %ebp and continue: such activity MUST restore the status quo immediately
139 # via one of these instructions.
117 rbp_sandboxing = 140 rbp_sandboxing =
118 (b_0100_11x0 0x01 0xfd | # add %r15,%rbp 141 (b_0100_11x0 0x01 0xfd | # add %r15,%rbp
119 b_0100_10x1 0x03 0xef | # add %r15,%rbp 142 b_0100_10x1 0x03 0xef | # add %r15,%rbp
120 0x49 0x8d 0x2c 0x2f | # lea (%r15,%rbp,1),%rbp 143 0x49 0x8d 0x2c 0x2f | # lea (%r15,%rbp,1),%rbp
121 0x4a 0x8d 0x6c 0x3d 0x00) # lea 0x0(%rbp,%r15,1),%rbp 144 0x4a 0x8d 0x6c 0x3d 0x00) # lea 0x0(%rbp,%r15,1),%rbp
145 # “Normal” instructions detect an error when confronted with restricted
146 # register %rbp. These instructions require this state instead.
147 #
148 # Check this precondition and mark the beginning of the instruction as
149 # invalid jump for target.
122 @{ if (restricted_register == REG_RBP) 150 @{ if (restricted_register == REG_RBP)
123 instruction_info_collected |= RESTRICTED_REGISTER_USED; 151 instruction_info_collected |= RESTRICTED_REGISTER_USED;
124 else 152 else
125 instruction_info_collected |= UNRESTRICTED_RBP_PROCESSED; 153 instruction_info_collected |= UNRESTRICTED_RBP_PROCESSED;
126 restricted_register = NO_REG; 154 restricted_register = NO_REG;
127 BitmapClearBit(valid_targets, (instruction_start - data)); 155 MakeInvalidJumpTarget((instruction_start - data), valid_targets);
128 }; 156 };
129 157
130 # Special %rbp modifications without required sandboxing 158 # Special %rsp modifications—the ones which don't need a sandboxing.
159 #
160 # Note that there are two different opcodes for “mov”: “mov” with opcode
161 # “0x89” moves from “A” to “B” while “mov” with opcode “0x8b” moves from
162 # “B” to “A”.
131 rsp_modifications = 163 rsp_modifications =
132 (b_0100_10x0 0x89 0xec) | # mov %rbp,%rsp 164 (b_0100_10x0 0x89 0xec) | # mov %rbp,%rsp
133 (b_0100_10x0 0x8b 0xe5) | # mov %rbp,%rsp 165 (b_0100_10x0 0x8b 0xe5) | # mov %rbp,%rsp
134 #(b_0100_1xx0 0x81 0xe4 any{3} (0x80 .. 0xff)) | # and $XXX,%rsp 166 #(b_0100_1xx0 0x81 0xe4 any{3} (0x80 .. 0xff)) | # and $XXX,%rsp
135 #Superfluous bits are not supported: 167 #Superfluous bits are not supported:
136 # http://code.google.com/p/nativeclient/issues/detail?id=3012 168 # http://code.google.com/p/nativeclient/issues/detail?id=3012
137 (b_0100_1000 0x83 0xe4 (0x80 .. 0xff)) # and $XXX,%rsp 169 (b_0100_1000 0x83 0xe4 (0x80 .. 0xff)) # and $XXX,%rsp
138 @process_0_operands; 170 @process_0_operands;
139 171
140 # Special instructions used for %rbp sandboxing 172 # Special instructions used for %rsp sandboxing.
173 #
174 # This is the “second half” of the %rsp sandboxing. Any zero-extending
175 # instruction which stores the data in %esp can be first part, but unlike
176 # the situation with other “normal” registers you can not just write to
177 # %esp and continue: such activity MUST restore the status quo immediately
178 # via one of these instructions.
141 rsp_sandboxing = 179 rsp_sandboxing =
142 (b_0100_11x0 0x01 0xfc | # add %r15,%rsp 180 (b_0100_11x0 0x01 0xfc | # add %r15,%rsp
143 b_0100_10x1 0x03 0xe7 | # add %r15,%rbp 181 b_0100_10x1 0x03 0xe7 | # add %r15,%rsp
144 0x4a 0x8d 0x24 0x3c) # lea (%rsp,%r15,1),%rsp 182 0x4a 0x8d 0x24 0x3c) # lea (%rsp,%r15,1),%rsp
183 # “Normal” instructions detect an error when confronted with restricted
184 # register %rsp. These instructions require this state instead.
185 #
186 # Check this precondition and mark the beginning of the instruction as
187 # invalid jump for target.
145 @{ if (restricted_register == REG_RSP) 188 @{ if (restricted_register == REG_RSP)
146 instruction_info_collected |= RESTRICTED_REGISTER_USED; 189 instruction_info_collected |= RESTRICTED_REGISTER_USED;
147 else 190 else
148 instruction_info_collected |= UNRESTRICTED_RSP_PROCESSED; 191 instruction_info_collected |= UNRESTRICTED_RSP_PROCESSED;
149 restricted_register = NO_REG; 192 restricted_register = NO_REG;
150 BitmapClearBit(valid_targets, (instruction_start - data)); 193 MakeInvalidJumpTarget((instruction_start - data), valid_targets);
151 }; 194 };
152 195
153 # naclcall or nacljmp. Note: first "and $~0x1f, %eXX" is a normal instruction 196 # naclcall or nacljmp. These are three-instruction indirection-jump sequences.
154 # and as such will detect case where %rbp/%rsp is illegally modified. 197 # and $~0x1f, %eXX
198 # and RBASE, %rXX
199 # jmpq *%rXX (or: callq *%rXX)
200 # Note: first "and $~0x1f, %eXX" is a normal instruction and as such will
201 # detect case where %rbp/%rsp is illegally modified when this machine will be
202 # combined with normal_instruction machine.
203 #
204 # There are number of variants present which differ by the REX prefix usage:
205 # we need to make sure “%eXX” in “and”, “%rXX” in “add”, and “%eXX” in “jmpq”
206 # or “callq” is the same register and it's much simpler to do if one single
207 # action handles only fixed number of bytes.
208 #
209 # Additional complication arises because x86-64 contains two different “add”
210 # instruction: with “0x01” and “0x03” opcode. They differ in the direction
211 # used: both can add “A” and “B” but one of them stores the result in “A” and
212 # other stores the result in “B” (see AMD/Intel manual for clarification).
213 # Both should be allowed.
214 #
215 # REGISTER USAGE ABBREVIATIONS:
216 # E86: legacy ia32 registers (all eight: %eax to %edi)
217 # R86: 64-bit counterparts for legacy 386 registers (%rax to %rdi)
218 # E64: 32-bit counterparts for new amd64 registers (%r8d to %r14d)
219 # R64: new amd64 registers (only seven: %r8 to %r14)
220 # RBASE: %r15 (used as “base of untrusted world” in NaCl for amd64)
155 naclcall_or_nacljmp = 221 naclcall_or_nacljmp =
156 # and $~0x1f, %eax/%ecx/%edx/%ebx/%esp/%ebp/%esi/%edi 222 # This block encodes call and jump superinstructions of the form:
157 (0x83 (0xe0|0xe1|0xe2|0xe3|0xe4|0xe5|0xe6|0xe7) 0xe0 223 # 0: 83 e_ e0 and $~0x1f,E86
158 # add %r15,%rax/%rcx/%rdx/%rbx/%rsp/%rbp/%rsi/%rdi 224 # 3: 4_ 01 f_ add RBASE,R86
159 b_0100_11x0 0x01 (0xf8|0xf9|0xfa|0xfb|0xfc|0xfd|0xfe|0xff) 225 # 6: ff e_ jmpq *R86
160 # callq %rax/%rcx/%rdx/%rbx/%rsp/%rbp/%rsi/%rdi 226 #### INSTRUCTION ONE (three bytes)
161 ((REX_WRX? 0xff (0xd0|0xd1|0xd2|0xd3|0xd4|0xd5|0xd6|0xd7)) | 227 # and $~0x1f, E86
162 # jmpq %rax/%rcx/%rdx/%rbx/%rsp/%rbp/%rsi/%rdi 228 (0x83 b_11_100_xxx 0xe0
163 (REX_WRX? 0xff (0xe0|0xe1|0xe2|0xe3|0xe4|0xe5|0xe6|0xe7)))) 229 #### INSTRUCTION TWO (three bytes)
164 @{ 230 # add RBASE, R86 (0x01 opcode)
165 instruction_start -= 6; 231 b_0100_11x0 0x01 b_11_111_xxx
166 if (RMFromModRM(instruction_start[1]) != 232 #### INSTRUCTION THREE: call (two bytes plus optional REX prefix)
167 RMFromModRM(instruction_start[5]) || 233 # callq R86
168 RMFromModRM(instruction_start[1]) != RMFromModRM(*current_position)) 234 ((REX_WRX? 0xff b_11_010_xxx) |
169 instruction_info_collected |= UNRECOGNIZED_INSTRUCTION; 235 #### INSTRUCTION THREE: jmp (two bytes plus optional REX prefix)
170 BitmapClearBit(valid_targets, (instruction_start - data) + 3); 236 # jmpq R86
171 BitmapClearBit(valid_targets, (instruction_start - data) + 6); 237 (REX_WRX? 0xff b_11_100_xxx)))
172 restricted_register = NO_REG; 238 @{
173 } | 239 ProcessNaclCallOrJmpAddToRMNoRex(&instruction_info_collected,
240 &instruction_start, current_position,
241 data, valid_targets);
242 } |
174 243
175 # and $~0x1f, %eax/%ecx/%edx/%ebx/%esp/%ebp/%esi/%edi 244 # This block encodes call and jump superinstructions of the form:
176 (0x83 (0xe0|0xe1|0xe2|0xe3|0xe4|0xe5|0xe6|0xe7) 0xe0 245 # 0: 83 e_ e0 and $~0x1f,E86
177 # add %r15,%rax/%rcx/%rdx/%rbx/%rsp/%rbp/%rsi/%rdi 246 # 3: 4_ 03 f_ add RBASE,R86
178 b_0100_10x1 0x03 (0xc7|0xcf|0xd7|0xdf|0xe7|0xef|0xf7|0xff) 247 # 6: ff e_ jmpq *R86
179 # callq %rax/%rcx/%rdx/%rbx/%rsp/%rbp/%rsi/%rdi 248 #### INSTRUCTION ONE (three bytes)
180 ((REX_WRX? 0xff (0xd0|0xd1|0xd2|0xd3|0xd4|0xd5|0xd6|0xd7)) | 249 # and $~0x1f, E86
181 # jmpq %rax/%rcx/%rdx/%rbx/%rsp/%rbp/%rsi/%rdi 250 (0x83 b_11_100_xxx 0xe0
182 (REX_WRX? 0xff (0xe0|0xe1|0xe2|0xe3|0xe4|0xe5|0xe6|0xe7)))) 251 #### INSTRUCTION TWO (three bytes)
183 @{ 252 # add RBASE, R86 (0x03 opcode)
184 instruction_start -= 6; 253 b_0100_10x1 0x03 b_11_xxx_111
185 if (RMFromModRM(instruction_start[1]) != 254 #### INSTRUCTION THREE: call (two bytes plus optional REX prefix)
186 RegFromModRM(instruction_start[5]) || 255 # callq R86
187 RMFromModRM(instruction_start[1]) != RMFromModRM(*current_position)) 256 ((REX_WRX? 0xff b_11_010_xxx) |
188 instruction_info_collected |= UNRECOGNIZED_INSTRUCTION; 257 #### INSTRUCTION THREE: jmp (two bytes plus optional REX prefix)
189 BitmapClearBit(valid_targets, (instruction_start - data) + 3); 258 # jmpq R86
190 BitmapClearBit(valid_targets, (instruction_start - data) + 6); 259 (REX_WRX? 0xff b_11_100_xxx)))
191 restricted_register = NO_REG; 260 @{
192 } | 261 ProcessNaclCallOrJmpAddToRegNoRex(&instruction_info_collected,
262 &instruction_start, current_position,
263 data, valid_targets);
264 } |
193 265
194 # rex.R?X? and $~0x1f, %eax/%ecx/%edx/%ebx/%esp/%ebp/%esi/%edi 266 # This block encodes call and jump superinstructions of the form:
195 ((REX_RX 0x83 (0xe0|0xe1|0xe2|0xe3|0xe4|0xe5|0xe6|0xe7) 0xe0 267 # 0: 4_ 83 e_ e0 and $~0x1f,E86
196 # add %r15,%rax/%rcx/%rdx/%rbx/%rsp/%rbp/%rsi/%rdi 268 # 4: 4_ 01 f_ add RBASE,R86
197 b_0100_11x0 0x01 (0xf8|0xf9|0xfa|0xfb|0xfc|0xfd|0xfe|0xff) 269 # 7: ff e_ jmpq *R86
198 # callq %rax/%rcx/%rdx/%rbx/%rsp/%rbp/%rsi/%rdi 270 #### INSTRUCTION ONE (four bytes)
199 ((REX_WRX? 0xff (0xd0|0xd1|0xd2|0xd3|0xd4|0xd5|0xd6|0xd7)) | 271 # and $~0x1f, E86
200 # jmpq %rax/%rcx/%rdx/%rbx/%rsp/%rbp/%rsi/%rdi 272 ((REX_RX 0x83 b_11_100_xxx 0xe0
201 (REX_WRX? 0xff (0xe0|0xe1|0xe2|0xe3|0xe4|0xe5|0xe6|0xe7)))) | 273 #### INSTRUCTION TWO (three bytes)
274 # add RBASE, R86 (0x01 opcode)
275 b_0100_11x0 0x01 b_11_111_xxx
276 #### INSTRUCTION THREE: call (two bytes plus optional REX prefix)
277 # callq R86
278 ((REX_WRX? 0xff b_11_010_xxx) |
279 #### INSTRUCTION THREE: jmp (two bytes plus optional REX prefix)
280 # jmpq R86
281 (REX_WRX? 0xff b_11_100_xxx))) |
202 282
203 # and $~0x1f, %r8d/%r9d/%r10d/%r11d/%r12d/%r13d/%r14d 283 # This block encodes call and jump superinstructions of the form:
204 (b_0100_0xx1 0x83 (0xe0|0xe1|0xe2|0xe3|0xe4|0xe5|0xe6) 0xe0 284 # 0: 4_ 83 e_ e0 and $~0x1f,E64
205 # add %r15, %r8d/%r9d/%r10d/%r11d/%r12d/%r13d/%r14d 285 # 4: 4_ 01 f_ add RBASE,R64
206 b_0100_11x1 0x01 (0xf8|0xf9|0xfa|0xfb|0xfc|0xfd|0xfe) 286 # 7: 4_ ff e_ jmpq *R64
207 # callq %r8/%r9/%r10/%r11/%r12/%r13/%r14 287 #### INSTRUCTION ONE (four bytes)
208 ((b_0100_xxx1 0xff (0xd0|0xd1|0xd2|0xd3|0xd4|0xd5|0xd6)) | 288 # and $~0x1f, E64
209 # jmpq %r8/%r9/%r10/%r11/%r12/%r13/%r14 289 (b_0100_0xx1 0x83 (b_11_100_xxx - b_11_100_111) 0xe0
210 (b_0100_xxx1 0xff (0xe0|0xe1|0xe2|0xe3|0xe4|0xe5|0xe6))))) 290 #### INSTRUCTION TWO (three bytes)
211 @{ 291 # add RBASE, R64 (0x01 opcode)
212 instruction_start -= 7; 292 b_0100_11x1 0x01 (b_11_111_xxx - b_11_111_111)
213 if (RMFromModRM(instruction_start[2]) != 293 #### INSTRUCTION THREE: call (three bytes)
214 RMFromModRM(instruction_start[6]) || 294 # callq R64
215 RMFromModRM(instruction_start[2]) != RMFromModRM(*current_position)) 295 ((b_0100_xxx1 0xff (b_11_010_xxx - b_11_010_111)) |
216 instruction_info_collected |= UNRECOGNIZED_INSTRUCTION; 296 #### INSTRUCTION THREE: jmp (three bytes)
217 BitmapClearBit(valid_targets, (instruction_start - data) + 4); 297 # jmpq R64
218 BitmapClearBit(valid_targets, (instruction_start - data) + 7); 298 (b_0100_xxx1 0xff (b_11_100_xxx - b_11_100_111)))))
219 restricted_register = NO_REG; 299 @{
220 } | 300 ProcessNaclCallOrJmpAddToRMWithRex(&instruction_info_collected,
301 &instruction_start, current_position,
302 data, valid_targets);
303 } |
221 304
222 # rex.R?X? and $~0x1f, %eax/%ecx/%edx/%ebx/%esp/%ebp/%esi/%edi 305 # This block encodes call and jump superinstructions of the form:
223 ((REX_RX 0x83 (0xe0|0xe1|0xe2|0xe3|0xe4|0xe5|0xe6|0xe7) 0xe0 306 # 0: 4_ 83 e_ e0 and $~0x1f,E86
224 # add %r15,%rax/%rcx/%rdx/%rbx/%rsp/%rbp/%rsi/%rdi 307 # 4: 4_ 03 f_ add RBASE,R86
225 b_0100_10x1 0x03 (0xc7|0xcf|0xd7|0xdf|0xe7|0xef|0xf7|0xff) 308 # 7: ff e_ jmpq *R86
226 # callq %rax/%rcx/%rdx/%rbx/%rsp/%rbp/%rsi/%rdi 309 #### INSTRUCTION ONE (four bytes)
227 ((REX_WRX? 0xff (0xd0|0xd1|0xd2|0xd3|0xd4|0xd5|0xd6|0xd7)) | 310 # and $~0x1f, E86
228 # jmpq %rax/%rcx/%rdx/%rbx/%rsp/%rbp/%rsi/%rdi 311 ((REX_RX 0x83 b_11_100_xxx 0xe0
229 (REX_WRX? 0xff (0xe0|0xe1|0xe2|0xe3|0xe4|0xe5|0xe6|0xe7)))) | 312 #### INSTRUCTION TWO (three bytes)
313 # add RBASE, R86 (0x03 opcode)
314 b_0100_10x1 0x03 b_11_xxx_111
315 #### INSTRUCTION THREE: call (two bytes plus optional REX prefix)
316 # callq R86
317 ((REX_WRX? 0xff b_11_010_xxx) |
318 #### INSTRUCTION THREE: jmp (two bytes plus optional REX prefix)
319 # jmpq R86
320 (REX_WRX? 0xff b_11_100_xxx))) |
230 321
231 # and $~0x1f, %r8d/%r9d/%r10d/%r11d/%r12d/%r13d/%r14d 322 # This block encodes call and jump superinstructions of the form:
232 (b_0100_0xx1 0x83 (0xe0|0xe1|0xe2|0xe3|0xe4|0xe5|0xe6) 0xe0 323 # 0: 4_ 83 e_ e0 and $~0x1f,E64
233 # add %r15, %r8d/%r9d/%r10d/%r11d/%r12d/%r13d/%r14d 324 # 4: 4_ 03 f_ add RBASE,R64
234 b_0100_11x1 0x03 (0xc7|0xcf|0xd7|0xdf|0xe7|0xef|0xf7) 325 # 7: 4_ ff e_ jmpq *R64
235 # callq %r8/%r9/%r10/%r11/%r12/%r13/%r14 326 #### INSTRUCTION ONE (four bytes)
236 ((b_0100_xxx1 0xff (0xd0|0xd1|0xd2|0xd3|0xd4|0xd5|0xd6)) | 327 # and $~0x1f, E64
237 # jmpq %r8/%r9/%r10/%r11/%r12/%r13/%r14 328 (b_0100_0xx1 0x83 (b_11_100_xxx - b_11_100_111) 0xe0
238 (b_0100_xxx1 0xff (0xe0|0xe1|0xe2|0xe3|0xe4|0xe5|0xe6))))) 329 #### INSTRUCTION TWO (three bytes)
239 @{ 330 # add RBASE, R64 (0x03 opcode)
240 instruction_start -= 7; 331 b_0100_11x1 0x03 (b_11_xxx_111 - b_11_111_111)
241 if (RMFromModRM(instruction_start[2]) != 332 #### INSTRUCTION THREE: call (three bytes)
242 RegFromModRM(instruction_start[6]) || 333 # callq R64
243 RMFromModRM(instruction_start[2]) != RMFromModRM(*current_position)) 334 ((b_0100_xxx1 0xff (b_11_010_xxx - b_11_010_111)) |
244 instruction_info_collected |= UNRECOGNIZED_INSTRUCTION; 335 #### INSTRUCTION THREE: jmp (three bytes)
245 BitmapClearBit(valid_targets, (instruction_start - data) + 4); 336 # jmpq R64
246 BitmapClearBit(valid_targets, (instruction_start - data) + 7); 337 (b_0100_xxx1 0xff (b_11_100_xxx - b_11_100_111)))))
247 restricted_register = NO_REG; 338 @{
248 }; 339 ProcessNaclCallOrJmpAddToRegWithRex(&instruction_info_collected,
340 &instruction_start, current_position,
341 data, valid_targets);
342 };
249 343
250 # EMMS/SSE2/AVX instructions which have implicit %ds:(%rsi) operand 344 # EMMS/SSE2/AVX instructions which have implicit %ds:(%rsi) operand
251 # maskmovq %mmX,%mmY 345 # maskmovq %mmX,%mmY
252 maskmovq = 346 maskmovq =
253 REX_WRXB? (0x0f 0xf7) 347 REX_WRXB? (0x0f 0xf7)
254 @CPUFeature_EMMX modrm_registers; 348 @CPUFeature_EMMX modrm_registers;
255 # maskmovdqu %xmmX, %xmmY 349 # maskmovdqu %xmmX, %xmmY
256 maskmovdqu = 350 maskmovdqu =
257 0x66 REX_WRXB? (0x0f 0xf7) @not_data16_prefix 351 0x66 REX_WRXB? (0x0f 0xf7) @not_data16_prefix
258 @CPUFeature_SSE2 modrm_registers; 352 @CPUFeature_SSE2 modrm_registers;
259 # vmaskmovdqu %xmmX, %xmmY 353 # vmaskmovdqu %xmmX, %xmmY
260 vmaskmovdqu = 354 vmaskmovdqu =
261 ((0xc4 (VEX_RB & VEX_map00001) 0x79 @vex_prefix3) | 355 ((0xc4 (VEX_RB & VEX_map00001) 0x79 @vex_prefix3) |
262 (0xc5 (0x79 | 0xf9) @vex_prefix_short)) 0xf7 356 (0xc5 (0x79 | 0xf9) @vex_prefix_short)) 0xf7
263 @CPUFeature_AVX modrm_registers; 357 @CPUFeature_AVX modrm_registers;
264 mmx_sse_rdi_instruction = maskmovq | maskmovdqu | vmaskmovdqu; 358 mmx_sse_rdi_instruction = maskmovq | maskmovdqu | vmaskmovdqu;
265 359
266 # String instructions which use only %ds:(%rsi) 360 # String instructions which use only %ds:(%rsi)
267 string_instruction_rsi_no_rdi = 361 string_instruction_rsi_no_rdi =
268 (rep? 0xac | # lods %ds:(%rsi),%al 362 (rep? 0xac | # lods %ds:(%rsi),%al
269 data16rep 0xad | # lods %ds:(%rsi),%ax 363 data16rep 0xad | # lods %ds:(%rsi),%ax
270 rep? REXW_NONE? 0xad) ; # lods %ds:(%rsi),%eax/%rax 364 rep? REXW_NONE? 0xad); # lods %ds:(%rsi),%eax/%rax
271 365
272 # String instructions which use only %ds:(%rdi) 366 # String instructions which use only %ds:(%rdi)
273 string_instruction_rdi_no_rsi = 367 string_instruction_rdi_no_rsi =
274 condrep? 0xae | # scas %es:(%rdi),%al 368 condrep? 0xae | # scas %es:(%rdi),%al
275 data16condrep 0xaf | # scas %es:(%rdi),%ax 369 data16condrep 0xaf | # scas %es:(%rdi),%ax
276 condrep? REXW_NONE? 0xaf | # scas %es:(%rdi),%eax/%rax 370 condrep? REXW_NONE? 0xaf | # scas %es:(%rdi),%eax/%rax
277 371
278 rep? 0xaa | # stos %al,%es:(%rdi) 372 rep? 0xaa | # stos %al,%es:(%rdi)
279 data16rep 0xab | # stos %ax,%es:(%rdi) 373 data16rep 0xab | # stos %ax,%es:(%rdi)
280 rep? REXW_NONE? 0xab ; # stos %eax/%rax,%es:(%rdi) 374 rep? REXW_NONE? 0xab; # stos %eax/%rax,%es:(%rdi)
281 375
282 # String instructions which use both %ds:(%rsi) and %ds:(%rdi) 376 # String instructions which use both %ds:(%rsi) and %ds:(%rdi)
283 string_instruction_rsi_rdi = 377 string_instruction_rsi_rdi =
284 condrep? 0xa6 | # cmpsb %es:(%rdi),%ds:(%rsi) 378 condrep? 0xa6 | # cmpsb %es:(%rdi),%ds:(%rsi)
285 data16condrep 0xa7 | # cmpsw %es:(%rdi),%ds:(%rsi) 379 data16condrep 0xa7 | # cmpsw %es:(%rdi),%ds:(%rsi)
286 condrep? REXW_NONE? 0xa7 | # cmps[lq] %es:(%rdi),%ds:(%rsi) 380 condrep? REXW_NONE? 0xa7 | # cmps[lq] %es:(%rdi),%ds:(%rsi)
287 381
288 rep? 0xa4 | # movsb %es:(%rdi),%ds:(%rsi) 382 rep? 0xa4 | # movsb %es:(%rdi),%ds:(%rsi)
289 data16rep 0xa5 | # movsw %es:(%rdi),%ds:(%rsi) 383 data16rep 0xa5 | # movsw %es:(%rdi),%ds:(%rsi)
290 rep? REXW_NONE? 0xa5 ; # movs[lq] %es:(%rdi),%ds:(%rsi) 384 rep? REXW_NONE? 0xa5; # movs[lq] %es:(%rdi),%ds:(%rsi)
291 385
386 # Superinstruction which handle instructions which require sandboxed %rsi.
387 #
388 # There are two variants which handle spurious REX prefixes.
389 #
390 # Note that both “0x89 0xf6” and “0x8b 0xf6” encode “mov %esi,%esi”:
391 # “mov” with opcode “0x89” moves from “A” to “B” while “mov” with opcode
392 # “0x8b” moves from “B” to “A” but when “A” and “B” happen to denote the
393 # same register there are no functional difference between these opcodes.
292 sandbox_instruction_rsi_no_rdi = 394 sandbox_instruction_rsi_no_rdi =
293 (0x89 | 0x8b) 0xf6 . # mov %esi,%esi 395 (0x89 | 0x8b) 0xf6 # mov %esi,%esi
294 0x49 0x8d 0x34 0x37 . # lea (%r15,%rsi,1),%rsi 396 0x49 0x8d 0x34 0x37 # lea (%r15,%rsi,1),%rsi
295 string_instruction_rsi_no_rdi 397 string_instruction_rsi_no_rdi
296 @{ 398 @{
297 instruction_start -= 6; 399 SandboxRxiSuperInstNoRexOnMov(&instruction_start, data, valid_targets);
298 BitmapClearBit(valid_targets, (instruction_start - data) + 2);
299 BitmapClearBit(valid_targets, (instruction_start - data) + 6);
300 restricted_register = NO_REG;
301 } | 400 } |
302 401
303 REX_X (0x89 | 0x8b) 0xf6 . # mov %esi,%esi 402 REX_X (0x89 | 0x8b) 0xf6 # mov %esi,%esi
304 0x49 0x8d 0x34 0x37 . # lea (%r15,%rsi,1),%rsi 403 0x49 0x8d 0x34 0x37 # lea (%r15,%rsi,1),%rsi
305 string_instruction_rsi_no_rdi 404 string_instruction_rsi_no_rdi
306 @{ 405 @{
307 instruction_start -= 7; 406 SandboxRxiSuperInstWithRexOnMov(&instruction_start, data, valid_targets);
308 BitmapClearBit(valid_targets, (instruction_start - data) + 3);
309 BitmapClearBit(valid_targets, (instruction_start - data) + 7);
310 restricted_register = NO_REG;
311 }; 407 };
312 408
409 # Superinstruction which handle instructions which require sandboxed %rdi.
410 #
411 # There are two variants which handle spurious REX prefixes.
412 #
413 # Note that both “0x89 0xff” and “0x8b 0xff” encode “mov %edi,%edi”:
414 # “mov” with opcode “0x89” moves from “A” to “B” while “mov” with opcode
415 # “0x8b” moves from “B” to “A” but when “A” and “B” happen to denote the
416 # same register there are no functional difference between these opcodes.
313 sandbox_instruction_rdi_no_rsi = 417 sandbox_instruction_rdi_no_rsi =
314 (0x89 | 0x8b) 0xff . # mov %edi,%edi 418 (0x89 | 0x8b) 0xff # mov %edi,%edi
315 0x49 0x8d 0x3c 0x3f . # lea (%r15,%rdi,1),%rdi 419 0x49 0x8d 0x3c 0x3f # lea (%r15,%rdi,1),%rdi
316 (string_instruction_rdi_no_rsi | mmx_sse_rdi_instruction) 420 (string_instruction_rdi_no_rsi | mmx_sse_rdi_instruction)
317 @{ 421 @{
318 instruction_start -= 6; 422 SandboxRxiSuperInstNoRexOnMov(&instruction_start, data, valid_targets);
319 BitmapClearBit(valid_targets, (instruction_start - data) + 2);
320 BitmapClearBit(valid_targets, (instruction_start - data) + 6);
321 restricted_register = NO_REG;
322 } | 423 } |
323 424
324 REX_X (0x89 | 0x8b) 0xff . # mov %edi,%edi 425 REX_X (0x89 | 0x8b) 0xff # mov %edi,%edi
325 0x49 0x8d 0x3c 0x3f . # lea (%r15,%rdi,1),%rdi 426 0x49 0x8d 0x3c 0x3f # lea (%r15,%rdi,1),%rdi
326 (string_instruction_rdi_no_rsi | mmx_sse_rdi_instruction) 427 (string_instruction_rdi_no_rsi | mmx_sse_rdi_instruction)
327 @{ 428 @{
328 instruction_start -= 7; 429 SandboxRxiSuperInstWithRexOnMov(&instruction_start, data, valid_targets);
329 BitmapClearBit(valid_targets, (instruction_start - data) + 3);
330 BitmapClearBit(valid_targets, (instruction_start - data) + 7);
331 restricted_register = NO_REG;
332 }; 430 };
333 431
334 432
335 # String instructions which use both %ds:(%rsi) and %ds:(%rdi) 433 # Superinstruction which handle instructions which require both sandboxed %rsi
434 # and sandboxed %rdi.
435 #
436 # There are four variants which handle spurious REX prefixes.
437 #
438 # Note that both “0x89 0xf6” and “0x8b 0xf6” encode “mov %esi,%esi” while both
439 # “0x89 0xff” and “0x8b 0xff” encode “mov %edi,%edi”: “mov” with opcode “0x89”
440 # moves from “A” to “B” while “mov” with opcode “0x8b” moves from “B” to “A”
441 # but when “A” and “B” happen to denote the same register there are no
442 # functional difference between these opcodes.
443 #
444 # Note: we call SandboxRxiSuperInst in actions here twice because we have two
445 # sandboxings here - one for %rsi and one for %rdi.
336 sandbox_instruction_rsi_rdi = 446 sandbox_instruction_rsi_rdi =
337 (0x89 | 0x8b) 0xf6 . # mov %esi,%esi 447 (0x89 | 0x8b) 0xf6 # mov %esi,%esi
338 0x49 0x8d 0x34 0x37 . # lea (%r15,%rsi,1),%rsi 448 0x49 0x8d 0x34 0x37 # lea (%r15,%rsi,1),%rsi
339 (0x89 | 0x8b) 0xff . # mov %edi,%edi 449 (0x89 | 0x8b) 0xff # mov %edi,%edi
340 0x49 0x8d 0x3c 0x3f . # lea (%r15,%rdi,1),%rdi 450 0x49 0x8d 0x3c 0x3f # lea (%r15,%rdi,1),%rdi
341 string_instruction_rsi_rdi 451 string_instruction_rsi_rdi
342 @{ 452 @{
343 instruction_start -= 12; 453 SandboxRxiSuperInstNoRexOnMov(&instruction_start, data, valid_targets);
344 BitmapClearBit(valid_targets, (instruction_start - data) + 2); 454 SandboxRxiSuperInstNoRexOnMov(&instruction_start, data, valid_targets);
345 BitmapClearBit(valid_targets, (instruction_start - data) + 6);
346 BitmapClearBit(valid_targets, (instruction_start - data) + 8);
347 BitmapClearBit(valid_targets, (instruction_start - data) + 12);
348 restricted_register = NO_REG;
349 } | 455 } |
350 456
351 (0x89 | 0x8b) 0xf6 . # mov %esi,%esi 457 (0x89 | 0x8b) 0xf6 # mov %esi,%esi
352 0x49 0x8d 0x34 0x37 . # lea (%r15,%rsi,1),%rsi 458 0x49 0x8d 0x34 0x37 # lea (%r15,%rsi,1),%rsi
353 REX_X (0x89 | 0x8b) 0xff . # mov %edi,%edi 459 REX_X (0x89 | 0x8b) 0xff # mov %edi,%edi
354 0x49 0x8d 0x3c 0x3f . # lea (%r15,%rdi,1),%rdi 460 0x49 0x8d 0x3c 0x3f # lea (%r15,%rdi,1),%rdi
355 string_instruction_rsi_rdi 461 string_instruction_rsi_rdi
356 @{ 462 @{
357 instruction_start -= 13; 463 SandboxRxiSuperInstWithRexOnMov(&instruction_start, data, valid_targets);
358 BitmapClearBit(valid_targets, (instruction_start - data) + 2); 464 SandboxRxiSuperInstNoRexOnMov(&instruction_start, data, valid_targets);
359 BitmapClearBit(valid_targets, (instruction_start - data) + 6);
360 BitmapClearBit(valid_targets, (instruction_start - data) + 9);
361 BitmapClearBit(valid_targets, (instruction_start - data) + 13);
362 restricted_register = NO_REG;
363 } | 465 } |
364 466
365 REX_X (0x89 | 0x8b) 0xf6 . # mov %esi,%esi 467 REX_X (0x89 | 0x8b) 0xf6 # mov %esi,%esi
366 0x49 0x8d 0x34 0x37 . # lea (%r15,%rsi,1),%rsi 468 0x49 0x8d 0x34 0x37 # lea (%r15,%rsi,1),%rsi
367 (0x89 | 0x8b) 0xff . # mov %edi,%edi 469 (0x89 | 0x8b) 0xff # mov %edi,%edi
368 0x49 0x8d 0x3c 0x3f . # lea (%r15,%rdi,1),%rdi 470 0x49 0x8d 0x3c 0x3f # lea (%r15,%rdi,1),%rdi
369 string_instruction_rsi_rdi 471 string_instruction_rsi_rdi
370 @{ 472 @{
371 instruction_start -= 13; 473 SandboxRxiSuperInstNoRexOnMov(&instruction_start, data, valid_targets);
372 BitmapClearBit(valid_targets, (instruction_start - data) + 3); 474 SandboxRxiSuperInstWithRexOnMov(&instruction_start, data, valid_targets);
373 BitmapClearBit(valid_targets, (instruction_start - data) + 7);
374 BitmapClearBit(valid_targets, (instruction_start - data) + 9);
375 BitmapClearBit(valid_targets, (instruction_start - data) + 13);
376 restricted_register = NO_REG;
377 } | 475 } |
378 476
379 REX_X (0x89 | 0x8b) 0xf6 . # mov %esi,%esi 477 REX_X (0x89 | 0x8b) 0xf6 # mov %esi,%esi
380 0x49 0x8d 0x34 0x37 . # lea (%r15,%rsi,1),%rsi 478 0x49 0x8d 0x34 0x37 # lea (%r15,%rsi,1),%rsi
381 REX_X (0x89 | 0x8b) 0xff . # mov %edi,%edi 479 REX_X (0x89 | 0x8b) 0xff # mov %edi,%edi
382 0x49 0x8d 0x3c 0x3f . # lea (%r15,%rdi,1),%rdi 480 0x49 0x8d 0x3c 0x3f # lea (%r15,%rdi,1),%rdi
383 string_instruction_rsi_rdi 481 string_instruction_rsi_rdi
384 @{ 482 @{
385 instruction_start -= 14; 483 SandboxRxiSuperInstWithRexOnMov(&instruction_start, data, valid_targets);
386 BitmapClearBit(valid_targets, (instruction_start - data) + 3); 484 SandboxRxiSuperInstWithRexOnMov(&instruction_start, data, valid_targets);
387 BitmapClearBit(valid_targets, (instruction_start - data) + 7);
388 BitmapClearBit(valid_targets, (instruction_start - data) + 10);
389 BitmapClearBit(valid_targets, (instruction_start - data) + 14);
390 restricted_register = NO_REG;
391 }; 485 };
392 486
393 special_instruction = 487 special_instruction =
394 (rbp_modifications | 488 (rbp_modifications |
395 rsp_modifications | 489 rsp_modifications |
396 rbp_sandboxing | 490 rbp_sandboxing |
397 rsp_sandboxing | 491 rsp_sandboxing |
398 naclcall_or_nacljmp | 492 naclcall_or_nacljmp |
399 sandbox_instruction_rsi_no_rdi | 493 sandbox_instruction_rsi_no_rdi |
400 sandbox_instruction_rdi_no_rsi | 494 sandbox_instruction_rdi_no_rsi |
401 sandbox_instruction_rsi_rdi) 495 sandbox_instruction_rsi_rdi)
496 # Mark the instruction as special—currently this information is used only in
497 # tests, but in the future we may use it for dynamic code modification
498 # support.
402 @{ 499 @{
403 instruction_info_collected |= SPECIAL_INSTRUCTION; 500 instruction_info_collected |= SPECIAL_INSTRUCTION;
404 }; 501 };
405 502
406 # Remove special instructions which are only allowed in special cases. 503 # Remove special instructions which are only allowed in special cases.
407 normal_instruction = one_instruction - special_instruction; 504 normal_instruction = one_instruction - special_instruction;
408 505
409 # Check if call is properly aligned 506 # Check if call is properly aligned.
507 #
508 # For direct call we explicitly encode all variations. For indirect call
509 # we accept all the special instructions which ends with indirect call.
410 call_alignment = 510 call_alignment =
411 ((normal_instruction & 511 ((normal_instruction &
412 # Direct call 512 # Direct call
413 ((data16 REX_RXB? 0xe8 rel16) | 513 ((data16 REX_RXB? 0xe8 rel16) |
414 (REX_WRXB? 0xe8 rel32) | 514 (REX_WRXB? 0xe8 rel32) |
415 (data16 REXW_RXB 0xe8 rel32))) | 515 (data16 REXW_RXB 0xe8 rel32))) |
416 (special_instruction & 516 (special_instruction &
417 # Indirect call 517 # Indirect call
418 (any* data16? REX_WRXB? 0xff ((opcode_2 | opcode_3) any* & 518 (any* data16? REX_WRXB? 0xff ((opcode_2 | opcode_3) any* &
419 (modrm_memory | modrm_registers))))) 519 (modrm_memory | modrm_registers)))))
520 # Call instruction must aligned to the end of bundle. Previously this was
521 # strict requirement, today it's just warning to aid with debugging.
420 @{ 522 @{
421 if (((current_position - data) & kBundleMask) != kBundleMask) 523 if (((current_position - data) & kBundleMask) != kBundleMask)
422 instruction_info_collected |= BAD_CALL_ALIGNMENT; 524 instruction_info_collected |= BAD_CALL_ALIGNMENT;
423 }; 525 };
424 526
425 527
426 main := ((call_alignment | normal_instruction | special_instruction) 528 main := ((call_alignment | normal_instruction | special_instruction)
529 # Beginning of the instruction is always valid target for jump. If this
530 # instruction is, in fact, part of the superinstruction then we'll clear
531 # that bit later.
427 >{ 532 >{
428 BitmapSetBit(valid_targets, current_position - data); 533 MakeJumpTargetValid(current_position - data, valid_targets);
429 } 534 }
535 # Here we call the user callback if there are validation errors or if the
536 # CALL_USER_CALLBACK_ON_EACH_INSTRUCTION option is used.
537 #
538 # After that we move instruction_start and clean all the variables which
539 # only used in the processing of a single instruction (prefixes, operand
540 # states and instruction_info_collected).
430 @{ 541 @{
431 if ((instruction_info_collected & VALIDATION_ERRORS_MASK) || 542 if ((instruction_info_collected & VALIDATION_ERRORS_MASK) ||
432 (options & CALL_USER_CALLBACK_ON_EACH_INSTRUCTION)) { 543 (options & CALL_USER_CALLBACK_ON_EACH_INSTRUCTION)) {
433 result &= user_callback( 544 result &= user_callback(
434 instruction_start, current_position, 545 instruction_start, current_position,
435 instruction_info_collected | 546 instruction_info_collected |
436 ((restricted_register << RESTRICTED_REGISTER_SHIFT) & 547 ((restricted_register << RESTRICTED_REGISTER_SHIFT) &
437 RESTRICTED_REGISTER_MASK), callback_data); 548 RESTRICTED_REGISTER_MASK), callback_data);
438 } 549 }
439 /* On successful match the instruction start must point to the next byte 550 /* On successful match the instruction start must point to the next byte
440 * to be able to report the new offset as the start of instruction 551 * to be able to report the new offset as the start of instruction
441 * causing error. */ 552 * causing error. */
442 instruction_start = current_position + 1; 553 instruction_start = current_position + 1;
443 instruction_info_collected = 0; 554 instruction_info_collected = 0;
444 SET_REX_PREFIX(FALSE); 555 SET_REX_PREFIX(FALSE);
556 /* Top three bis of VEX2 are inverted: see AMD/Intel manual. */
445 SET_VEX_PREFIX2(0xe0); 557 SET_VEX_PREFIX2(0xe0);
446 SET_VEX_PREFIX3(0x00); 558 SET_VEX_PREFIX3(0x00);
447 operand_states = 0; 559 operand_states = 0;
448 })* 560 })*
449 $err{ 561 $err{
450 result &= user_callback(instruction_start, current_position, 562 result &= user_callback(instruction_start, current_position,
451 UNRECOGNIZED_INSTRUCTION, callback_data); 563 UNRECOGNIZED_INSTRUCTION, callback_data);
452 continue; 564 continue;
453 }; 565 };
454 566
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
532 user_callback, callback_data); 644 user_callback, callback_data);
533 645
534 /* We only use malloc for a large code sequences */ 646 /* We only use malloc for a large code sequences */
535 if (size > sizeof valid_targets_small) { 647 if (size > sizeof valid_targets_small) {
536 free(jump_dests); 648 free(jump_dests);
537 free(valid_targets); 649 free(valid_targets);
538 } 650 }
539 if (!result) errno = EINVAL; 651 if (!result) errno = EINVAL;
540 return result; 652 return result;
541 } 653 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698