Index: src/trusted/validator_ragel/unreviewed/validator_x86_64.rl |
=================================================================== |
--- src/trusted/validator_ragel/unreviewed/validator_x86_64.rl (revision 9911) |
+++ src/trusted/validator_ragel/unreviewed/validator_x86_64.rl (working copy) |
@@ -1,542 +0,0 @@ |
-/* |
- * Copyright (c) 2012 The Native Client Authors. All rights reserved. |
- * Use of this source code is governed by a BSD-style license that can be |
- * found in the LICENSE file. |
- */ |
- |
-#include <assert.h> |
-#include <errno.h> |
-#include <stddef.h> |
-#include <stdio.h> |
-#include <stdlib.h> |
-#include <string.h> |
- |
-#include "native_client/src/trusted/validator_ragel/unreviewed/validator_internal.h" |
- |
-%%{ |
- machine x86_64_validator; |
- alphtype unsigned char; |
- variable p current_position; |
- variable pe end_of_bundle; |
- variable eof end_of_bundle; |
- variable cs current_state; |
- |
- include byte_machine "byte_machines.rl"; |
- |
- include prefix_actions |
- "native_client/src/trusted/validator_ragel/unreviewed/parse_instruction.rl"; |
- include prefixes_parsing |
- "native_client/src/trusted/validator_ragel/unreviewed/parse_instruction.rl"; |
- include rex_actions |
- "native_client/src/trusted/validator_ragel/unreviewed/parse_instruction.rl"; |
- include rex_parsing |
- "native_client/src/trusted/validator_ragel/unreviewed/parse_instruction.rl"; |
- include vex_actions_amd64 |
- "native_client/src/trusted/validator_ragel/unreviewed/parse_instruction.rl"; |
- include vex_parsing_amd64 |
- "native_client/src/trusted/validator_ragel/unreviewed/parse_instruction.rl"; |
- include displacement_fields_actions |
- "native_client/src/trusted/validator_ragel/unreviewed/parse_instruction.rl"; |
- include displacement_fields_parsing |
- "native_client/src/trusted/validator_ragel/unreviewed/parse_instruction.rl"; |
- include modrm_actions_amd64 |
- "native_client/src/trusted/validator_ragel/unreviewed/parse_instruction.rl"; |
- include modrm_parsing_amd64 |
- "native_client/src/trusted/validator_ragel/unreviewed/parse_instruction.rl"; |
- include operand_actions_amd64 |
- "native_client/src/trusted/validator_ragel/unreviewed/parse_instruction.rl"; |
- include immediate_fields_actions |
- "native_client/src/trusted/validator_ragel/unreviewed/parse_instruction.rl"; |
- include immediate_fields_parsing_amd64 |
- "native_client/src/trusted/validator_ragel/unreviewed/parse_instruction.rl"; |
- action rel8_operand { |
- rel8_operand(current_position + 1, data, jump_dests, size, |
- &instruction_info_collected); |
- } |
- action rel16_operand { |
- #error rel16_operand should never be used in nacl |
- } |
- action rel32_operand { |
- rel32_operand(current_position + 1, data, jump_dests, size, |
- &instruction_info_collected); |
- } |
- include relative_fields_parsing |
- "native_client/src/trusted/validator_ragel/unreviewed/parse_instruction.rl"; |
- include cpuid_actions |
- "native_client/src/trusted/validator_ragel/unreviewed/parse_instruction.rl"; |
- |
- action check_access { |
- check_access(instruction_start - data, base, index, restricted_register, |
- valid_targets, &instruction_info_collected); |
- } |
- |
- action last_byte_is_not_immediate { |
- instruction_info_collected |= LAST_BYTE_IS_NOT_IMMEDIATE; |
- } |
- |
- action modifiable_instruction { |
- instruction_info_collected |= MODIFIABLE_INSTRUCTION; |
- } |
- |
- action process_0_operands { |
- process_0_operands(&restricted_register, &instruction_info_collected); |
- } |
- action process_1_operand { |
- process_1_operand(&restricted_register, &instruction_info_collected, |
- rex_prefix, operand_states); |
- } |
- action process_1_operand_zero_extends { |
- process_1_operand_zero_extends(&restricted_register, |
- &instruction_info_collected, rex_prefix, |
- operand_states); |
- } |
- action process_2_operands { |
- process_2_operands(&restricted_register, &instruction_info_collected, |
- rex_prefix, operand_states); |
- } |
- action process_2_operands_zero_extends { |
- process_2_operands_zero_extends(&restricted_register, |
- &instruction_info_collected, rex_prefix, |
- operand_states); |
- } |
- |
- include decode_x86_64 "validator_x86_64_instruction.rl"; |
- |
- data16condrep = (data16 | condrep data16 | data16 condrep); |
- data16rep = (data16 | rep data16 | data16 rep); |
- |
- # Special %rbp modifications without required sandboxing |
- rbp_modifications = |
- (b_0100_10x0 0x89 0xe5) | # mov %rsp,%rbp |
- (b_0100_10x0 0x8b 0xec) # | mov %rsp,%rbp |
- #(b_0100_1xx0 0x81 0xe5 any{3} (0x80 .. 0xff)) | # and $XXX,%rbp |
- #(b_0100_1xx0 0x83 0xe5 (0x80 .. 0xff)) # and $XXX,%rbp |
- @process_0_operands; |
- |
- # Special instructions used for %rbp sandboxing |
- rbp_sandboxing = |
- (b_0100_11x0 0x01 0xfd | # add %r15,%rbp |
- b_0100_10x1 0x03 0xef | # add %r15,%rbp |
- 0x49 0x8d 0x2c 0x2f | # lea (%r15,%rbp,1),%rbp |
- 0x4a 0x8d 0x6c 0x3d 0x00) # lea 0x0(%rbp,%r15,1),%rbp |
- @{ if (restricted_register == REG_RBP) |
- instruction_info_collected |= RESTRICTED_REGISTER_USED; |
- else |
- instruction_info_collected |= UNRESTRICTED_RBP_PROCESSED; |
- restricted_register = NO_REG; |
- BitmapClearBit(valid_targets, (instruction_start - data)); |
- }; |
- |
- # Special %rbp modifications without required sandboxing |
- rsp_modifications = |
- (b_0100_10x0 0x89 0xec) | # mov %rbp,%rsp |
- (b_0100_10x0 0x8b 0xe5) | # mov %rbp,%rsp |
- #(b_0100_1xx0 0x81 0xe4 any{3} (0x80 .. 0xff)) | # and $XXX,%rsp |
- #Superfluous bits are not supported: |
- # http://code.google.com/p/nativeclient/issues/detail?id=3012 |
- (b_0100_1000 0x83 0xe4 (0x80 .. 0xff)) # and $XXX,%rsp |
- @process_0_operands; |
- |
- # Special instructions used for %rbp sandboxing |
- rsp_sandboxing = |
- (b_0100_11x0 0x01 0xfc | # add %r15,%rsp |
- b_0100_10x1 0x03 0xe7 | # add %r15,%rbp |
- 0x4a 0x8d 0x24 0x3c) # lea (%rsp,%r15,1),%rsp |
- @{ if (restricted_register == REG_RSP) |
- instruction_info_collected |= RESTRICTED_REGISTER_USED; |
- else |
- instruction_info_collected |= UNRESTRICTED_RSP_PROCESSED; |
- restricted_register = NO_REG; |
- BitmapClearBit(valid_targets, (instruction_start - data)); |
- }; |
- |
- # naclcall or nacljmp. Note: first "and $~0x1f, %eXX" is a normal instruction |
- # and as such will detect case where %rbp/%rsp is illegally modified. |
- naclcall_or_nacljmp = |
- # and $~0x1f, %eax/%ecx/%edx/%ebx/%esp/%ebp/%esi/%edi |
- (0x83 (0xe0|0xe1|0xe2|0xe3|0xe4|0xe5|0xe6|0xe7) 0xe0 |
- # add %r15,%rax/%rcx/%rdx/%rbx/%rsp/%rbp/%rsi/%rdi |
- b_0100_11x0 0x01 (0xf8|0xf9|0xfa|0xfb|0xfc|0xfd|0xfe|0xff) |
- # callq %rax/%rcx/%rdx/%rbx/%rsp/%rbp/%rsi/%rdi |
- ((REX_WRX? 0xff (0xd0|0xd1|0xd2|0xd3|0xd4|0xd5|0xd6|0xd7)) | |
- # jmpq %rax/%rcx/%rdx/%rbx/%rsp/%rbp/%rsi/%rdi |
- (REX_WRX? 0xff (0xe0|0xe1|0xe2|0xe3|0xe4|0xe5|0xe6|0xe7)))) |
- @{ |
- instruction_start -= 6; |
- if (RMFromModRM(instruction_start[1]) != |
- RMFromModRM(instruction_start[5]) || |
- RMFromModRM(instruction_start[1]) != RMFromModRM(*current_position)) |
- instruction_info_collected |= UNRECOGNIZED_INSTRUCTION; |
- BitmapClearBit(valid_targets, (instruction_start - data) + 3); |
- BitmapClearBit(valid_targets, (instruction_start - data) + 6); |
- restricted_register = NO_REG; |
- } | |
- |
- # and $~0x1f, %eax/%ecx/%edx/%ebx/%esp/%ebp/%esi/%edi |
- (0x83 (0xe0|0xe1|0xe2|0xe3|0xe4|0xe5|0xe6|0xe7) 0xe0 |
- # add %r15,%rax/%rcx/%rdx/%rbx/%rsp/%rbp/%rsi/%rdi |
- b_0100_10x1 0x03 (0xc7|0xcf|0xd7|0xdf|0xe7|0xef|0xf7|0xff) |
- # callq %rax/%rcx/%rdx/%rbx/%rsp/%rbp/%rsi/%rdi |
- ((REX_WRX? 0xff (0xd0|0xd1|0xd2|0xd3|0xd4|0xd5|0xd6|0xd7)) | |
- # jmpq %rax/%rcx/%rdx/%rbx/%rsp/%rbp/%rsi/%rdi |
- (REX_WRX? 0xff (0xe0|0xe1|0xe2|0xe3|0xe4|0xe5|0xe6|0xe7)))) |
- @{ |
- instruction_start -= 6; |
- if (RMFromModRM(instruction_start[1]) != |
- RegFromModRM(instruction_start[5]) || |
- RMFromModRM(instruction_start[1]) != RMFromModRM(*current_position)) |
- instruction_info_collected |= UNRECOGNIZED_INSTRUCTION; |
- BitmapClearBit(valid_targets, (instruction_start - data) + 3); |
- BitmapClearBit(valid_targets, (instruction_start - data) + 6); |
- restricted_register = NO_REG; |
- } | |
- |
- # rex.R?X? and $~0x1f, %eax/%ecx/%edx/%ebx/%esp/%ebp/%esi/%edi |
- ((REX_RX 0x83 (0xe0|0xe1|0xe2|0xe3|0xe4|0xe5|0xe6|0xe7) 0xe0 |
- # add %r15,%rax/%rcx/%rdx/%rbx/%rsp/%rbp/%rsi/%rdi |
- b_0100_11x0 0x01 (0xf8|0xf9|0xfa|0xfb|0xfc|0xfd|0xfe|0xff) |
- # callq %rax/%rcx/%rdx/%rbx/%rsp/%rbp/%rsi/%rdi |
- ((REX_WRX? 0xff (0xd0|0xd1|0xd2|0xd3|0xd4|0xd5|0xd6|0xd7)) | |
- # jmpq %rax/%rcx/%rdx/%rbx/%rsp/%rbp/%rsi/%rdi |
- (REX_WRX? 0xff (0xe0|0xe1|0xe2|0xe3|0xe4|0xe5|0xe6|0xe7)))) | |
- |
- # and $~0x1f, %r8d/%r9d/%r10d/%r11d/%r12d/%r13d/%r14d |
- (b_0100_0xx1 0x83 (0xe0|0xe1|0xe2|0xe3|0xe4|0xe5|0xe6) 0xe0 |
- # add %r15, %r8d/%r9d/%r10d/%r11d/%r12d/%r13d/%r14d |
- b_0100_11x1 0x01 (0xf8|0xf9|0xfa|0xfb|0xfc|0xfd|0xfe) |
- # callq %r8/%r9/%r10/%r11/%r12/%r13/%r14 |
- ((b_0100_xxx1 0xff (0xd0|0xd1|0xd2|0xd3|0xd4|0xd5|0xd6)) | |
- # jmpq %r8/%r9/%r10/%r11/%r12/%r13/%r14 |
- (b_0100_xxx1 0xff (0xe0|0xe1|0xe2|0xe3|0xe4|0xe5|0xe6))))) |
- @{ |
- instruction_start -= 7; |
- if (RMFromModRM(instruction_start[2]) != |
- RMFromModRM(instruction_start[6]) || |
- RMFromModRM(instruction_start[2]) != RMFromModRM(*current_position)) |
- instruction_info_collected |= UNRECOGNIZED_INSTRUCTION; |
- BitmapClearBit(valid_targets, (instruction_start - data) + 4); |
- BitmapClearBit(valid_targets, (instruction_start - data) + 7); |
- restricted_register = NO_REG; |
- } | |
- |
- # rex.R?X? and $~0x1f, %eax/%ecx/%edx/%ebx/%esp/%ebp/%esi/%edi |
- ((REX_RX 0x83 (0xe0|0xe1|0xe2|0xe3|0xe4|0xe5|0xe6|0xe7) 0xe0 |
- # add %r15,%rax/%rcx/%rdx/%rbx/%rsp/%rbp/%rsi/%rdi |
- b_0100_10x1 0x03 (0xc7|0xcf|0xd7|0xdf|0xe7|0xef|0xf7|0xff) |
- # callq %rax/%rcx/%rdx/%rbx/%rsp/%rbp/%rsi/%rdi |
- ((REX_WRX? 0xff (0xd0|0xd1|0xd2|0xd3|0xd4|0xd5|0xd6|0xd7)) | |
- # jmpq %rax/%rcx/%rdx/%rbx/%rsp/%rbp/%rsi/%rdi |
- (REX_WRX? 0xff (0xe0|0xe1|0xe2|0xe3|0xe4|0xe5|0xe6|0xe7)))) | |
- |
- # and $~0x1f, %r8d/%r9d/%r10d/%r11d/%r12d/%r13d/%r14d |
- (b_0100_0xx1 0x83 (0xe0|0xe1|0xe2|0xe3|0xe4|0xe5|0xe6) 0xe0 |
- # add %r15, %r8d/%r9d/%r10d/%r11d/%r12d/%r13d/%r14d |
- b_0100_11x1 0x03 (0xc7|0xcf|0xd7|0xdf|0xe7|0xef|0xf7) |
- # callq %r8/%r9/%r10/%r11/%r12/%r13/%r14 |
- ((b_0100_xxx1 0xff (0xd0|0xd1|0xd2|0xd3|0xd4|0xd5|0xd6)) | |
- # jmpq %r8/%r9/%r10/%r11/%r12/%r13/%r14 |
- (b_0100_xxx1 0xff (0xe0|0xe1|0xe2|0xe3|0xe4|0xe5|0xe6))))) |
- @{ |
- instruction_start -= 7; |
- if (RMFromModRM(instruction_start[2]) != |
- RegFromModRM(instruction_start[6]) || |
- RMFromModRM(instruction_start[2]) != RMFromModRM(*current_position)) |
- instruction_info_collected |= UNRECOGNIZED_INSTRUCTION; |
- BitmapClearBit(valid_targets, (instruction_start - data) + 4); |
- BitmapClearBit(valid_targets, (instruction_start - data) + 7); |
- restricted_register = NO_REG; |
- }; |
- |
- # EMMS/SSE2/AVX instructions which have implicit %ds:(%rsi) operand |
- # maskmovq %mmX,%mmY |
- maskmovq = |
- REX_WRXB? (0x0f 0xf7) |
- @CPUFeature_EMMX modrm_registers; |
- # maskmovdqu %xmmX, %xmmY |
- maskmovdqu = |
- 0x66 REX_WRXB? (0x0f 0xf7) @not_data16_prefix |
- @CPUFeature_SSE2 modrm_registers; |
- # vmaskmovdqu %xmmX, %xmmY |
- vmaskmovdqu = |
- ((0xc4 (VEX_RB & VEX_map00001) 0x79 @vex_prefix3) | |
- (0xc5 (0x79 | 0xf9) @vex_prefix_short)) 0xf7 |
- @CPUFeature_AVX modrm_registers; |
- mmx_sse_rdi_instruction = maskmovq | maskmovdqu | vmaskmovdqu; |
- |
- # String instructions which use only %ds:(%rsi) |
- string_instruction_rsi_no_rdi = |
- (rep? 0xac | # lods %ds:(%rsi),%al |
- data16rep 0xad | # lods %ds:(%rsi),%ax |
- rep? REXW_NONE? 0xad) ; # lods %ds:(%rsi),%eax/%rax |
- |
- # String instructions which use only %ds:(%rdi) |
- string_instruction_rdi_no_rsi = |
- condrep? 0xae | # scas %es:(%rdi),%al |
- data16condrep 0xaf | # scas %es:(%rdi),%ax |
- condrep? REXW_NONE? 0xaf | # scas %es:(%rdi),%eax/%rax |
- |
- rep? 0xaa | # stos %al,%es:(%rdi) |
- data16rep 0xab | # stos %ax,%es:(%rdi) |
- rep? REXW_NONE? 0xab ; # stos %eax/%rax,%es:(%rdi) |
- |
- # String instructions which use both %ds:(%rsi) and %ds:(%rdi) |
- string_instruction_rsi_rdi = |
- condrep? 0xa6 | # cmpsb %es:(%rdi),%ds:(%rsi) |
- data16condrep 0xa7 | # cmpsw %es:(%rdi),%ds:(%rsi) |
- condrep? REXW_NONE? 0xa7 | # cmps[lq] %es:(%rdi),%ds:(%rsi) |
- |
- rep? 0xa4 | # movsb %es:(%rdi),%ds:(%rsi) |
- data16rep 0xa5 | # movsw %es:(%rdi),%ds:(%rsi) |
- rep? REXW_NONE? 0xa5 ; # movs[lq] %es:(%rdi),%ds:(%rsi) |
- |
- sandbox_instruction_rsi_no_rdi = |
- (0x89 | 0x8b) 0xf6 . # mov %esi,%esi |
- 0x49 0x8d 0x34 0x37 . # lea (%r15,%rsi,1),%rsi |
- string_instruction_rsi_no_rdi |
- @{ |
- instruction_start -= 6; |
- BitmapClearBit(valid_targets, (instruction_start - data) + 2); |
- BitmapClearBit(valid_targets, (instruction_start - data) + 6); |
- restricted_register = NO_REG; |
- } | |
- |
- REX_X (0x89 | 0x8b) 0xf6 . # mov %esi,%esi |
- 0x49 0x8d 0x34 0x37 . # lea (%r15,%rsi,1),%rsi |
- string_instruction_rsi_no_rdi |
- @{ |
- instruction_start -= 7; |
- BitmapClearBit(valid_targets, (instruction_start - data) + 3); |
- BitmapClearBit(valid_targets, (instruction_start - data) + 7); |
- restricted_register = NO_REG; |
- }; |
- |
- sandbox_instruction_rdi_no_rsi = |
- (0x89 | 0x8b) 0xff . # mov %edi,%edi |
- 0x49 0x8d 0x3c 0x3f . # lea (%r15,%rdi,1),%rdi |
- (string_instruction_rdi_no_rsi | mmx_sse_rdi_instruction) |
- @{ |
- instruction_start -= 6; |
- BitmapClearBit(valid_targets, (instruction_start - data) + 2); |
- BitmapClearBit(valid_targets, (instruction_start - data) + 6); |
- restricted_register = NO_REG; |
- } | |
- |
- REX_X (0x89 | 0x8b) 0xff . # mov %edi,%edi |
- 0x49 0x8d 0x3c 0x3f . # lea (%r15,%rdi,1),%rdi |
- (string_instruction_rdi_no_rsi | mmx_sse_rdi_instruction) |
- @{ |
- instruction_start -= 7; |
- BitmapClearBit(valid_targets, (instruction_start - data) + 3); |
- BitmapClearBit(valid_targets, (instruction_start - data) + 7); |
- restricted_register = NO_REG; |
- }; |
- |
- |
- # String instructions which use both %ds:(%rsi) and %ds:(%rdi) |
- sandbox_instruction_rsi_rdi = |
- (0x89 | 0x8b) 0xf6 . # mov %esi,%esi |
- 0x49 0x8d 0x34 0x37 . # lea (%r15,%rsi,1),%rsi |
- (0x89 | 0x8b) 0xff . # mov %edi,%edi |
- 0x49 0x8d 0x3c 0x3f . # lea (%r15,%rdi,1),%rdi |
- string_instruction_rsi_rdi |
- @{ |
- instruction_start -= 12; |
- BitmapClearBit(valid_targets, (instruction_start - data) + 2); |
- BitmapClearBit(valid_targets, (instruction_start - data) + 6); |
- BitmapClearBit(valid_targets, (instruction_start - data) + 8); |
- BitmapClearBit(valid_targets, (instruction_start - data) + 12); |
- restricted_register = NO_REG; |
- } | |
- |
- (0x89 | 0x8b) 0xf6 . # mov %esi,%esi |
- 0x49 0x8d 0x34 0x37 . # lea (%r15,%rsi,1),%rsi |
- REX_X (0x89 | 0x8b) 0xff . # mov %edi,%edi |
- 0x49 0x8d 0x3c 0x3f . # lea (%r15,%rdi,1),%rdi |
- string_instruction_rsi_rdi |
- @{ |
- instruction_start -= 13; |
- BitmapClearBit(valid_targets, (instruction_start - data) + 2); |
- BitmapClearBit(valid_targets, (instruction_start - data) + 6); |
- BitmapClearBit(valid_targets, (instruction_start - data) + 9); |
- BitmapClearBit(valid_targets, (instruction_start - data) + 13); |
- restricted_register = NO_REG; |
- } | |
- |
- REX_X (0x89 | 0x8b) 0xf6 . # mov %esi,%esi |
- 0x49 0x8d 0x34 0x37 . # lea (%r15,%rsi,1),%rsi |
- (0x89 | 0x8b) 0xff . # mov %edi,%edi |
- 0x49 0x8d 0x3c 0x3f . # lea (%r15,%rdi,1),%rdi |
- string_instruction_rsi_rdi |
- @{ |
- instruction_start -= 13; |
- BitmapClearBit(valid_targets, (instruction_start - data) + 3); |
- BitmapClearBit(valid_targets, (instruction_start - data) + 7); |
- BitmapClearBit(valid_targets, (instruction_start - data) + 9); |
- BitmapClearBit(valid_targets, (instruction_start - data) + 13); |
- restricted_register = NO_REG; |
- } | |
- |
- REX_X (0x89 | 0x8b) 0xf6 . # mov %esi,%esi |
- 0x49 0x8d 0x34 0x37 . # lea (%r15,%rsi,1),%rsi |
- REX_X (0x89 | 0x8b) 0xff . # mov %edi,%edi |
- 0x49 0x8d 0x3c 0x3f . # lea (%r15,%rdi,1),%rdi |
- string_instruction_rsi_rdi |
- @{ |
- instruction_start -= 14; |
- BitmapClearBit(valid_targets, (instruction_start - data) + 3); |
- BitmapClearBit(valid_targets, (instruction_start - data) + 7); |
- BitmapClearBit(valid_targets, (instruction_start - data) + 10); |
- BitmapClearBit(valid_targets, (instruction_start - data) + 14); |
- restricted_register = NO_REG; |
- }; |
- |
- special_instruction = |
- (rbp_modifications | |
- rsp_modifications | |
- rbp_sandboxing | |
- rsp_sandboxing | |
- naclcall_or_nacljmp | |
- sandbox_instruction_rsi_no_rdi | |
- sandbox_instruction_rdi_no_rsi | |
- sandbox_instruction_rsi_rdi) |
- @{ |
- instruction_info_collected |= SPECIAL_INSTRUCTION; |
- }; |
- |
- # Remove special instructions which are only allowed in special cases. |
- normal_instruction = one_instruction - special_instruction; |
- |
- # Check if call is properly aligned |
- call_alignment = |
- ((normal_instruction & |
- # Direct call |
- ((data16 REX_RXB? 0xe8 rel16) | |
- (REX_WRXB? 0xe8 rel32) | |
- (data16 REXW_RXB 0xe8 rel32))) | |
- (special_instruction & |
- # Indirect call |
- (any* data16? REX_WRXB? 0xff ((opcode_2 | opcode_3) any* & |
- (modrm_memory | modrm_registers))))) |
- @{ |
- if (((current_position - data) & kBundleMask) != kBundleMask) |
- instruction_info_collected |= BAD_CALL_ALIGNMENT; |
- }; |
- |
- |
- main := ((call_alignment | normal_instruction | special_instruction) |
- >{ |
- BitmapSetBit(valid_targets, current_position - data); |
- } |
- @{ |
- if ((instruction_info_collected & |
- (VALIDATION_ERRORS_MASK | BAD_CALL_ALIGNMENT)) || |
- (options & CALL_USER_CALLBACK_ON_EACH_INSTRUCTION)) { |
- result &= user_callback( |
- instruction_start, current_position, |
- instruction_info_collected | |
- ((restricted_register << RESTRICTED_REGISTER_SHIFT) & |
- RESTRICTED_REGISTER_MASK), callback_data); |
- } |
- /* On successful match the instruction start must point to the next byte |
- * to be able to report the new offset as the start of instruction |
- * causing error. */ |
- instruction_start = current_position + 1; |
- instruction_info_collected = 0; |
- SET_REX_PREFIX(FALSE); |
- SET_VEX_PREFIX2(0xe0); |
- SET_VEX_PREFIX3(0x00); |
- operand_states = 0; |
- })* |
- $err{ |
- result &= user_callback(instruction_start, current_position, |
- UNRECOGNIZED_INSTRUCTION, callback_data); |
- continue; |
- }; |
- |
-}%% |
- |
-%% write data; |
- |
-Bool ValidateChunkAMD64(const uint8_t *data, size_t size, |
- enum validation_options options, |
- const NaClCPUFeaturesX86 *cpu_features, |
- validation_callback_func user_callback, |
- void *callback_data) { |
- bitmap_word valid_targets_small; |
- bitmap_word jump_dests_small; |
- bitmap_word *valid_targets; |
- bitmap_word *jump_dests; |
- const uint8_t *current_position; |
- const uint8_t *end_of_bundle; |
- int result = TRUE; |
- |
- CHECK(sizeof valid_targets_small == sizeof jump_dests_small); |
- CHECK(size % kBundleSize == 0); |
- |
- /* For a very small sequence (one bundle) malloc is too expensive. */ |
- if (size <= sizeof valid_targets_small) { |
- valid_targets_small = 0; |
- valid_targets = &valid_targets_small; |
- jump_dests_small = 0; |
- jump_dests = &jump_dests_small; |
- } else { |
- valid_targets = BitmapAllocate(size); |
- jump_dests = BitmapAllocate(size); |
- if (!valid_targets || !jump_dests) { |
- free(jump_dests); |
- free(valid_targets); |
- errno = ENOMEM; |
- return FALSE; |
- } |
- } |
- |
- if (options & PROCESS_CHUNK_AS_A_CONTIGUOUS_STREAM) |
- end_of_bundle = data + size; |
- else |
- end_of_bundle = data + kBundleSize; |
- |
- for (current_position = data; |
- current_position < data + size; |
- current_position = end_of_bundle, |
- end_of_bundle = current_position + kBundleSize) { |
- /* Start of the instruction being processed. */ |
- const uint8_t *instruction_start = current_position; |
- int current_state; |
- uint32_t instruction_info_collected = 0; |
- /* Keeps one byte of information per operand in the current instruction: |
- * 2 bits for register kinds, |
- * 5 bits for register numbers (16 regs plus RIZ). */ |
- uint32_t operand_states = 0; |
- enum register_name base = NO_REG; |
- enum register_name index = NO_REG; |
- enum register_name restricted_register = NO_REG; |
- uint8_t rex_prefix = FALSE; |
- uint8_t vex_prefix2 = 0xe0; |
- uint8_t vex_prefix3 = 0x00; |
- |
- %% write init; |
- %% write exec; |
- |
- if (restricted_register == REG_RBP) |
- result &= user_callback(end_of_bundle, end_of_bundle, |
- RESTRICTED_RBP_UNPROCESSED | |
- ((REG_RBP << RESTRICTED_REGISTER_SHIFT) & |
- RESTRICTED_REGISTER_MASK), callback_data); |
- else if (restricted_register == REG_RSP) |
- result &= user_callback(end_of_bundle, end_of_bundle, |
- RESTRICTED_RSP_UNPROCESSED | |
- ((REG_RSP << RESTRICTED_REGISTER_SHIFT) & |
- RESTRICTED_REGISTER_MASK), callback_data); |
- } |
- |
- result &= ProcessInvalidJumpTargets(data, size, valid_targets, jump_dests, |
- user_callback, callback_data); |
- |
- /* We only use malloc for a large code sequences */ |
- if (size > sizeof valid_targets_small) { |
- free(jump_dests); |
- free(valid_targets); |
- } |
- if (!result) errno = EINVAL; |
- return result; |
-} |