Chromium Code Reviews| Index: src/trusted/validator_ragel/validator_x86_32.rl |
| =================================================================== |
| --- src/trusted/validator_ragel/validator_x86_32.rl (revision 10976) |
| +++ src/trusted/validator_ragel/validator_x86_32.rl (working copy) |
| @@ -20,9 +20,10 @@ |
| #include <string.h> |
| #include "native_client/src/trusted/validator_ragel/bitmap.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. */ |
| +/* TODO(khim): change gen_dfa to remove needs for these lines. */ |
| #undef GET_VEX_PREFIX3 |
| #define GET_VEX_PREFIX3 0 |
| #undef SET_VEX_PREFIX3 |
| @@ -61,14 +62,6 @@ |
| 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 property. 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; |
| - } |
| - |
| include decode_x86_32 "validator_x86_32_instruction.rl"; |
| special_instruction = |
| @@ -93,20 +86,19 @@ |
| 0x65 0x8b (0x05|0x0d|0x015|0x1d|0x25|0x2d|0x35|0x3d) |
| (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 register-addressed |
| - # indirect call. |
| + # For direct call we explicitly encode all variations. |
| + direct_call = (data16 0xe8 rel16) | (0xe8 rel32); |
| + |
| + # For indirect call we accept only near register-addressed indirect call. |
| + indirect_call_register = data16? 0xff (opcode_2 & modrm_registers); |
| + |
| + # Ragel machine that accepts one call instruction or call superinstruction and |
| + # checks if call is properly aligned. |
| call_alignment = |
| - ((one_instruction & |
| - # Direct call |
| - ((data16 0xe8 rel16) | |
| - (0xe8 rel32))) | |
| - (special_instruction & |
| - # Indirect call |
| - (any* data16? 0xff ((opcode_2 | opcode_3) any* & |
| - modrm_registers)))) |
| + ((one_instruction & direct_call) |
| + # For indirect calls we accept all the special instructions which ends with |
| + # register-addressed indirect call. |
| + (special_instruction & (any* indirect_call_register))) |
| # Call instruction must aligned to the end of bundle. Previously this was |
| # strict requirement, today it's just warning to aid with debugging. |
| @{ |
| @@ -114,15 +106,15 @@ |
| instruction_info_collected |= BAD_CALL_ALIGNMENT; |
| }; |
| - # This action calls user's callback (if needed) and cleans up validator's |
| + # This action calls users callback (if needed) and cleans up validators |
|
halyavin
2013/03/19 15:03:54
user, not users
khim
2013/03/21 14:38:17
Done.
|
| # internal state. |
| # |
| - # We call the user callback if there are validation errors or if the |
| - # CALL_USER_CALLBACK_ON_EACH_INSTRUCTION option is used. |
| + # We call the user callback either on validation errors or on every |
| + # instruction, depending on CALL_USER_CALLBACK_ON_EACH_INSTRUTION option. |
| # |
| # After that we move instruction_begin and clean all the variables which |
| - # only used in the processing of a single instruction (prefixes, operand |
| - # states and instruction_info_collected). |
| + # are only used in the processing of a single instruction (here it's just |
| + # instruction_info_collected, there are more state in x86-64 case). |
| action end_of_instruction_cleanup { |
| /* Mark start of this instruction as a valid target for jump. */ |
| MarkValidJumpTarget(instruction_begin - data, valid_targets); |
| @@ -135,9 +127,11 @@ |
| instruction_info_collected, callback_data); |
| } |
| - /* On successful match the instruction_begin must point to the next byte |
| - * to be able to report the new offset as the start of instruction |
| - * causing error. */ |
| + /* |
| + * We may set instruction_begin at the first byte of the instruction instead |
| + * of here but in the case of incorrect one byte instructions user callback |
| + * may be called before instruction_begin is set. |
| + */ |
| instruction_begin = instruction_end; |
| /* Clear variables (well, one variable currently). */ |
| @@ -160,8 +154,8 @@ |
| } |
| # This is main ragel machine: it does 99% of validation work. There are only |
| - # one thing to do if this machine accepts the bundles - check that direct |
| - # jumps are correct. This is done in the following way: |
| + # one thing to do if this ragel machine accepts the bundles - check that |
| + # direct jumps are correct. This is done in the following way: |
| # * DFA fills two arrays: valid_targets and jump_dests. |
| # * ProcessInvalidJumpTargets checks that "jump_dests & !valid_targets == 0". |
| # All other checks are done here. |
| @@ -171,9 +165,12 @@ |
| }%% |
| +/* |
| + * The "write data" statement causes Ragel to emit the constant static data |
| + * needed by the ragel machine. |
| + */ |
| %% write data; |
| - |
| Bool ValidateChunkIA32(const uint8_t *data, size_t size, |
| uint32_t options, |
| const NaClCPUFeaturesX86 *cpu_features, |
| @@ -210,7 +207,7 @@ |
| /* |
| * This option is usually used in tests: we will process the whole chunk |
| * in one pass. Usually each bundle is processed separately which means |
| - * instructions (and super-instructions) can not cross borders of the bundle. |
| + * instructions (and "superinstructions") can not cross borders of the bundle. |
| */ |
| if (options & PROCESS_CHUNK_AS_A_CONTIGUOUS_STREAM) |
| end_of_bundle = data + size; |
| @@ -234,7 +231,15 @@ |
| uint32_t instruction_info_collected = 0; |
| int current_state; |
| + /* |
| + * The "write init" statement causes Ragel to emit initialization code. |
| + * This should be executed once before the ragel machine is started. |
| + */ |
| %% write init; |
| + /* |
| + * The "write exec" statement causes Ragel to emit the ragel machine's |
| + * execution code. |
| + */ |
| %% write exec; |
| } |