Index: src/trusted/validator_ragel/validator_x86_32.rl |
=================================================================== |
--- src/trusted/validator_ragel/validator_x86_32.rl (revision 9944) |
+++ src/trusted/validator_ragel/validator_x86_32.rl (working copy) |
@@ -4,6 +4,14 @@ |
* found in the LICENSE file. |
*/ |
+/* |
+ * This is the core of ia32-mode validator. Please note that this file |
+ * combines ragel machine description and C language actions. Please read |
+ * validator_internals.html first to understand how the whole thing is built: |
+ * it explains how the byte sequences are constructed, what constructs like |
+ * “@{}” or “REX_WRX?” mean, etc. |
+ */ |
+ |
#include <assert.h> |
#include <errno.h> |
#include <stddef.h> |
@@ -11,7 +19,7 @@ |
#include <stdlib.h> |
#include <string.h> |
-#include "native_client/src/trusted/validator_ragel/unreviewed/validator_internal.h" |
+#include "native_client/src/trusted/validator_ragel/validator_internal.h" |
/* Ignore this information: it's not used by security model in IA32 mode. */ |
#undef GET_VEX_PREFIX3 |
@@ -47,13 +55,20 @@ |
"native_client/src/trusted/validator_ragel/unreviewed/parse_instruction.rl"; |
include immediate_fields_parsing_ia32 |
"native_client/src/trusted/validator_ragel/unreviewed/parse_instruction.rl"; |
+ # rel8 actions are used in relative jumps with 8-bit offset. |
action rel8_operand { |
rel8_operand(current_position + 1, data, jump_dests, size, |
&instruction_info_collected); |
} |
+ # rel16 actions are used in relative jums with 16-bit offset. |
+ # |
+ # Such instructions should be included in the validator's DFA, but we can not |
+ # just exlude them because they are refenced in relative_fields_parsing ragel |
+ # machine. Ensure compilations error in case of usage. |
action rel16_operand { |
#error rel16_operand should never be used in nacl |
} |
+ # rel32 actions are used in relative calls and jumps with 32-bit offset. |
action rel32_operand { |
rel32_operand(current_position + 1, data, jump_dests, size, |
&instruction_info_collected); |
@@ -63,6 +78,10 @@ |
include cpuid_actions |
"native_client/src/trusted/validator_ragel/unreviewed/parse_instruction.rl"; |
+ # Action which marks last byte as not immediate. Most 3DNow! instructions, |
+ # some AVX and XOP instructions have this proerty. It's referenced by |
+ # decode_x86_32 machine in [autogenerated] “validator_x86_32_instruction.rl” |
+ # file. |
action last_byte_is_not_immediate { |
instruction_info_collected |= LAST_BYTE_IS_NOT_IMMEDIATE; |
} |
@@ -70,16 +89,20 @@ |
include decode_x86_32 "validator_x86_32_instruction.rl"; |
special_instruction = |
- (0x83 0xe0 0xe0 0xff (0xd0|0xe0) | # naclcall/jmp %eax |
- 0x83 0xe1 0xe0 0xff (0xd1|0xe1) | # naclcall/jmp %ecx |
- 0x83 0xe2 0xe0 0xff (0xd2|0xe2) | # naclcall/jmp %edx |
- 0x83 0xe3 0xe0 0xff (0xd3|0xe3) | # naclcall/jmp %ebx |
- 0x83 0xe4 0xe0 0xff (0xd4|0xe4) | # naclcall/jmp %esp |
- 0x83 0xe5 0xe0 0xff (0xd5|0xe5) | # naclcall/jmp %ebp |
- 0x83 0xe6 0xe0 0xff (0xd6|0xe6) | # naclcall/jmp %esi |
- 0x83 0xe7 0xe0 0xff (0xd7|0xe7)) # naclcall/jmp %edi |
+ # and $~0x1f, %eXX call %eXX |
+ # ↓↓↓↓↓↓↓↓↓↓ |
Brad Chen
2012/10/22 21:29:05
What character are you using to generate the up an
khim
2013/03/08 17:59:53
Done.
|
+ (0x83 0xe0 0xe0 0xff (0xd0|0xe0) | # naclcall/jmp %eax |
+ 0x83 0xe1 0xe0 0xff (0xd1|0xe1) | # naclcall/jmp %ecx |
+ 0x83 0xe2 0xe0 0xff (0xd2|0xe2) | # naclcall/jmp %edx |
+ 0x83 0xe3 0xe0 0xff (0xd3|0xe3) | # naclcall/jmp %ebx |
+ 0x83 0xe4 0xe0 0xff (0xd4|0xe4) | # naclcall/jmp %esp |
+ 0x83 0xe5 0xe0 0xff (0xd5|0xe5) | # naclcall/jmp %ebp |
+ 0x83 0xe6 0xe0 0xff (0xd6|0xe6) | # naclcall/jmp %esi |
+ 0x83 0xe7 0xe0 0xff (0xd7|0xe7)) # naclcall/jmp %edi |
+ # ↑↑↑↑ ↑↑↑↑ |
+ # and $~0x1f, %eXX jmp %eXX |
@{ |
- BitmapClearBit(valid_targets, (current_position - data) - 1); |
+ MakeInvalidJumpTarget((current_position - data) - 1, valid_targets); |
instruction_start -= 3; |
instruction_info_collected |= SPECIAL_INSTRUCTION; |
} | |
@@ -88,6 +111,9 @@ |
(0x00|0x04) 0x00 0x00 0x00); # mov %gs:0x0/0x4,%reg |
# Check if call is properly aligned |
+ # |
+ # For direct call we explicitly encode all variations. For indirect call |
+ # we accept all the special instructions which ends with indirect call. |
call_alignment = |
((one_instruction & |
# Direct call |
@@ -97,15 +123,26 @@ |
# Indirect call |
(any* data16? 0xff ((opcode_2 | opcode_3) any* & |
(modrm_memory | modrm_registers))))) |
+ # Call instruction must aligned to the end of bundle. Previously this was |
+ # strict requirement, today it's just warning to aid with debugging. |
@{ |
if (((current_position - data) & kBundleMask) != kBundleMask) |
instruction_info_collected |= BAD_CALL_ALIGNMENT; |
}; |
main := ((call_alignment | one_instruction | special_instruction) |
+ # Beginning of the instruction is always valid target for jump. If this |
+ # instruction is, in fact, part of the superinstruction then we'll clear |
+ # that bit later. |
>{ |
- BitmapSetBit(valid_targets, current_position - data); |
+ MakeJumpTargetValid(current_position - data, valid_targets); |
} |
+ # Here we call the user callback if there are validation errors or if the |
+ # CALL_USER_CALLBACK_ON_EACH_INSTRUCTION option is used. |
+ # |
+ # After that we move instruction_start and clean all the variables which |
+ # only used in the processing of a single instruction (prefixes, operand |
+ # states and instruction_info_collected). |
@{ |
if ((instruction_info_collected & VALIDATION_ERRORS_MASK) || |
(options & CALL_USER_CALLBACK_ON_EACH_INSTRUCTION)) { |