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

Side by Side Diff: src/trusted/validator_ragel/unreviewed/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
(Empty)
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 #include <assert.h>
8 #include <errno.h>
9 #include <stddef.h>
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <string.h>
13
14 #include "native_client/src/trusted/validator_ragel/unreviewed/validator_interna l.h"
15
16 %%{
17 machine x86_64_validator;
18 alphtype unsigned char;
19 variable p current_position;
20 variable pe end_of_bundle;
21 variable eof end_of_bundle;
22 variable cs current_state;
23
24 include byte_machine "byte_machines.rl";
25
26 include prefix_actions
27 "native_client/src/trusted/validator_ragel/unreviewed/parse_instruction.rl";
28 include prefixes_parsing
29 "native_client/src/trusted/validator_ragel/unreviewed/parse_instruction.rl";
30 include rex_actions
31 "native_client/src/trusted/validator_ragel/unreviewed/parse_instruction.rl";
32 include rex_parsing
33 "native_client/src/trusted/validator_ragel/unreviewed/parse_instruction.rl";
34 include vex_actions_amd64
35 "native_client/src/trusted/validator_ragel/unreviewed/parse_instruction.rl";
36 include vex_parsing_amd64
37 "native_client/src/trusted/validator_ragel/unreviewed/parse_instruction.rl";
38 include displacement_fields_actions
39 "native_client/src/trusted/validator_ragel/unreviewed/parse_instruction.rl";
40 include displacement_fields_parsing
41 "native_client/src/trusted/validator_ragel/unreviewed/parse_instruction.rl";
42 include modrm_actions_amd64
43 "native_client/src/trusted/validator_ragel/unreviewed/parse_instruction.rl";
44 include modrm_parsing_amd64
45 "native_client/src/trusted/validator_ragel/unreviewed/parse_instruction.rl";
46 include operand_actions_amd64
47 "native_client/src/trusted/validator_ragel/unreviewed/parse_instruction.rl";
48 include immediate_fields_actions
49 "native_client/src/trusted/validator_ragel/unreviewed/parse_instruction.rl";
50 include immediate_fields_parsing_amd64
51 "native_client/src/trusted/validator_ragel/unreviewed/parse_instruction.rl";
52 action rel8_operand {
53 rel8_operand(current_position + 1, data, jump_dests, size,
54 &instruction_info_collected);
55 }
56 action rel16_operand {
57 #error rel16_operand should never be used in nacl
58 }
59 action rel32_operand {
60 rel32_operand(current_position + 1, data, jump_dests, size,
61 &instruction_info_collected);
62 }
63 include relative_fields_parsing
64 "native_client/src/trusted/validator_ragel/unreviewed/parse_instruction.rl";
65 include cpuid_actions
66 "native_client/src/trusted/validator_ragel/unreviewed/parse_instruction.rl";
67
68 action check_access {
69 check_access(instruction_start - data, base, index, restricted_register,
70 valid_targets, &instruction_info_collected);
71 }
72
73 action last_byte_is_not_immediate {
74 instruction_info_collected |= LAST_BYTE_IS_NOT_IMMEDIATE;
75 }
76
77 action modifiable_instruction {
78 instruction_info_collected |= MODIFIABLE_INSTRUCTION;
79 }
80
81 action process_0_operands {
82 process_0_operands(&restricted_register, &instruction_info_collected);
83 }
84 action process_1_operand {
85 process_1_operand(&restricted_register, &instruction_info_collected,
86 rex_prefix, operand_states);
87 }
88 action process_1_operand_zero_extends {
89 process_1_operand_zero_extends(&restricted_register,
90 &instruction_info_collected, rex_prefix,
91 operand_states);
92 }
93 action process_2_operands {
94 process_2_operands(&restricted_register, &instruction_info_collected,
95 rex_prefix, operand_states);
96 }
97 action process_2_operands_zero_extends {
98 process_2_operands_zero_extends(&restricted_register,
99 &instruction_info_collected, rex_prefix,
100 operand_states);
101 }
102
103 include decode_x86_64 "validator_x86_64_instruction.rl";
104
105 data16condrep = (data16 | condrep data16 | data16 condrep);
106 data16rep = (data16 | rep data16 | data16 rep);
107
108 # Special %rbp modifications without required sandboxing
109 rbp_modifications =
110 (b_0100_10x0 0x89 0xe5) | # mov %rsp,%rbp
111 (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;
115
116 # Special instructions used for %rbp sandboxing
117 rbp_sandboxing =
118 (b_0100_11x0 0x01 0xfd | # add %r15,%rbp
119 b_0100_10x1 0x03 0xef | # add %r15,%rbp
120 0x49 0x8d 0x2c 0x2f | # lea (%r15,%rbp,1),%rbp
121 0x4a 0x8d 0x6c 0x3d 0x00) # lea 0x0(%rbp,%r15,1),%rbp
122 @{ if (restricted_register == REG_RBP)
123 instruction_info_collected |= RESTRICTED_REGISTER_USED;
124 else
125 instruction_info_collected |= UNRESTRICTED_RBP_PROCESSED;
126 restricted_register = NO_REG;
127 BitmapClearBit(valid_targets, (instruction_start - data));
128 };
129
130 # Special %rbp modifications without required sandboxing
131 rsp_modifications =
132 (b_0100_10x0 0x89 0xec) | # mov %rbp,%rsp
133 (b_0100_10x0 0x8b 0xe5) | # mov %rbp,%rsp
134 #(b_0100_1xx0 0x81 0xe4 any{3} (0x80 .. 0xff)) | # and $XXX,%rsp
135 #Superfluous bits are not supported:
136 # http://code.google.com/p/nativeclient/issues/detail?id=3012
137 (b_0100_1000 0x83 0xe4 (0x80 .. 0xff)) # and $XXX,%rsp
138 @process_0_operands;
139
140 # Special instructions used for %rsp sandboxing
141 rsp_sandboxing =
142 (b_0100_11x0 0x01 0xfc | # add %r15,%rsp
143 b_0100_10x1 0x03 0xe7 | # add %r15,%rsp
144 # OR can be used as well, see
145 # http://code.google.com/p/nativeclient/issues/detail?id=3070
146 b_0100_11x0 0x09 0xfc | # or %r15,%rsp
147 b_0100_10x1 0x0b 0xe7 | # or %r15,%rsp
148 0x4a 0x8d 0x24 0x3c) # lea (%rsp,%r15,1),%rsp
149 @{ if (restricted_register == REG_RSP)
150 instruction_info_collected |= RESTRICTED_REGISTER_USED;
151 else
152 instruction_info_collected |= UNRESTRICTED_RSP_PROCESSED;
153 restricted_register = NO_REG;
154 BitmapClearBit(valid_targets, (instruction_start - data));
155 };
156
157 # naclcall or nacljmp. Note: first "and $~0x1f, %eXX" is a normal instruction
158 # and as such will detect case where %rbp/%rsp is illegally modified.
159 naclcall_or_nacljmp =
160 # and $~0x1f, %eax/%ecx/%edx/%ebx/%esp/%ebp/%esi/%edi
161 (0x83 (0xe0|0xe1|0xe2|0xe3|0xe4|0xe5|0xe6|0xe7) 0xe0
162 # add %r15,%rax/%rcx/%rdx/%rbx/%rsp/%rbp/%rsi/%rdi
163 b_0100_11x0 0x01 (0xf8|0xf9|0xfa|0xfb|0xfc|0xfd|0xfe|0xff)
164 # callq %rax/%rcx/%rdx/%rbx/%rsp/%rbp/%rsi/%rdi
165 ((REX_WRX? 0xff (0xd0|0xd1|0xd2|0xd3|0xd4|0xd5|0xd6|0xd7)) |
166 # jmpq %rax/%rcx/%rdx/%rbx/%rsp/%rbp/%rsi/%rdi
167 (REX_WRX? 0xff (0xe0|0xe1|0xe2|0xe3|0xe4|0xe5|0xe6|0xe7))))
168 @{
169 instruction_start -= 6;
170 if (RMFromModRM(instruction_start[1]) !=
171 RMFromModRM(instruction_start[5]) ||
172 RMFromModRM(instruction_start[1]) != RMFromModRM(*current_position))
173 instruction_info_collected |= UNRECOGNIZED_INSTRUCTION;
174 BitmapClearBit(valid_targets, (instruction_start - data) + 3);
175 BitmapClearBit(valid_targets, (instruction_start - data) + 6);
176 restricted_register = NO_REG;
177 } |
178
179 # and $~0x1f, %eax/%ecx/%edx/%ebx/%esp/%ebp/%esi/%edi
180 (0x83 (0xe0|0xe1|0xe2|0xe3|0xe4|0xe5|0xe6|0xe7) 0xe0
181 # add %r15,%rax/%rcx/%rdx/%rbx/%rsp/%rbp/%rsi/%rdi
182 b_0100_10x1 0x03 (0xc7|0xcf|0xd7|0xdf|0xe7|0xef|0xf7|0xff)
183 # callq %rax/%rcx/%rdx/%rbx/%rsp/%rbp/%rsi/%rdi
184 ((REX_WRX? 0xff (0xd0|0xd1|0xd2|0xd3|0xd4|0xd5|0xd6|0xd7)) |
185 # jmpq %rax/%rcx/%rdx/%rbx/%rsp/%rbp/%rsi/%rdi
186 (REX_WRX? 0xff (0xe0|0xe1|0xe2|0xe3|0xe4|0xe5|0xe6|0xe7))))
187 @{
188 instruction_start -= 6;
189 if (RMFromModRM(instruction_start[1]) !=
190 RegFromModRM(instruction_start[5]) ||
191 RMFromModRM(instruction_start[1]) != RMFromModRM(*current_position))
192 instruction_info_collected |= UNRECOGNIZED_INSTRUCTION;
193 BitmapClearBit(valid_targets, (instruction_start - data) + 3);
194 BitmapClearBit(valid_targets, (instruction_start - data) + 6);
195 restricted_register = NO_REG;
196 } |
197
198 # rex.R?X? and $~0x1f, %eax/%ecx/%edx/%ebx/%esp/%ebp/%esi/%edi
199 ((REX_RX 0x83 (0xe0|0xe1|0xe2|0xe3|0xe4|0xe5|0xe6|0xe7) 0xe0
200 # add %r15,%rax/%rcx/%rdx/%rbx/%rsp/%rbp/%rsi/%rdi
201 b_0100_11x0 0x01 (0xf8|0xf9|0xfa|0xfb|0xfc|0xfd|0xfe|0xff)
202 # callq %rax/%rcx/%rdx/%rbx/%rsp/%rbp/%rsi/%rdi
203 ((REX_WRX? 0xff (0xd0|0xd1|0xd2|0xd3|0xd4|0xd5|0xd6|0xd7)) |
204 # jmpq %rax/%rcx/%rdx/%rbx/%rsp/%rbp/%rsi/%rdi
205 (REX_WRX? 0xff (0xe0|0xe1|0xe2|0xe3|0xe4|0xe5|0xe6|0xe7)))) |
206
207 # and $~0x1f, %r8d/%r9d/%r10d/%r11d/%r12d/%r13d/%r14d
208 (b_0100_0xx1 0x83 (0xe0|0xe1|0xe2|0xe3|0xe4|0xe5|0xe6) 0xe0
209 # add %r15, %r8d/%r9d/%r10d/%r11d/%r12d/%r13d/%r14d
210 b_0100_11x1 0x01 (0xf8|0xf9|0xfa|0xfb|0xfc|0xfd|0xfe)
211 # callq %r8/%r9/%r10/%r11/%r12/%r13/%r14
212 ((b_0100_xxx1 0xff (0xd0|0xd1|0xd2|0xd3|0xd4|0xd5|0xd6)) |
213 # jmpq %r8/%r9/%r10/%r11/%r12/%r13/%r14
214 (b_0100_xxx1 0xff (0xe0|0xe1|0xe2|0xe3|0xe4|0xe5|0xe6)))))
215 @{
216 instruction_start -= 7;
217 if (RMFromModRM(instruction_start[2]) !=
218 RMFromModRM(instruction_start[6]) ||
219 RMFromModRM(instruction_start[2]) != RMFromModRM(*current_position))
220 instruction_info_collected |= UNRECOGNIZED_INSTRUCTION;
221 BitmapClearBit(valid_targets, (instruction_start - data) + 4);
222 BitmapClearBit(valid_targets, (instruction_start - data) + 7);
223 restricted_register = NO_REG;
224 } |
225
226 # rex.R?X? and $~0x1f, %eax/%ecx/%edx/%ebx/%esp/%ebp/%esi/%edi
227 ((REX_RX 0x83 (0xe0|0xe1|0xe2|0xe3|0xe4|0xe5|0xe6|0xe7) 0xe0
228 # add %r15,%rax/%rcx/%rdx/%rbx/%rsp/%rbp/%rsi/%rdi
229 b_0100_10x1 0x03 (0xc7|0xcf|0xd7|0xdf|0xe7|0xef|0xf7|0xff)
230 # callq %rax/%rcx/%rdx/%rbx/%rsp/%rbp/%rsi/%rdi
231 ((REX_WRX? 0xff (0xd0|0xd1|0xd2|0xd3|0xd4|0xd5|0xd6|0xd7)) |
232 # jmpq %rax/%rcx/%rdx/%rbx/%rsp/%rbp/%rsi/%rdi
233 (REX_WRX? 0xff (0xe0|0xe1|0xe2|0xe3|0xe4|0xe5|0xe6|0xe7)))) |
234
235 # and $~0x1f, %r8d/%r9d/%r10d/%r11d/%r12d/%r13d/%r14d
236 (b_0100_0xx1 0x83 (0xe0|0xe1|0xe2|0xe3|0xe4|0xe5|0xe6) 0xe0
237 # add %r15, %r8d/%r9d/%r10d/%r11d/%r12d/%r13d/%r14d
238 b_0100_11x1 0x03 (0xc7|0xcf|0xd7|0xdf|0xe7|0xef|0xf7)
239 # callq %r8/%r9/%r10/%r11/%r12/%r13/%r14
240 ((b_0100_xxx1 0xff (0xd0|0xd1|0xd2|0xd3|0xd4|0xd5|0xd6)) |
241 # jmpq %r8/%r9/%r10/%r11/%r12/%r13/%r14
242 (b_0100_xxx1 0xff (0xe0|0xe1|0xe2|0xe3|0xe4|0xe5|0xe6)))))
243 @{
244 instruction_start -= 7;
245 if (RMFromModRM(instruction_start[2]) !=
246 RegFromModRM(instruction_start[6]) ||
247 RMFromModRM(instruction_start[2]) != RMFromModRM(*current_position))
248 instruction_info_collected |= UNRECOGNIZED_INSTRUCTION;
249 BitmapClearBit(valid_targets, (instruction_start - data) + 4);
250 BitmapClearBit(valid_targets, (instruction_start - data) + 7);
251 restricted_register = NO_REG;
252 };
253
254 # EMMS/SSE2/AVX instructions which have implicit %ds:(%rsi) operand
255 # maskmovq %mmX,%mmY
256 maskmovq =
257 REX_WRXB? (0x0f 0xf7)
258 @CPUFeature_EMMX modrm_registers;
259 # maskmovdqu %xmmX, %xmmY
260 maskmovdqu =
261 0x66 REX_WRXB? (0x0f 0xf7) @not_data16_prefix
262 @CPUFeature_SSE2 modrm_registers;
263 # vmaskmovdqu %xmmX, %xmmY
264 vmaskmovdqu =
265 ((0xc4 (VEX_RB & VEX_map00001) 0x79 @vex_prefix3) |
266 (0xc5 (0x79 | 0xf9) @vex_prefix_short)) 0xf7
267 @CPUFeature_AVX modrm_registers;
268 mmx_sse_rdi_instruction = maskmovq | maskmovdqu | vmaskmovdqu;
269
270 # String instructions which use only %ds:(%rsi)
271 string_instruction_rsi_no_rdi =
272 (rep? 0xac | # lods %ds:(%rsi),%al
273 data16rep 0xad | # lods %ds:(%rsi),%ax
274 rep? REXW_NONE? 0xad) ; # lods %ds:(%rsi),%eax/%rax
275
276 # String instructions which use only %ds:(%rdi)
277 string_instruction_rdi_no_rsi =
278 condrep? 0xae | # scas %es:(%rdi),%al
279 data16condrep 0xaf | # scas %es:(%rdi),%ax
280 condrep? REXW_NONE? 0xaf | # scas %es:(%rdi),%eax/%rax
281
282 rep? 0xaa | # stos %al,%es:(%rdi)
283 data16rep 0xab | # stos %ax,%es:(%rdi)
284 rep? REXW_NONE? 0xab ; # stos %eax/%rax,%es:(%rdi)
285
286 # String instructions which use both %ds:(%rsi) and %ds:(%rdi)
287 string_instruction_rsi_rdi =
288 condrep? 0xa6 | # cmpsb %es:(%rdi),%ds:(%rsi)
289 data16condrep 0xa7 | # cmpsw %es:(%rdi),%ds:(%rsi)
290 condrep? REXW_NONE? 0xa7 | # cmps[lq] %es:(%rdi),%ds:(%rsi)
291
292 rep? 0xa4 | # movsb %es:(%rdi),%ds:(%rsi)
293 data16rep 0xa5 | # movsw %es:(%rdi),%ds:(%rsi)
294 rep? REXW_NONE? 0xa5 ; # movs[lq] %es:(%rdi),%ds:(%rsi)
295
296 sandbox_instruction_rsi_no_rdi =
297 (0x89 | 0x8b) 0xf6 . # mov %esi,%esi
298 0x49 0x8d 0x34 0x37 . # lea (%r15,%rsi,1),%rsi
299 string_instruction_rsi_no_rdi
300 @{
301 instruction_start -= 6;
302 BitmapClearBit(valid_targets, (instruction_start - data) + 2);
303 BitmapClearBit(valid_targets, (instruction_start - data) + 6);
304 restricted_register = NO_REG;
305 } |
306
307 REX_X (0x89 | 0x8b) 0xf6 . # mov %esi,%esi
308 0x49 0x8d 0x34 0x37 . # lea (%r15,%rsi,1),%rsi
309 string_instruction_rsi_no_rdi
310 @{
311 instruction_start -= 7;
312 BitmapClearBit(valid_targets, (instruction_start - data) + 3);
313 BitmapClearBit(valid_targets, (instruction_start - data) + 7);
314 restricted_register = NO_REG;
315 };
316
317 sandbox_instruction_rdi_no_rsi =
318 (0x89 | 0x8b) 0xff . # mov %edi,%edi
319 0x49 0x8d 0x3c 0x3f . # lea (%r15,%rdi,1),%rdi
320 (string_instruction_rdi_no_rsi | mmx_sse_rdi_instruction)
321 @{
322 instruction_start -= 6;
323 BitmapClearBit(valid_targets, (instruction_start - data) + 2);
324 BitmapClearBit(valid_targets, (instruction_start - data) + 6);
325 restricted_register = NO_REG;
326 } |
327
328 REX_X (0x89 | 0x8b) 0xff . # mov %edi,%edi
329 0x49 0x8d 0x3c 0x3f . # lea (%r15,%rdi,1),%rdi
330 (string_instruction_rdi_no_rsi | mmx_sse_rdi_instruction)
331 @{
332 instruction_start -= 7;
333 BitmapClearBit(valid_targets, (instruction_start - data) + 3);
334 BitmapClearBit(valid_targets, (instruction_start - data) + 7);
335 restricted_register = NO_REG;
336 };
337
338
339 # String instructions which use both %ds:(%rsi) and %ds:(%rdi)
340 sandbox_instruction_rsi_rdi =
341 (0x89 | 0x8b) 0xf6 . # mov %esi,%esi
342 0x49 0x8d 0x34 0x37 . # lea (%r15,%rsi,1),%rsi
343 (0x89 | 0x8b) 0xff . # mov %edi,%edi
344 0x49 0x8d 0x3c 0x3f . # lea (%r15,%rdi,1),%rdi
345 string_instruction_rsi_rdi
346 @{
347 instruction_start -= 12;
348 BitmapClearBit(valid_targets, (instruction_start - data) + 2);
349 BitmapClearBit(valid_targets, (instruction_start - data) + 6);
350 BitmapClearBit(valid_targets, (instruction_start - data) + 8);
351 BitmapClearBit(valid_targets, (instruction_start - data) + 12);
352 restricted_register = NO_REG;
353 } |
354
355 (0x89 | 0x8b) 0xf6 . # mov %esi,%esi
356 0x49 0x8d 0x34 0x37 . # lea (%r15,%rsi,1),%rsi
357 REX_X (0x89 | 0x8b) 0xff . # mov %edi,%edi
358 0x49 0x8d 0x3c 0x3f . # lea (%r15,%rdi,1),%rdi
359 string_instruction_rsi_rdi
360 @{
361 instruction_start -= 13;
362 BitmapClearBit(valid_targets, (instruction_start - data) + 2);
363 BitmapClearBit(valid_targets, (instruction_start - data) + 6);
364 BitmapClearBit(valid_targets, (instruction_start - data) + 9);
365 BitmapClearBit(valid_targets, (instruction_start - data) + 13);
366 restricted_register = NO_REG;
367 } |
368
369 REX_X (0x89 | 0x8b) 0xf6 . # mov %esi,%esi
370 0x49 0x8d 0x34 0x37 . # lea (%r15,%rsi,1),%rsi
371 (0x89 | 0x8b) 0xff . # mov %edi,%edi
372 0x49 0x8d 0x3c 0x3f . # lea (%r15,%rdi,1),%rdi
373 string_instruction_rsi_rdi
374 @{
375 instruction_start -= 13;
376 BitmapClearBit(valid_targets, (instruction_start - data) + 3);
377 BitmapClearBit(valid_targets, (instruction_start - data) + 7);
378 BitmapClearBit(valid_targets, (instruction_start - data) + 9);
379 BitmapClearBit(valid_targets, (instruction_start - data) + 13);
380 restricted_register = NO_REG;
381 } |
382
383 REX_X (0x89 | 0x8b) 0xf6 . # mov %esi,%esi
384 0x49 0x8d 0x34 0x37 . # lea (%r15,%rsi,1),%rsi
385 REX_X (0x89 | 0x8b) 0xff . # mov %edi,%edi
386 0x49 0x8d 0x3c 0x3f . # lea (%r15,%rdi,1),%rdi
387 string_instruction_rsi_rdi
388 @{
389 instruction_start -= 14;
390 BitmapClearBit(valid_targets, (instruction_start - data) + 3);
391 BitmapClearBit(valid_targets, (instruction_start - data) + 7);
392 BitmapClearBit(valid_targets, (instruction_start - data) + 10);
393 BitmapClearBit(valid_targets, (instruction_start - data) + 14);
394 restricted_register = NO_REG;
395 };
396
397 special_instruction =
398 (rbp_modifications |
399 rsp_modifications |
400 rbp_sandboxing |
401 rsp_sandboxing |
402 naclcall_or_nacljmp |
403 sandbox_instruction_rsi_no_rdi |
404 sandbox_instruction_rdi_no_rsi |
405 sandbox_instruction_rsi_rdi)
406 @{
407 instruction_info_collected |= SPECIAL_INSTRUCTION;
408 };
409
410 # Remove special instructions which are only allowed in special cases.
411 normal_instruction = one_instruction - special_instruction;
412
413 # Check if call is properly aligned
414 call_alignment =
415 ((normal_instruction &
416 # Direct call
417 ((data16 REX_RXB? 0xe8 rel16) |
418 (REX_WRXB? 0xe8 rel32) |
419 (data16 REXW_RXB 0xe8 rel32))) |
420 (special_instruction &
421 # Indirect call
422 (any* data16? REX_WRXB? 0xff ((opcode_2 | opcode_3) any* &
423 (modrm_memory | modrm_registers)))))
424 @{
425 if (((current_position - data) & kBundleMask) != kBundleMask)
426 instruction_info_collected |= BAD_CALL_ALIGNMENT;
427 };
428
429
430 main := ((call_alignment | normal_instruction | special_instruction)
431 >{
432 BitmapSetBit(valid_targets, current_position - data);
433 }
434 @{
435 if ((instruction_info_collected & VALIDATION_ERRORS_MASK) ||
436 (options & CALL_USER_CALLBACK_ON_EACH_INSTRUCTION)) {
437 result &= user_callback(
438 instruction_start, current_position,
439 instruction_info_collected |
440 ((restricted_register << RESTRICTED_REGISTER_SHIFT) &
441 RESTRICTED_REGISTER_MASK), callback_data);
442 }
443 /* On successful match the instruction start must point to the next byte
444 * to be able to report the new offset as the start of instruction
445 * causing error. */
446 instruction_start = current_position + 1;
447 instruction_info_collected = 0;
448 SET_REX_PREFIX(FALSE);
449 SET_VEX_PREFIX2(0xe0);
450 SET_VEX_PREFIX3(0x00);
451 operand_states = 0;
452 })*
453 $err{
454 result &= user_callback(instruction_start, current_position,
455 UNRECOGNIZED_INSTRUCTION, callback_data);
456 continue;
457 };
458
459 }%%
460
461 %% write data;
462
463 Bool ValidateChunkAMD64(const uint8_t *data, size_t size,
464 enum ValidationOptions options,
465 const NaClCPUFeaturesX86 *cpu_features,
466 ValidationCallbackFunc user_callback,
467 void *callback_data) {
468 bitmap_word valid_targets_small;
469 bitmap_word jump_dests_small;
470 bitmap_word *valid_targets;
471 bitmap_word *jump_dests;
472 const uint8_t *current_position;
473 const uint8_t *end_of_bundle;
474 int result = TRUE;
475
476 CHECK(sizeof valid_targets_small == sizeof jump_dests_small);
477 CHECK(size % kBundleSize == 0);
478
479 /* For a very small sequence (one bundle) malloc is too expensive. */
480 if (size <= sizeof valid_targets_small) {
481 valid_targets_small = 0;
482 valid_targets = &valid_targets_small;
483 jump_dests_small = 0;
484 jump_dests = &jump_dests_small;
485 } else {
486 valid_targets = BitmapAllocate(size);
487 jump_dests = BitmapAllocate(size);
488 if (!valid_targets || !jump_dests) {
489 free(jump_dests);
490 free(valid_targets);
491 errno = ENOMEM;
492 return FALSE;
493 }
494 }
495
496 if (options & PROCESS_CHUNK_AS_A_CONTIGUOUS_STREAM)
497 end_of_bundle = data + size;
498 else
499 end_of_bundle = data + kBundleSize;
500
501 for (current_position = data;
502 current_position < data + size;
503 current_position = end_of_bundle,
504 end_of_bundle = current_position + kBundleSize) {
505 /* Start of the instruction being processed. */
506 const uint8_t *instruction_start = current_position;
507 int current_state;
508 uint32_t instruction_info_collected = 0;
509 /* Keeps one byte of information per operand in the current instruction:
510 * 2 bits for register kinds,
511 * 5 bits for register numbers (16 regs plus RIZ). */
512 uint32_t operand_states = 0;
513 enum OperandName base = NO_REG;
514 enum OperandName index = NO_REG;
515 enum OperandName restricted_register = NO_REG;
516 uint8_t rex_prefix = FALSE;
517 uint8_t vex_prefix2 = 0xe0;
518 uint8_t vex_prefix3 = 0x00;
519
520 %% write init;
521 %% write exec;
522
523 if (restricted_register == REG_RBP)
524 result &= user_callback(end_of_bundle, end_of_bundle,
525 RESTRICTED_RBP_UNPROCESSED |
526 ((REG_RBP << RESTRICTED_REGISTER_SHIFT) &
527 RESTRICTED_REGISTER_MASK), callback_data);
528 else if (restricted_register == REG_RSP)
529 result &= user_callback(end_of_bundle, end_of_bundle,
530 RESTRICTED_RSP_UNPROCESSED |
531 ((REG_RSP << RESTRICTED_REGISTER_SHIFT) &
532 RESTRICTED_REGISTER_MASK), callback_data);
533 }
534
535 result &= ProcessInvalidJumpTargets(data, size, valid_targets, jump_dests,
536 user_callback, callback_data);
537
538 /* We only use malloc for a large code sequences */
539 if (size > sizeof valid_targets_small) {
540 free(jump_dests);
541 free(valid_targets);
542 }
543 if (!result) errno = EINVAL;
544 return result;
545 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698