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

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 %rbp sandboxing
141 rsp_sandboxing =
142 (b_0100_11x0 0x01 0xfc | # add %r15,%rsp
143 b_0100_10x1 0x03 0xe7 | # add %r15,%rbp
144 0x4a 0x8d 0x24 0x3c) # lea (%rsp,%r15,1),%rsp
145 @{ if (restricted_register == REG_RSP)
146 instruction_info_collected |= RESTRICTED_REGISTER_USED;
147 else
148 instruction_info_collected |= UNRESTRICTED_RSP_PROCESSED;
149 restricted_register = NO_REG;
150 BitmapClearBit(valid_targets, (instruction_start - data));
151 };
152
153 # naclcall or nacljmp. Note: first "and $~0x1f, %eXX" is a normal instruction
154 # and as such will detect case where %rbp/%rsp is illegally modified.
155 naclcall_or_nacljmp =
156 # and $~0x1f, %eax/%ecx/%edx/%ebx/%esp/%ebp/%esi/%edi
157 (0x83 (0xe0|0xe1|0xe2|0xe3|0xe4|0xe5|0xe6|0xe7) 0xe0
158 # add %r15,%rax/%rcx/%rdx/%rbx/%rsp/%rbp/%rsi/%rdi
159 b_0100_11x0 0x01 (0xf8|0xf9|0xfa|0xfb|0xfc|0xfd|0xfe|0xff)
160 # callq %rax/%rcx/%rdx/%rbx/%rsp/%rbp/%rsi/%rdi
161 ((REX_WRX? 0xff (0xd0|0xd1|0xd2|0xd3|0xd4|0xd5|0xd6|0xd7)) |
162 # jmpq %rax/%rcx/%rdx/%rbx/%rsp/%rbp/%rsi/%rdi
163 (REX_WRX? 0xff (0xe0|0xe1|0xe2|0xe3|0xe4|0xe5|0xe6|0xe7))))
164 @{
165 instruction_start -= 6;
166 if (RMFromModRM(instruction_start[1]) !=
167 RMFromModRM(instruction_start[5]) ||
168 RMFromModRM(instruction_start[1]) != RMFromModRM(*current_position))
169 instruction_info_collected |= UNRECOGNIZED_INSTRUCTION;
170 BitmapClearBit(valid_targets, (instruction_start - data) + 3);
171 BitmapClearBit(valid_targets, (instruction_start - data) + 6);
172 restricted_register = NO_REG;
173 } |
174
175 # and $~0x1f, %eax/%ecx/%edx/%ebx/%esp/%ebp/%esi/%edi
176 (0x83 (0xe0|0xe1|0xe2|0xe3|0xe4|0xe5|0xe6|0xe7) 0xe0
177 # add %r15,%rax/%rcx/%rdx/%rbx/%rsp/%rbp/%rsi/%rdi
178 b_0100_10x1 0x03 (0xc7|0xcf|0xd7|0xdf|0xe7|0xef|0xf7|0xff)
179 # callq %rax/%rcx/%rdx/%rbx/%rsp/%rbp/%rsi/%rdi
180 ((REX_WRX? 0xff (0xd0|0xd1|0xd2|0xd3|0xd4|0xd5|0xd6|0xd7)) |
181 # jmpq %rax/%rcx/%rdx/%rbx/%rsp/%rbp/%rsi/%rdi
182 (REX_WRX? 0xff (0xe0|0xe1|0xe2|0xe3|0xe4|0xe5|0xe6|0xe7))))
183 @{
184 instruction_start -= 6;
185 if (RMFromModRM(instruction_start[1]) !=
186 RegFromModRM(instruction_start[5]) ||
187 RMFromModRM(instruction_start[1]) != RMFromModRM(*current_position))
188 instruction_info_collected |= UNRECOGNIZED_INSTRUCTION;
189 BitmapClearBit(valid_targets, (instruction_start - data) + 3);
190 BitmapClearBit(valid_targets, (instruction_start - data) + 6);
191 restricted_register = NO_REG;
192 } |
193
194 # rex.R?X? and $~0x1f, %eax/%ecx/%edx/%ebx/%esp/%ebp/%esi/%edi
195 ((REX_RX 0x83 (0xe0|0xe1|0xe2|0xe3|0xe4|0xe5|0xe6|0xe7) 0xe0
196 # add %r15,%rax/%rcx/%rdx/%rbx/%rsp/%rbp/%rsi/%rdi
197 b_0100_11x0 0x01 (0xf8|0xf9|0xfa|0xfb|0xfc|0xfd|0xfe|0xff)
198 # callq %rax/%rcx/%rdx/%rbx/%rsp/%rbp/%rsi/%rdi
199 ((REX_WRX? 0xff (0xd0|0xd1|0xd2|0xd3|0xd4|0xd5|0xd6|0xd7)) |
200 # jmpq %rax/%rcx/%rdx/%rbx/%rsp/%rbp/%rsi/%rdi
201 (REX_WRX? 0xff (0xe0|0xe1|0xe2|0xe3|0xe4|0xe5|0xe6|0xe7)))) |
202
203 # and $~0x1f, %r8d/%r9d/%r10d/%r11d/%r12d/%r13d/%r14d
204 (b_0100_0xx1 0x83 (0xe0|0xe1|0xe2|0xe3|0xe4|0xe5|0xe6) 0xe0
205 # add %r15, %r8d/%r9d/%r10d/%r11d/%r12d/%r13d/%r14d
206 b_0100_11x1 0x01 (0xf8|0xf9|0xfa|0xfb|0xfc|0xfd|0xfe)
207 # callq %r8/%r9/%r10/%r11/%r12/%r13/%r14
208 ((b_0100_xxx1 0xff (0xd0|0xd1|0xd2|0xd3|0xd4|0xd5|0xd6)) |
209 # jmpq %r8/%r9/%r10/%r11/%r12/%r13/%r14
210 (b_0100_xxx1 0xff (0xe0|0xe1|0xe2|0xe3|0xe4|0xe5|0xe6)))))
211 @{
212 instruction_start -= 7;
213 if (RMFromModRM(instruction_start[2]) !=
214 RMFromModRM(instruction_start[6]) ||
215 RMFromModRM(instruction_start[2]) != RMFromModRM(*current_position))
216 instruction_info_collected |= UNRECOGNIZED_INSTRUCTION;
217 BitmapClearBit(valid_targets, (instruction_start - data) + 4);
218 BitmapClearBit(valid_targets, (instruction_start - data) + 7);
219 restricted_register = NO_REG;
220 } |
221
222 # rex.R?X? and $~0x1f, %eax/%ecx/%edx/%ebx/%esp/%ebp/%esi/%edi
223 ((REX_RX 0x83 (0xe0|0xe1|0xe2|0xe3|0xe4|0xe5|0xe6|0xe7) 0xe0
224 # add %r15,%rax/%rcx/%rdx/%rbx/%rsp/%rbp/%rsi/%rdi
225 b_0100_10x1 0x03 (0xc7|0xcf|0xd7|0xdf|0xe7|0xef|0xf7|0xff)
226 # callq %rax/%rcx/%rdx/%rbx/%rsp/%rbp/%rsi/%rdi
227 ((REX_WRX? 0xff (0xd0|0xd1|0xd2|0xd3|0xd4|0xd5|0xd6|0xd7)) |
228 # jmpq %rax/%rcx/%rdx/%rbx/%rsp/%rbp/%rsi/%rdi
229 (REX_WRX? 0xff (0xe0|0xe1|0xe2|0xe3|0xe4|0xe5|0xe6|0xe7)))) |
230
231 # and $~0x1f, %r8d/%r9d/%r10d/%r11d/%r12d/%r13d/%r14d
232 (b_0100_0xx1 0x83 (0xe0|0xe1|0xe2|0xe3|0xe4|0xe5|0xe6) 0xe0
233 # add %r15, %r8d/%r9d/%r10d/%r11d/%r12d/%r13d/%r14d
234 b_0100_11x1 0x03 (0xc7|0xcf|0xd7|0xdf|0xe7|0xef|0xf7)
235 # callq %r8/%r9/%r10/%r11/%r12/%r13/%r14
236 ((b_0100_xxx1 0xff (0xd0|0xd1|0xd2|0xd3|0xd4|0xd5|0xd6)) |
237 # jmpq %r8/%r9/%r10/%r11/%r12/%r13/%r14
238 (b_0100_xxx1 0xff (0xe0|0xe1|0xe2|0xe3|0xe4|0xe5|0xe6)))))
239 @{
240 instruction_start -= 7;
241 if (RMFromModRM(instruction_start[2]) !=
242 RegFromModRM(instruction_start[6]) ||
243 RMFromModRM(instruction_start[2]) != RMFromModRM(*current_position))
244 instruction_info_collected |= UNRECOGNIZED_INSTRUCTION;
245 BitmapClearBit(valid_targets, (instruction_start - data) + 4);
246 BitmapClearBit(valid_targets, (instruction_start - data) + 7);
247 restricted_register = NO_REG;
248 };
249
250 # EMMS/SSE2/AVX instructions which have implicit %ds:(%rsi) operand
251 # maskmovq %mmX,%mmY
252 maskmovq =
253 REX_WRXB? (0x0f 0xf7)
254 @CPUFeature_EMMX modrm_registers;
255 # maskmovdqu %xmmX, %xmmY
256 maskmovdqu =
257 0x66 REX_WRXB? (0x0f 0xf7) @not_data16_prefix
258 @CPUFeature_SSE2 modrm_registers;
259 # vmaskmovdqu %xmmX, %xmmY
260 vmaskmovdqu =
261 ((0xc4 (VEX_RB & VEX_map00001) 0x79 @vex_prefix3) |
262 (0xc5 (0x79 | 0xf9) @vex_prefix_short)) 0xf7
263 @CPUFeature_AVX modrm_registers;
264 mmx_sse_rdi_instruction = maskmovq | maskmovdqu | vmaskmovdqu;
265
266 # String instructions which use only %ds:(%rsi)
267 string_instruction_rsi_no_rdi =
268 (rep? 0xac | # lods %ds:(%rsi),%al
269 data16rep 0xad | # lods %ds:(%rsi),%ax
270 rep? REXW_NONE? 0xad) ; # lods %ds:(%rsi),%eax/%rax
271
272 # String instructions which use only %ds:(%rdi)
273 string_instruction_rdi_no_rsi =
274 condrep? 0xae | # scas %es:(%rdi),%al
275 data16condrep 0xaf | # scas %es:(%rdi),%ax
276 condrep? REXW_NONE? 0xaf | # scas %es:(%rdi),%eax/%rax
277
278 rep? 0xaa | # stos %al,%es:(%rdi)
279 data16rep 0xab | # stos %ax,%es:(%rdi)
280 rep? REXW_NONE? 0xab ; # stos %eax/%rax,%es:(%rdi)
281
282 # String instructions which use both %ds:(%rsi) and %ds:(%rdi)
283 string_instruction_rsi_rdi =
284 condrep? 0xa6 | # cmpsb %es:(%rdi),%ds:(%rsi)
285 data16condrep 0xa7 | # cmpsw %es:(%rdi),%ds:(%rsi)
286 condrep? REXW_NONE? 0xa7 | # cmps[lq] %es:(%rdi),%ds:(%rsi)
287
288 rep? 0xa4 | # movsb %es:(%rdi),%ds:(%rsi)
289 data16rep 0xa5 | # movsw %es:(%rdi),%ds:(%rsi)
290 rep? REXW_NONE? 0xa5 ; # movs[lq] %es:(%rdi),%ds:(%rsi)
291
292 sandbox_instruction_rsi_no_rdi =
293 (0x89 | 0x8b) 0xf6 . # mov %esi,%esi
294 0x49 0x8d 0x34 0x37 . # lea (%r15,%rsi,1),%rsi
295 string_instruction_rsi_no_rdi
296 @{
297 instruction_start -= 6;
298 BitmapClearBit(valid_targets, (instruction_start - data) + 2);
299 BitmapClearBit(valid_targets, (instruction_start - data) + 6);
300 restricted_register = NO_REG;
301 } |
302
303 REX_X (0x89 | 0x8b) 0xf6 . # mov %esi,%esi
304 0x49 0x8d 0x34 0x37 . # lea (%r15,%rsi,1),%rsi
305 string_instruction_rsi_no_rdi
306 @{
307 instruction_start -= 7;
308 BitmapClearBit(valid_targets, (instruction_start - data) + 3);
309 BitmapClearBit(valid_targets, (instruction_start - data) + 7);
310 restricted_register = NO_REG;
311 };
312
313 sandbox_instruction_rdi_no_rsi =
314 (0x89 | 0x8b) 0xff . # mov %edi,%edi
315 0x49 0x8d 0x3c 0x3f . # lea (%r15,%rdi,1),%rdi
316 (string_instruction_rdi_no_rsi | mmx_sse_rdi_instruction)
317 @{
318 instruction_start -= 6;
319 BitmapClearBit(valid_targets, (instruction_start - data) + 2);
320 BitmapClearBit(valid_targets, (instruction_start - data) + 6);
321 restricted_register = NO_REG;
322 } |
323
324 REX_X (0x89 | 0x8b) 0xff . # mov %edi,%edi
325 0x49 0x8d 0x3c 0x3f . # lea (%r15,%rdi,1),%rdi
326 (string_instruction_rdi_no_rsi | mmx_sse_rdi_instruction)
327 @{
328 instruction_start -= 7;
329 BitmapClearBit(valid_targets, (instruction_start - data) + 3);
330 BitmapClearBit(valid_targets, (instruction_start - data) + 7);
331 restricted_register = NO_REG;
332 };
333
334
335 # String instructions which use both %ds:(%rsi) and %ds:(%rdi)
336 sandbox_instruction_rsi_rdi =
337 (0x89 | 0x8b) 0xf6 . # mov %esi,%esi
338 0x49 0x8d 0x34 0x37 . # lea (%r15,%rsi,1),%rsi
339 (0x89 | 0x8b) 0xff . # mov %edi,%edi
340 0x49 0x8d 0x3c 0x3f . # lea (%r15,%rdi,1),%rdi
341 string_instruction_rsi_rdi
342 @{
343 instruction_start -= 12;
344 BitmapClearBit(valid_targets, (instruction_start - data) + 2);
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 } |
350
351 (0x89 | 0x8b) 0xf6 . # mov %esi,%esi
352 0x49 0x8d 0x34 0x37 . # lea (%r15,%rsi,1),%rsi
353 REX_X (0x89 | 0x8b) 0xff . # mov %edi,%edi
354 0x49 0x8d 0x3c 0x3f . # lea (%r15,%rdi,1),%rdi
355 string_instruction_rsi_rdi
356 @{
357 instruction_start -= 13;
358 BitmapClearBit(valid_targets, (instruction_start - data) + 2);
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 } |
364
365 REX_X (0x89 | 0x8b) 0xf6 . # mov %esi,%esi
366 0x49 0x8d 0x34 0x37 . # lea (%r15,%rsi,1),%rsi
367 (0x89 | 0x8b) 0xff . # mov %edi,%edi
368 0x49 0x8d 0x3c 0x3f . # lea (%r15,%rdi,1),%rdi
369 string_instruction_rsi_rdi
370 @{
371 instruction_start -= 13;
372 BitmapClearBit(valid_targets, (instruction_start - data) + 3);
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 } |
378
379 REX_X (0x89 | 0x8b) 0xf6 . # mov %esi,%esi
380 0x49 0x8d 0x34 0x37 . # lea (%r15,%rsi,1),%rsi
381 REX_X (0x89 | 0x8b) 0xff . # mov %edi,%edi
382 0x49 0x8d 0x3c 0x3f . # lea (%r15,%rdi,1),%rdi
383 string_instruction_rsi_rdi
384 @{
385 instruction_start -= 14;
386 BitmapClearBit(valid_targets, (instruction_start - data) + 3);
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 };
392
393 special_instruction =
394 (rbp_modifications |
395 rsp_modifications |
396 rbp_sandboxing |
397 rsp_sandboxing |
398 naclcall_or_nacljmp |
399 sandbox_instruction_rsi_no_rdi |
400 sandbox_instruction_rdi_no_rsi |
401 sandbox_instruction_rsi_rdi)
402 @{
403 instruction_info_collected |= SPECIAL_INSTRUCTION;
404 };
405
406 # Remove special instructions which are only allowed in special cases.
407 normal_instruction = one_instruction - special_instruction;
408
409 # Check if call is properly aligned
410 call_alignment =
411 ((normal_instruction &
412 # Direct call
413 ((data16 REX_RXB? 0xe8 rel16) |
414 (REX_WRXB? 0xe8 rel32) |
415 (data16 REXW_RXB 0xe8 rel32))) |
416 (special_instruction &
417 # Indirect call
418 (any* data16? REX_WRXB? 0xff ((opcode_2 | opcode_3) any* &
419 (modrm_memory | modrm_registers)))))
420 @{
421 if (((current_position - data) & kBundleMask) != kBundleMask)
422 instruction_info_collected |= BAD_CALL_ALIGNMENT;
423 };
424
425
426 main := ((call_alignment | normal_instruction | special_instruction)
427 >{
428 BitmapSetBit(valid_targets, current_position - data);
429 }
430 @{
431 if ((instruction_info_collected &
432 (VALIDATION_ERRORS_MASK | BAD_CALL_ALIGNMENT)) ||
433 (options & CALL_USER_CALLBACK_ON_EACH_INSTRUCTION)) {
434 result &= user_callback(
435 instruction_start, current_position,
436 instruction_info_collected |
437 ((restricted_register << RESTRICTED_REGISTER_SHIFT) &
438 RESTRICTED_REGISTER_MASK), callback_data);
439 }
440 /* On successful match the instruction start must point to the next byte
441 * to be able to report the new offset as the start of instruction
442 * causing error. */
443 instruction_start = current_position + 1;
444 instruction_info_collected = 0;
445 SET_REX_PREFIX(FALSE);
446 SET_VEX_PREFIX2(0xe0);
447 SET_VEX_PREFIX3(0x00);
448 operand_states = 0;
449 })*
450 $err{
451 result &= user_callback(instruction_start, current_position,
452 UNRECOGNIZED_INSTRUCTION, callback_data);
453 continue;
454 };
455
456 }%%
457
458 %% write data;
459
460 Bool ValidateChunkAMD64(const uint8_t *data, size_t size,
461 enum validation_options options,
462 const NaClCPUFeaturesX86 *cpu_features,
463 validation_callback_func user_callback,
464 void *callback_data) {
465 bitmap_word valid_targets_small;
466 bitmap_word jump_dests_small;
467 bitmap_word *valid_targets;
468 bitmap_word *jump_dests;
469 const uint8_t *current_position;
470 const uint8_t *end_of_bundle;
471 int result = TRUE;
472
473 CHECK(sizeof valid_targets_small == sizeof jump_dests_small);
474 CHECK(size % kBundleSize == 0);
475
476 /* For a very small sequence (one bundle) malloc is too expensive. */
477 if (size <= sizeof valid_targets_small) {
478 valid_targets_small = 0;
479 valid_targets = &valid_targets_small;
480 jump_dests_small = 0;
481 jump_dests = &jump_dests_small;
482 } else {
483 valid_targets = BitmapAllocate(size);
484 jump_dests = BitmapAllocate(size);
485 if (!valid_targets || !jump_dests) {
486 free(jump_dests);
487 free(valid_targets);
488 errno = ENOMEM;
489 return FALSE;
490 }
491 }
492
493 if (options & PROCESS_CHUNK_AS_A_CONTIGUOUS_STREAM)
494 end_of_bundle = data + size;
495 else
496 end_of_bundle = data + kBundleSize;
497
498 for (current_position = data;
499 current_position < data + size;
500 current_position = end_of_bundle,
501 end_of_bundle = current_position + kBundleSize) {
502 /* Start of the instruction being processed. */
503 const uint8_t *instruction_start = current_position;
504 int current_state;
505 uint32_t instruction_info_collected = 0;
506 /* Keeps one byte of information per operand in the current instruction:
507 * 2 bits for register kinds,
508 * 5 bits for register numbers (16 regs plus RIZ). */
509 uint32_t operand_states = 0;
510 enum register_name base = NO_REG;
511 enum register_name index = NO_REG;
512 enum register_name restricted_register = NO_REG;
513 uint8_t rex_prefix = FALSE;
514 uint8_t vex_prefix2 = 0xe0;
515 uint8_t vex_prefix3 = 0x00;
516
517 %% write init;
518 %% write exec;
519
520 if (restricted_register == REG_RBP)
521 result &= user_callback(end_of_bundle, end_of_bundle,
522 RESTRICTED_RBP_UNPROCESSED |
523 ((REG_RBP << RESTRICTED_REGISTER_SHIFT) &
524 RESTRICTED_REGISTER_MASK), callback_data);
525 else if (restricted_register == REG_RSP)
526 result &= user_callback(end_of_bundle, end_of_bundle,
527 RESTRICTED_RSP_UNPROCESSED |
528 ((REG_RSP << RESTRICTED_REGISTER_SHIFT) &
529 RESTRICTED_REGISTER_MASK), callback_data);
530 }
531
532 result &= ProcessInvalidJumpTargets(data, size, valid_targets, jump_dests,
533 user_callback, callback_data);
534
535 /* We only use malloc for a large code sequences */
536 if (size > sizeof valid_targets_small) {
537 free(jump_dests);
538 free(valid_targets);
539 }
540 if (!result) errno = EINVAL;
541 return result;
542 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698