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/* 8 * Full-blown decoder for ia32 case. Can be used to decode instruction sequence 9 * and process it, but right now is only used in tests. 10 * 11 * The code is in [hand-written] "parse_instruction.rl" and in [auto-generated] 12 * "decoder_x86_32_instruction.rl" file. This file only includes tiny amount 13 * of the glue code. 14 */ 15 16#include <assert.h> 17#include <stddef.h> 18#include <stdio.h> 19#include <stdlib.h> 20#include <string.h> 21 22#include "native_client/src/shared/utils/types.h" 23#include "native_client/src/trusted/validator_ragel/decoder_internal.h" 24 25%%{ 26 machine x86_32_decoder; 27 alphtype unsigned char; 28 variable p current_position; 29 variable pe end_position; 30 variable eof end_position; 31 variable cs current_state; 32 33 include byte_machine "byte_machines.rl"; 34 35 include prefixes_parsing_decoder 36 "native_client/src/trusted/validator_ragel/parse_instruction.rl"; 37 include vex_actions_ia32 38 "native_client/src/trusted/validator_ragel/parse_instruction.rl"; 39 include vex_parsing_ia32 40 "native_client/src/trusted/validator_ragel/parse_instruction.rl"; 41 include att_suffix_actions 42 "native_client/src/trusted/validator_ragel/parse_instruction.rl"; 43 include set_spurious_prefixes 44 "native_client/src/trusted/validator_ragel/parse_instruction.rl"; 45 include displacement_fields_parsing 46 "native_client/src/trusted/validator_ragel/parse_instruction.rl"; 47 include modrm_actions_ia32 48 "native_client/src/trusted/validator_ragel/parse_instruction.rl"; 49 include modrm_parsing 50 "native_client/src/trusted/validator_ragel/parse_instruction.rl"; 51 include operand_format_actions 52 "native_client/src/trusted/validator_ragel/parse_instruction.rl"; 53 include operand_source_actions_ia32_decoder 54 "native_client/src/trusted/validator_ragel/parse_instruction.rl"; 55 include immediate_fields_parsing 56 "native_client/src/trusted/validator_ragel/parse_instruction.rl"; 57 include relative_fields_decoder_actions 58 "native_client/src/trusted/validator_ragel/parse_instruction.rl"; 59 include relative_fields_parsing 60 "native_client/src/trusted/validator_ragel/parse_instruction.rl"; 61 include cpuid_actions 62 "native_client/src/trusted/validator_ragel/parse_instruction.rl"; 63 64 include decode_x86_32 "decoder_x86_32_instruction.rl"; 65 66 action end_of_instruction_cleanup { 67 process_instruction(instruction_begin, current_position + 1, &instruction, 68 userdata); 69 instruction_begin = current_position + 1; 70 SET_DISPLACEMENT_FORMAT(DISPNONE); 71 SET_IMMEDIATE_FORMAT(IMMNONE); 72 SET_SECOND_IMMEDIATE_FORMAT(IMMNONE); 73 SET_DATA16_PREFIX(FALSE); 74 SET_LOCK_PREFIX(FALSE); 75 SET_REPNZ_PREFIX(FALSE); 76 SET_REPZ_PREFIX(FALSE); 77 SET_BRANCH_NOT_TAKEN(FALSE); 78 SET_BRANCH_TAKEN(FALSE); 79 SET_VEX_PREFIX3(0x00); 80 SET_ATT_INSTRUCTION_SUFFIX(NULL); 81 } 82 83 action report_fatal_error { 84 process_error(current_position, userdata); 85 result = FALSE; 86 goto error_detected; 87 } 88 89 decoder := (one_instruction @end_of_instruction_cleanup)* 90 $!report_fatal_error; 91}%% 92 93/* 94 * The "write data" statement causes Ragel to emit the constant static data 95 * needed by the ragel machine. 96 */ 97%% write data; 98 99int DecodeChunkIA32(const uint8_t *data, size_t size, 100 ProcessInstructionFunc process_instruction, 101 ProcessDecodingErrorFunc process_error, void *userdata) { 102 const uint8_t *current_position = data; 103 const uint8_t *end_position = data + size; 104 const uint8_t *instruction_begin = current_position; 105 uint8_t vex_prefix3 = 0x00; 106 enum ImmediateMode imm_operand = IMMNONE; 107 enum ImmediateMode imm2_operand = IMMNONE; 108 struct Instruction instruction; 109 int result = TRUE; 110 111 int current_state; 112 113 memset(&instruction, 0, sizeof instruction); 114 115 /* 116 * The "write init" statement causes Ragel to emit initialization code. 117 * This should be executed once before the ragel machine is started. 118 */ 119 %% write init; 120 /* 121 * The "write exec" statement causes Ragel to emit the ragel machine's 122 * execution code. 123 */ 124 %% write exec; 125 126error_detected: 127 return result; 128} 129