1/* 2 * Copyright (c) 2011 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 amd64 case. Can be used to decode instruction 9 * sequence 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_64_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/include/elf32.h" 23#include "native_client/src/shared/utils/types.h" 24#include "native_client/src/trusted/validator_ragel/decoder_internal.h" 25 26#define GET_REX_PREFIX() instruction.prefix.rex 27#define SET_REX_PREFIX(PREFIX_BYTE) instruction.prefix.rex = (PREFIX_BYTE) 28#define GET_VEX_PREFIX2() vex_prefix2 29#define SET_VEX_PREFIX2(PREFIX_BYTE) vex_prefix2 = (PREFIX_BYTE) 30#define CLEAR_SPURIOUS_REX_B() \ 31 instruction.prefix.rex_b_spurious = FALSE 32#define SET_SPURIOUS_REX_B() \ 33 if (GET_REX_PREFIX() & REX_B) instruction.prefix.rex_b_spurious = TRUE 34#define CLEAR_SPURIOUS_REX_X() \ 35 instruction.prefix.rex_x_spurious = FALSE 36#define SET_SPURIOUS_REX_X() \ 37 if (GET_REX_PREFIX() & REX_X) instruction.prefix.rex_x_spurious = TRUE 38#define CLEAR_SPURIOUS_REX_R() \ 39 instruction.prefix.rex_r_spurious = FALSE 40#define SET_SPURIOUS_REX_R() \ 41 if (GET_REX_PREFIX() & REX_R) instruction.prefix.rex_r_spurious = TRUE 42#define CLEAR_SPURIOUS_REX_W() \ 43 instruction.prefix.rex_w_spurious = FALSE 44#define SET_SPURIOUS_REX_W() \ 45 if (GET_REX_PREFIX() & REX_W) instruction.prefix.rex_w_spurious = TRUE 46 47%%{ 48 machine x86_64_decoder; 49 alphtype unsigned char; 50 variable p current_position; 51 variable pe end_position; 52 variable eof end_position; 53 variable cs current_state; 54 55 include byte_machine "byte_machines.rl"; 56 57 include prefixes_parsing_decoder 58 "native_client/src/trusted/validator_ragel/parse_instruction.rl"; 59 include rex_actions 60 "native_client/src/trusted/validator_ragel/parse_instruction.rl"; 61 include rex_parsing 62 "native_client/src/trusted/validator_ragel/parse_instruction.rl"; 63 include vex_actions_amd64 64 "native_client/src/trusted/validator_ragel/parse_instruction.rl"; 65 include vex_parsing_amd64 66 "native_client/src/trusted/validator_ragel/parse_instruction.rl"; 67 include att_suffix_actions 68 "native_client/src/trusted/validator_ragel/parse_instruction.rl"; 69 include set_spurious_prefixes 70 "native_client/src/trusted/validator_ragel/parse_instruction.rl"; 71 include displacement_fields_parsing 72 "native_client/src/trusted/validator_ragel/parse_instruction.rl"; 73 include modrm_actions_amd64 74 "native_client/src/trusted/validator_ragel/parse_instruction.rl"; 75 include modrm_parsing 76 "native_client/src/trusted/validator_ragel/parse_instruction.rl"; 77 include operand_format_actions 78 "native_client/src/trusted/validator_ragel/parse_instruction.rl"; 79 include operand_source_actions_amd64_decoder 80 "native_client/src/trusted/validator_ragel/parse_instruction.rl"; 81 include immediate_fields_parsing 82 "native_client/src/trusted/validator_ragel/parse_instruction.rl"; 83 include relative_fields_decoder_actions 84 "native_client/src/trusted/validator_ragel/parse_instruction.rl"; 85 include relative_fields_parsing 86 "native_client/src/trusted/validator_ragel/parse_instruction.rl"; 87 include cpuid_actions 88 "native_client/src/trusted/validator_ragel/parse_instruction.rl"; 89 90 include decode_x86_64 "decoder_x86_64_instruction.rl"; 91 92 action end_of_instruction_cleanup { 93 process_instruction(instruction_begin, current_position + 1, &instruction, 94 userdata); 95 instruction_begin = current_position + 1; 96 SET_DISPLACEMENT_FORMAT(DISPNONE); 97 SET_IMMEDIATE_FORMAT(IMMNONE); 98 SET_SECOND_IMMEDIATE_FORMAT(IMMNONE); 99 SET_REX_PREFIX(FALSE); 100 SET_DATA16_PREFIX(FALSE); 101 SET_LOCK_PREFIX(FALSE); 102 SET_REPNZ_PREFIX(FALSE); 103 SET_REPZ_PREFIX(FALSE); 104 SET_BRANCH_NOT_TAKEN(FALSE); 105 SET_BRANCH_TAKEN(FALSE); 106 /* 107 * Top three bits of VEX2 are inverted: see AMD/Intel manual. 108 * Pass VEX2 prefix value that corresponds to zero bits. 109 */ 110 SET_VEX_PREFIX2(VEX_R | VEX_X | VEX_B); 111 SET_VEX_PREFIX3(0x00); 112 SET_ATT_INSTRUCTION_SUFFIX(NULL); 113 CLEAR_SPURIOUS_REX_B(); 114 CLEAR_SPURIOUS_REX_X(); 115 CLEAR_SPURIOUS_REX_R(); 116 CLEAR_SPURIOUS_REX_W(); 117 } 118 119 action report_fatal_error { 120 process_error(current_position, userdata); 121 result = FALSE; 122 goto error_detected; 123 } 124 125 decoder := (one_instruction @end_of_instruction_cleanup)* 126 $!report_fatal_error; 127}%% 128 129/* 130 * The "write data" statement causes Ragel to emit the constant static data 131 * needed by the ragel machine. 132 */ 133%% write data; 134 135int DecodeChunkAMD64(const uint8_t *data, size_t size, 136 ProcessInstructionFunc process_instruction, 137 ProcessDecodingErrorFunc process_error, 138 void *userdata) { 139 const uint8_t *current_position = data; 140 const uint8_t *end_position = data + size; 141 const uint8_t *instruction_begin = current_position; 142 /* 143 * Top three bits of VEX2 are inverted: see AMD/Intel manual. 144 * Start with VEX2 prefix value that corresponds to zero bits. 145 */ 146 uint8_t vex_prefix2 = VEX_R | VEX_X | VEX_B; 147 uint8_t vex_prefix3 = 0x00; 148 enum ImmediateMode imm_operand = IMMNONE; 149 enum ImmediateMode imm2_operand = IMMNONE; 150 struct Instruction instruction; 151 int result = TRUE; 152 153 int current_state; 154 155 memset(&instruction, 0, sizeof instruction); 156 157 /* 158 * The "write init" statement causes Ragel to emit initialization code. 159 * This should be executed once before the ragel machine is started. 160 */ 161 %% write init; 162 /* 163 * The "write exec" statement causes Ragel to emit the ragel machine's 164 * execution code. 165 */ 166 %% write exec; 167 168error_detected: 169 return result; 170} 171