| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (c) 2012 The Native Client Authors. All rights reserved. | 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 | 3 * Use of this source code is governed by a BSD-style license that can be |
| 4 * found in the LICENSE file. | 4 * found in the LICENSE file. |
| 5 */ | 5 */ |
| 6 | 6 |
| 7 /* | 7 /* |
| 8 * This is the core of amd64-mode validator. Please note that this file | 8 * This is the core of amd64-mode validator. Please note that this file |
| 9 * combines ragel machine description and C language actions. Please read | 9 * combines ragel machine description and C language actions. Please read |
| 10 * validator_internals.html first to understand how the whole thing is built: | 10 * validator_internals.html first to understand how the whole thing is built: |
| 11 * it explains how the byte sequences are constructed, what constructs like | 11 * it explains how the byte sequences are constructed, what constructs like |
| 12 * "@{}" or "REX_WRX?" mean, etc. | 12 * "@{}" or "REX_WRX?" mean, etc. |
| 13 */ | 13 */ |
| 14 | 14 |
| 15 #include <assert.h> | 15 #include <assert.h> |
| 16 #include <errno.h> | 16 #include <errno.h> |
| 17 #include <stddef.h> | 17 #include <stddef.h> |
| 18 #include <stdio.h> | 18 #include <stdio.h> |
| 19 #include <stdlib.h> | 19 #include <stdlib.h> |
| 20 #include <string.h> | 20 #include <string.h> |
| 21 | 21 |
| 22 #include "native_client/src/trusted/validator_ragel/bitmap.h" | 22 #include "native_client/src/trusted/validator_ragel/bitmap.h" |
| 23 #include "native_client/src/trusted/validator_ragel/unreviewed/validator_interna
l.h" | 23 #include "native_client/src/trusted/validator_ragel/validator_internal.h" |
| 24 | 24 |
| 25 %%{ | 25 %%{ |
| 26 machine x86_64_validator; | 26 machine x86_64_validator; |
| 27 alphtype unsigned char; | 27 alphtype unsigned char; |
| 28 variable p current_position; | 28 variable p current_position; |
| 29 variable pe end_of_bundle; | 29 variable pe end_of_bundle; |
| 30 variable eof end_of_bundle; | 30 variable eof end_of_bundle; |
| 31 variable cs current_state; | 31 variable cs current_state; |
| 32 | 32 |
| 33 include byte_machine "byte_machines.rl"; | 33 include byte_machine "byte_machines.rl"; |
| (...skipping 30 matching lines...) Expand all Loading... |
| 64 "native_client/src/trusted/validator_ragel/unreviewed/parse_instruction.rl"; | 64 "native_client/src/trusted/validator_ragel/unreviewed/parse_instruction.rl"; |
| 65 include cpuid_actions | 65 include cpuid_actions |
| 66 "native_client/src/trusted/validator_ragel/unreviewed/parse_instruction.rl"; | 66 "native_client/src/trusted/validator_ragel/unreviewed/parse_instruction.rl"; |
| 67 | 67 |
| 68 action check_access { | 68 action check_access { |
| 69 CheckAccess(instruction_begin - data, base, index, restricted_register, | 69 CheckAccess(instruction_begin - data, base, index, restricted_register, |
| 70 valid_targets, &instruction_info_collected); | 70 valid_targets, &instruction_info_collected); |
| 71 } | 71 } |
| 72 | 72 |
| 73 # Action which marks last byte as not immediate. Most 3DNow! instructions, | 73 # Action which marks last byte as not immediate. Most 3DNow! instructions, |
| 74 # some AVX and XOP instructions have this proerty. It's referenced by | 74 # some AVX and XOP instructions have this property. |
| 75 # decode_x86_32 machine in [autogenerated] "validator_x86_32_instruction.rl" | 75 # |
| 76 # file. | 76 # This action is referenced by decode_x86_32 ragel machine in [autogenerated] |
| 77 # "validator_x86_64_instruction.rl" file. |
| 77 action last_byte_is_not_immediate { | 78 action last_byte_is_not_immediate { |
| 78 instruction_info_collected |= LAST_BYTE_IS_NOT_IMMEDIATE; | 79 instruction_info_collected |= LAST_BYTE_IS_NOT_IMMEDIATE; |
| 79 } | 80 } |
| 80 | 81 |
| 81 action modifiable_instruction { | 82 action modifiable_instruction { |
| 82 instruction_info_collected |= MODIFIABLE_INSTRUCTION; | 83 instruction_info_collected |= MODIFIABLE_INSTRUCTION; |
| 83 } | 84 } |
| 84 | 85 |
| 85 action process_0_operands { | 86 action process_0_operands { |
| 86 Process0Operands(&restricted_register, &instruction_info_collected); | 87 Process0Operands(&restricted_register, &instruction_info_collected); |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 131 # instruction (it gets assembled as 'lea 0x00(%rbp,%r15,1),%rbp'). | 132 # instruction (it gets assembled as 'lea 0x00(%rbp,%r15,1),%rbp'). |
| 132 0x4a 0x8d 0x6c 0x3d 0x00 | # lea 0x00(%rbp,%r15,1),%rbp | 133 0x4a 0x8d 0x6c 0x3d 0x00 | # lea 0x00(%rbp,%r15,1),%rbp |
| 133 0x4a 0x8d 0xac 0x3d 0x00 0x00 0x00 0x00) # lea 0x00000000(%rbp,%r15,1),%rbp | 134 0x4a 0x8d 0xac 0x3d 0x00 0x00 0x00 0x00) # lea 0x00000000(%rbp,%r15,1),%rbp |
| 134 # Note: restricted_register keeps the restricted register as explained in | 135 # Note: restricted_register keeps the restricted register as explained in |
| 135 # http://www.chromium.org/nativeclient/design-documents/nacl-sfi-model-on-x8
6-64-systems | 136 # http://www.chromium.org/nativeclient/design-documents/nacl-sfi-model-on-x8
6-64-systems |
| 136 # | 137 # |
| 137 # "Normal" instructions can not be used in a place where %rbp is restricted. | 138 # "Normal" instructions can not be used in a place where %rbp is restricted. |
| 138 # But since these instructions are "second half" of the %rbp sandboxing they | 139 # But since these instructions are "second half" of the %rbp sandboxing they |
| 139 # can be used *only* when %rbp is restricted. | 140 # can be used *only* when %rbp is restricted. |
| 140 # | 141 # |
| 141 # That is (normal instruction): | 142 # Compare: |
| 142 # mov %eax,%ebp | 143 # mov %eax,%ebp |
| 143 # mov %esi,%edi <- Error: %ebp is restricted | 144 # mov %esi,%edi <- Error: %ebp is restricted |
| 144 # vs | 145 # vs |
| 145 # mov %esi,%edi | 146 # mov %esi,%edi |
| 146 # add %r15,%rbp <- Error: %ebp is *not* restricted | 147 # add %r15,%rbp <- Error: %ebp is *not* restricted |
| 147 # vs | 148 # vs |
| 148 # mov %eax,%ebp | 149 # mov %eax,%ebp |
| 149 # add %r15,%rbp <- Ok: %rbp is restricted as it should be | 150 # add %r15,%rbp <- Ok: %rbp is restricted as it should be |
| 150 # | 151 # |
| 151 # Check this precondition and mark the beginning of the instruction as | 152 # Check this precondition and mark the beginning of the instruction as |
| 152 # invalid jump for target. | 153 # invalid jump for target. |
| 153 @{ if (restricted_register == REG_RBP) | 154 @{ if (restricted_register == REG_RBP) |
| 155 /* RESTRICTED_REGISTER_USED is informational flag used in tests. */ |
| 154 instruction_info_collected |= RESTRICTED_REGISTER_USED; | 156 instruction_info_collected |= RESTRICTED_REGISTER_USED; |
| 155 else | 157 else |
| 158 /* UNRESTRICTED_RSP_PROCESSED is error flag used in production. */ |
| 156 instruction_info_collected |= UNRESTRICTED_RBP_PROCESSED; | 159 instruction_info_collected |= UNRESTRICTED_RBP_PROCESSED; |
| 157 restricted_register = NO_REG; | 160 restricted_register = NO_REG; |
| 158 UnmarkValidJumpTarget((instruction_begin - data), valid_targets); | 161 UnmarkValidJumpTarget((instruction_begin - data), valid_targets); |
| 159 }; | 162 }; |
| 160 | 163 |
| 161 # Special %rsp modifications - the ones which don't need a sandboxing. | 164 # Special %rsp modifications - the ones which don't need a sandboxing. |
| 162 # | 165 # |
| 163 # Note that there are two different opcodes for "mov": in x86-64 there are two | 166 # Note that there are two different opcodes for "mov": in x86-64 there are two |
| 164 # fields in ModR/M byte (REG field and RM field) and "mov" may be used to move | 167 # fields in ModR/M byte (REG field and RM field) and "mov" may be used to move |
| 165 # from REG field to RM or in the other direction thus there are two encodings | 168 # from REG field to RM or in the other direction thus there are two encodings |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 214 instruction_info_collected |= UNRESTRICTED_RSP_PROCESSED; | 217 instruction_info_collected |= UNRESTRICTED_RSP_PROCESSED; |
| 215 restricted_register = NO_REG; | 218 restricted_register = NO_REG; |
| 216 UnmarkValidJumpTarget((instruction_begin - data), valid_targets); | 219 UnmarkValidJumpTarget((instruction_begin - data), valid_targets); |
| 217 }; | 220 }; |
| 218 | 221 |
| 219 # naclcall or nacljmp. These are three-instruction indirection-jump sequences. | 222 # naclcall or nacljmp. These are three-instruction indirection-jump sequences. |
| 220 # and $~0x1f, %eXX | 223 # and $~0x1f, %eXX |
| 221 # and RBASE, %rXX | 224 # and RBASE, %rXX |
| 222 # jmpq *%rXX (or: callq *%rXX) | 225 # jmpq *%rXX (or: callq *%rXX) |
| 223 # Note: first "and $~0x1f, %eXX" is a normal instruction (it can occur not | 226 # Note: first "and $~0x1f, %eXX" is a normal instruction (it can occur not |
| 224 # just as part of the naclcall/nacljmp, but also as a standolene instruction). | 227 # just as part of the naclcall/nacljmp, but also as a standalene instruction). |
| 225 # | 228 # |
| 226 # This means that when naclcall_or_nacljmp ragel machine will be combined with | 229 # This means that when naclcall_or_nacljmp ragel machine will be combined with |
| 227 # "normal_instruction*" regular action process_1_operand_zero_extends will be | 230 # "normal_instruction*" regular action process_1_operand_zero_extends will be |
| 228 # triggered when main ragel machine will accept "and $~0x1f, %eXX" x86-64 | 231 # triggered when main ragel machine will accept "and $~0x1f, %eXX" x86-64 |
| 229 # instruction. This action will check if %rbp/%rsp is legally modified thus | 232 # instruction. This action will check if %rbp/%rsp is legally modified thus |
| 230 # we don't need to duplicate this logic in naclcall_or_nacljmp ragel machine. | 233 # we don't need to duplicate this logic in naclcall_or_nacljmp ragel machine. |
| 231 # | 234 # |
| 232 # There are number of variants present which differ by the REX prefix usage: | 235 # There are number of variants present which differ by the REX prefix usage: |
| 233 # we need to make sure "%eXX" in "and", "%rXX" in "add", and "%eXX" in "jmpq" | 236 # we need to make sure "%eXX" in "and", "%rXX" in "add", and "%eXX" in "jmpq" |
| 234 # or "callq" is the same register and it's much simpler to do if one single | 237 # or "callq" is the same register and it's much simpler to do if one single |
| 235 # action handles only fixed number of bytes. | 238 # action handles only fixed number of bytes. |
| 236 # | 239 # |
| 237 # Additional complication arises because x86-64 contains two different "add" | 240 # Additional complication arises because x86-64 contains two different "add" |
| 238 # instruction: with "0x01" and "0x03" opcode. They differ in the direction | 241 # instruction: with "0x01" and "0x03" opcode. They differ in the direction |
| 239 # used: both can encode "add %src_register, %dst_register", but the first one | 242 # used: both can encode "add %src_register, %dst_register", but the first one |
| 240 # uses field REG of the ModR/M byte for the src and field RM of the ModR/M | 243 # uses field REG of the ModR/M byte for the src and field RM of the ModR/M |
| 241 # byte for the dst while last one uses field RM of the ModR/M byte for the src | 244 # byte for the dst while last one uses field RM of the ModR/M byte for the src |
| 242 # and field REG of the ModR/M byte for dst. Both should be allowed. | 245 # and field REG of the ModR/M byte for dst. Both should be allowed. |
| 243 # | 246 # |
| 244 # See AMD/Intel manual for clarification "add" instruction encoding. | 247 # See AMD/Intel manual for clarification about “add” instruction encoding. |
| 245 # | 248 # |
| 246 # REGISTER USAGE ABBREVIATIONS: | 249 # REGISTER USAGE ABBREVIATIONS: |
| 247 # E86: legacy ia32 registers (all eight: %eax to %edi) | 250 # E86: legacy ia32 registers (all eight: %eax to %edi) |
| 248 # R86: 64-bit counterparts for legacy 386 registers (%rax to %rdi) | 251 # R86: 64-bit counterparts for legacy 386 registers (%rax to %rdi) |
| 249 # E64: 32-bit counterparts for new amd64 registers (%r8d to %r14d) | 252 # E64: 32-bit counterparts for new amd64 registers (%r8d to %r14d) |
| 250 # R64: new amd64 registers (only seven: %r8 to %r14) | 253 # R64: new amd64 registers (only seven: %r8 to %r14) |
| 251 # RBASE: %r15 (used as "base of untrusted world" in NaCl for amd64) | 254 # RBASE: %r15 (used as "base of untrusted world" in NaCl for amd64) |
| 252 naclcall_or_nacljmp = | 255 naclcall_or_nacljmp = |
| 253 # This block encodes call and jump "superinstruction" of the following form: | 256 # This block encodes call and jump "superinstruction" of the following form: |
| 254 # 0: 83 e_ e0 and $~0x1f,E86 | 257 # 0: 83 e_ e0 and $~0x1f,E86 |
| (...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 365 ((b_0100_xxx1 0xff (b_11_010_xxx - b_11_010_111)) | | 368 ((b_0100_xxx1 0xff (b_11_010_xxx - b_11_010_111)) | |
| 366 #### INSTRUCTION THREE: jmp (three bytes) | 369 #### INSTRUCTION THREE: jmp (three bytes) |
| 367 # jmpq R64 | 370 # jmpq R64 |
| 368 (b_0100_xxx1 0xff (b_11_100_xxx - b_11_100_111))))) | 371 (b_0100_xxx1 0xff (b_11_100_xxx - b_11_100_111))))) |
| 369 @{ | 372 @{ |
| 370 ProcessNaclCallOrJmpAddToRegWithRex(&instruction_info_collected, | 373 ProcessNaclCallOrJmpAddToRegWithRex(&instruction_info_collected, |
| 371 &instruction_begin, current_position, | 374 &instruction_begin, current_position, |
| 372 data, valid_targets); | 375 data, valid_targets); |
| 373 }; | 376 }; |
| 374 | 377 |
| 375 # EMMS/SSE2/AVX instructions which have implicit %ds:(%rsi) operand | 378 # EMMX/SSE/SSE2/AVX instructions which have implicit %ds:(%rsi) operand |
| 376 # maskmovq %mmX,%mmY | 379 |
| 377 maskmovq = | 380 # maskmovq %mmX,%mmY (EMMX or SSE) |
| 378 REX_WRXB? (0x0f 0xf7) | 381 maskmovq = REX_WRXB? 0x0f 0xf7 @CPUFeature_EMMXSSE modrm_registers; |
| 379 @CPUFeature_EMMX modrm_registers; | 382 |
| 380 # maskmovdqu %xmmX, %xmmY | 383 # maskmovdqu %xmmX, %xmmY (SSE2) |
| 381 maskmovdqu = | 384 maskmovdqu = 0x66 REX_WRXB? 0x0f 0xf7 @CPUFeature_SSE2 modrm_registers; |
| 382 0x66 REX_WRXB? (0x0f 0xf7) @not_data16_prefix | 385 |
| 383 @CPUFeature_SSE2 modrm_registers; | 386 # vmaskmovdqu %xmmX, %xmmY (AVX) |
| 384 # vmaskmovdqu %xmmX, %xmmY | 387 vmaskmovdqu = ((0xc4 (VEX_RB & VEX_map00001) b_0_1111_0_01) | |
| 385 vmaskmovdqu = | 388 (0xc5 b_X_1111_0_01)) 0xf7 @CPUFeature_AVX modrm_registers; |
| 386 ((0xc4 (VEX_RB & VEX_map00001) 0x79 @vex_prefix3) | | 389 |
| 387 (0xc5 (0x79 | 0xf9) @vex_prefix_short)) 0xf7 | |
| 388 @CPUFeature_AVX modrm_registers; | |
| 389 mmx_sse_rdi_instruction = maskmovq | maskmovdqu | vmaskmovdqu; | 390 mmx_sse_rdi_instruction = maskmovq | maskmovdqu | vmaskmovdqu; |
| 390 | 391 |
| 391 # Temporary fix: for string instructions combination of data16 and rep(ne) | 392 # Temporary fix: for string instructions combination of data16 and rep(ne) |
| 392 # prefixes is disallowed to mimic old validator behavior. | 393 # prefixes is disallowed to mimic old validator behavior. |
| 393 # See http://code.google.com/p/nativeclient/issues/detail?id=1950 | 394 # See http://code.google.com/p/nativeclient/issues/detail?id=1950 |
| 394 | 395 |
| 395 # data16rep = (data16 | rep data16 | data16 rep); | 396 # data16rep = (data16 | rep data16 | data16 rep); |
| 396 # data16condrep = (data16 | condrep data16 | data16 condrep); | 397 # data16condrep = (data16 | condrep data16 | data16 condrep); |
| 397 data16rep = data16; | 398 data16rep = data16; |
| 398 data16condrep = data16; | 399 data16condrep = data16; |
| (...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 546 # Mark the instruction as special - currently this information is used only | 547 # Mark the instruction as special - currently this information is used only |
| 547 # in tests, but in the future we may use it for dynamic code modification | 548 # in tests, but in the future we may use it for dynamic code modification |
| 548 # support. | 549 # support. |
| 549 @{ | 550 @{ |
| 550 instruction_info_collected |= SPECIAL_INSTRUCTION; | 551 instruction_info_collected |= SPECIAL_INSTRUCTION; |
| 551 }; | 552 }; |
| 552 | 553 |
| 553 # Remove special instructions which are only allowed in special cases. | 554 # Remove special instructions which are only allowed in special cases. |
| 554 normal_instruction = one_instruction - special_instruction; | 555 normal_instruction = one_instruction - special_instruction; |
| 555 | 556 |
| 556 # Check if call is properly aligned. | 557 # Ragel machine which checks if call is properly aligned. |
| 557 # | 558 # |
| 558 # For direct call we explicitly encode all variations. For indirect call | 559 # For direct call we explicitly encode all variations. For indirect call |
| 559 # we accept all the special instructions which ends with indirect call. | 560 # we accept all the special instructions which ends with indirect call. |
| 560 call_alignment = | 561 call_alignment = |
| 561 ((normal_instruction & | 562 ((normal_instruction & |
| 562 # Direct call | 563 # Direct call |
| 563 ((data16 REX_RXB? 0xe8 rel16) | | 564 ((data16 REX_RXB? 0xe8 rel16) | |
| 564 (REX_WRXB? 0xe8 rel32) | | 565 (REX_WRXB? 0xe8 rel32) | |
| 565 (data16 REXW_RXB 0xe8 rel32))) | | 566 (data16 REXW_RXB 0xe8 rel32))) | |
| 566 (special_instruction & | 567 (special_instruction & |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 626 * the ValidateChunkAMD64 function. | 627 * the ValidateChunkAMD64 function. |
| 627 * | 628 * |
| 628 * It does not affect the case which we really care about (when code | 629 * It does not affect the case which we really care about (when code |
| 629 * is validatable), but makes it possible to detect more errors in one | 630 * is validatable), but makes it possible to detect more errors in one |
| 630 * run in tools like ncval. | 631 * run in tools like ncval. |
| 631 */ | 632 */ |
| 632 continue; | 633 continue; |
| 633 } | 634 } |
| 634 | 635 |
| 635 # This is main ragel machine: it does 99% of validation work. There are only | 636 # This is main ragel machine: it does 99% of validation work. There are only |
| 636 # one thing to do with bundle if this machine accepts the bundle: | 637 # one thing to do with bundle if this ragel machine accepts the bundle: |
| 637 # * check for the state of the restricted_register at the end of the bundle. | 638 # * check for the state of the restricted_register at the end of the bundle. |
| 638 # It's an error is %rbp or %rsp is restricted at the end of the bundle. | 639 # It's an error is %rbp or %rsp is restricted at the end of the bundle. |
| 639 # Additionally if all the bundles are fine you need to check that direct jumps | 640 # Additionally if all the bundles are fine you need to check that direct jumps |
| 640 # are corect. Thiis is done in the following way: | 641 # are corect. Thiis is done in the following way: |
| 641 # * DFA fills two arrays: valid_targets and jump_dests. | 642 # * DFA fills two arrays: valid_targets and jump_dests. |
| 642 # * ProcessInvalidJumpTargets checks that "jump_dests & !valid_targets == 0". | 643 # * ProcessInvalidJumpTargets checks that "jump_dests & !valid_targets == 0". |
| 643 # All other checks are done here. | 644 # All other checks are done here. |
| 644 | 645 |
| 645 main := ((call_alignment | normal_instruction | special_instruction) | 646 main := ((call_alignment | normal_instruction | special_instruction) |
| 646 @end_of_instruction_cleanup)* | 647 @end_of_instruction_cleanup)* |
| 647 $!report_fatal_error; | 648 $!report_fatal_error; |
| 648 | 649 |
| 649 }%% | 650 }%% |
| 650 | 651 |
| 652 /* |
| 653 * The "write data" statement causes Ragel to emit the constant static data |
| 654 * needed by the ragel machine. |
| 655 */ |
| 651 %% write data; | 656 %% write data; |
| 652 | 657 |
| 653 enum OperandKind { | 658 enum OperandKind { |
| 654 OPERAND_SANDBOX_IRRELEVANT = 0, | 659 OPERAND_SANDBOX_IRRELEVANT = 0, |
| 655 /* | 660 /* |
| 656 * Currently we do not distinguish 8bit and 16bit modifications from | 661 * Currently we do not distinguish 8bit and 16bit modifications from |
| 657 * OPERAND_SANDBOX_UNRESTRICTED to match the behavior of the old validator. | 662 * OPERAND_SANDBOX_UNRESTRICTED to match the behavior of the old validator. |
| 658 * | 663 * |
| 659 * 8bit operands must be distinguished from other types because the REX prefix | 664 * 8bit operands must be distinguished from other types because the REX prefix |
| 660 * regulates the choice between %ah and %spl, as well as %ch and %bpl. | 665 * regulates the choice between %ah and %spl, as well as %ch and %bpl. |
| (...skipping 503 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1164 free(jump_dests); | 1169 free(jump_dests); |
| 1165 free(valid_targets); | 1170 free(valid_targets); |
| 1166 errno = ENOMEM; | 1171 errno = ENOMEM; |
| 1167 return FALSE; | 1172 return FALSE; |
| 1168 } | 1173 } |
| 1169 } | 1174 } |
| 1170 | 1175 |
| 1171 /* | 1176 /* |
| 1172 * This option is usually used in tests: we will process the whole chunk | 1177 * This option is usually used in tests: we will process the whole chunk |
| 1173 * in one pass. Usually each bundle is processed separately which means | 1178 * in one pass. Usually each bundle is processed separately which means |
| 1174 * instructions (and super-instructions) can not cross borders of the bundle. | 1179 * instructions (and "superinstructions") can not cross borders of the bundle. |
| 1175 */ | 1180 */ |
| 1176 if (options & PROCESS_CHUNK_AS_A_CONTIGUOUS_STREAM) | 1181 if (options & PROCESS_CHUNK_AS_A_CONTIGUOUS_STREAM) |
| 1177 end_of_bundle = data + size; | 1182 end_of_bundle = data + size; |
| 1178 else | 1183 else |
| 1179 end_of_bundle = data + kBundleSize; | 1184 end_of_bundle = data + kBundleSize; |
| 1180 | 1185 |
| 1181 /* | 1186 /* |
| 1182 * Main loop. Here we process the data array bundle-after-bundle. | 1187 * Main loop. Here we process the data array bundle-after-bundle. |
| 1183 * Ragel-produced DFA does all the checks with one exception: direct jumps. | 1188 * Ragel-produced DFA does all the checks with one exception: direct jumps. |
| 1184 * It collects the two arrays: valid_targets and jump_dests which are used | 1189 * It collects the two arrays: valid_targets and jump_dests which are used |
| (...skipping 15 matching lines...) Expand all Loading... |
| 1200 uint32_t operand_states = 0; | 1205 uint32_t operand_states = 0; |
| 1201 enum OperandName base = NO_REG; | 1206 enum OperandName base = NO_REG; |
| 1202 enum OperandName index = NO_REG; | 1207 enum OperandName index = NO_REG; |
| 1203 enum OperandName restricted_register = | 1208 enum OperandName restricted_register = |
| 1204 EXTRACT_RESTRICTED_REGISTER_INITIAL_VALUE(options); | 1209 EXTRACT_RESTRICTED_REGISTER_INITIAL_VALUE(options); |
| 1205 uint8_t rex_prefix = FALSE; | 1210 uint8_t rex_prefix = FALSE; |
| 1206 /* Top three bits of VEX2 are inverted: see AMD/Intel manual. */ | 1211 /* Top three bits of VEX2 are inverted: see AMD/Intel manual. */ |
| 1207 uint8_t vex_prefix2 = VEX_R | VEX_X | VEX_B; | 1212 uint8_t vex_prefix2 = VEX_R | VEX_X | VEX_B; |
| 1208 uint8_t vex_prefix3 = 0x00; | 1213 uint8_t vex_prefix3 = 0x00; |
| 1209 | 1214 |
| 1215 /* |
| 1216 * The "write init" statement causes Ragel to emit initialization code. |
| 1217 * This should be executed once before the ragel machine is started. |
| 1218 */ |
| 1210 %% write init; | 1219 %% write init; |
| 1220 /* |
| 1221 * The "write exec" statement causes Ragel to emit the ragel machine's |
| 1222 * execution code. |
| 1223 */ |
| 1211 %% write exec; | 1224 %% write exec; |
| 1212 | 1225 |
| 1213 /* | 1226 /* |
| 1214 * Ragel DFA accepted the bundle, but we still need to make sure the last | 1227 * Ragel DFA accepted the bundle, but we still need to make sure the last |
| 1215 * instruction haven't left %rbp or %rsp in restricted state. | 1228 * instruction haven't left %rbp or %rsp in restricted state. |
| 1216 */ | 1229 */ |
| 1217 if (restricted_register == REG_RBP) | 1230 if (restricted_register == REG_RBP) |
| 1218 result &= user_callback(end_of_bundle, end_of_bundle, | 1231 result &= user_callback(end_of_bundle, end_of_bundle, |
| 1219 RESTRICTED_RBP_UNPROCESSED | | 1232 RESTRICTED_RBP_UNPROCESSED | |
| 1220 ((REG_RBP << RESTRICTED_REGISTER_SHIFT) & | 1233 ((REG_RBP << RESTRICTED_REGISTER_SHIFT) & |
| (...skipping 11 matching lines...) Expand all Loading... |
| 1232 */ | 1245 */ |
| 1233 result &= ProcessInvalidJumpTargets(data, size, valid_targets, jump_dests, | 1246 result &= ProcessInvalidJumpTargets(data, size, valid_targets, jump_dests, |
| 1234 user_callback, callback_data); | 1247 user_callback, callback_data); |
| 1235 | 1248 |
| 1236 /* We only use malloc for a large code sequences */ | 1249 /* We only use malloc for a large code sequences */ |
| 1237 if (jump_dests != &jump_dests_small) free(jump_dests); | 1250 if (jump_dests != &jump_dests_small) free(jump_dests); |
| 1238 if (valid_targets != &valid_targets_small) free(valid_targets); | 1251 if (valid_targets != &valid_targets_small) free(valid_targets); |
| 1239 if (!result) errno = EINVAL; | 1252 if (!result) errno = EINVAL; |
| 1240 return result; | 1253 return result; |
| 1241 } | 1254 } |
| OLD | NEW |