| OLD | NEW |
| (Empty) |
| 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 /* ncinstbuffer-inl.h - Holds nline functions for commonly used (simple) | |
| 8 * functions in ncinstbuffer.h. Used to speed up code. Inlineed routines | |
| 9 * correspond to the following functions in ncinstbuffer.h, but with an | |
| 10 * 'Inline' suffix: | |
| 11 * | |
| 12 * NCRemainingMemoryAdvance | |
| 13 * NCRemainingMemoryReset | |
| 14 * NCRemainingMemoryLookahead | |
| 15 * NCRemainingMemoryRead | |
| 16 * NCInstBytesPeek | |
| 17 * NCInstByte | |
| 18 * NCInstBytesRead | |
| 19 * NCInstBytesReadBytes | |
| 20 * NCInstBytesReset | |
| 21 * NCInstBytesInit | |
| 22 * NCInstBytesByte | |
| 23 * | |
| 24 * See ncinstbuffer.h for comments on how to use the corresponding inline | |
| 25 * functions. | |
| 26 */ | |
| 27 | |
| 28 #ifndef NATIVE_CLIENT_SRC_TRUSTED_VALIDATOR_X86_NCINSTBUFFER_INL_C__ | |
| 29 #define NATIVE_CLIENT_SRC_TRUSTED_VALIDATOR_X86_NCINSTBUFFER_INL_C__ | |
| 30 | |
| 31 #include "native_client/src/trusted/validator/x86/ncinstbuffer.h" | |
| 32 | |
| 33 /* Constant NCBUF_CLEAR_CACHE controls the behaviour of the buffer containing | |
| 34 * the sequence of parsed bytes. Turn it on (1) to fill unused bytes with the | |
| 35 * constant zero, and to allow access to all bytes in the sequence of parsed | |
| 36 * bytes. Turn it off (0) to force access to only include the actual parsed | |
| 37 * bytes. | |
| 38 * | |
| 39 * Note: Ideally, we would like to turn this feature off. However, the current | |
| 40 * instruction parser (in ncdecode.c) and corresponding printer (in | |
| 41 * ncdis_util.c) are problematic. The parser allows a partial match of | |
| 42 * an instruction, without verifying that ALL necessary bytes are there. The | |
| 43 * corresponding printer, assumes that only complete matches (during parsing) | |
| 44 * were performed. The result is that the code sometimes assumes that many | |
| 45 * more bytes were parsed than were actually parsed. | |
| 46 * | |
| 47 * To quickly fix the code so that it doesn't do illegal memory accesses, but | |
| 48 * has consistent behaviour, the flag is currently sets NCBUF_CLEAR_CACHE to 1. | |
| 49 * | |
| 50 * To debug this problem, set the flag NCBUF_CLEAR_CACHE to 0. | |
| 51 * | |
| 52 * TODO(karl) Fix the parser/printer so that NCBUF_CLEAR_CACHE can be set to 0. | |
| 53 */ | |
| 54 #define NCBUF_CLEAR_CACHE 1 | |
| 55 | |
| 56 /* Defines the number of bytes in the buffer. */ | |
| 57 #if NCBUF_CLEAR_CACHE | |
| 58 #define NCBUF_BYTES_LENGTH(bytes) MAX_INST_LENGTH | |
| 59 #else | |
| 60 #define NCBUF_BYTES_LENGTH(bytes) (bytes)->length | |
| 61 #endif | |
| 62 | |
| 63 /* The constant to return if memory overflow occurs. */ | |
| 64 # define NC_MEMORY_OVERFLOW 0 | |
| 65 | |
| 66 /* Returns the next byte in memory, or 0x00 if there are no more | |
| 67 * bytes in memory. | |
| 68 */ | |
| 69 static INLINE uint8_t NCRemainingMemoryPeekInline(NCRemainingMemory* memory) { | |
| 70 return (memory->cur_pos >= memory->mlimit) | |
| 71 ? NC_MEMORY_OVERFLOW : *(memory->cur_pos); | |
| 72 } | |
| 73 | |
| 74 /* Starts a new instruction at the current position in the memory | |
| 75 * segment. | |
| 76 */ | |
| 77 static INLINE void NCRemainingMemoryAdvanceInline(NCRemainingMemory* memory) { | |
| 78 memory->mpc = memory->cur_pos; | |
| 79 memory->read_length = 0; | |
| 80 memory->overflow_count = 0; | |
| 81 } | |
| 82 | |
| 83 /* Moves back to the beginning of the current instruction in | |
| 84 * the memory segment. | |
| 85 */ | |
| 86 static INLINE void NCRemainingMemoryResetInline(NCRemainingMemory* memory) { | |
| 87 memory->cur_pos = memory->mpc; | |
| 88 memory->next_byte = NCRemainingMemoryPeekInline(memory); | |
| 89 memory->read_length = 0; | |
| 90 memory->overflow_count = 0; | |
| 91 } | |
| 92 | |
| 93 /* Looks ahead N bytes into the memory, and returns the corresponding | |
| 94 * byte, or 0x00 if at the end of memory. i is zero-based. | |
| 95 */ | |
| 96 static INLINE uint8_t NCRemainingMemoryLookaheadInline( | |
| 97 NCRemainingMemory* memory, ssize_t n) { | |
| 98 if ((memory->cur_pos + n) < memory->mlimit) { | |
| 99 return memory->cur_pos[n]; | |
| 100 } else { | |
| 101 return NC_MEMORY_OVERFLOW; | |
| 102 } | |
| 103 } | |
| 104 | |
| 105 /* Reads and returns the next byte in the memory segment. Returns 0x00 if at | |
| 106 * the end of the memory segment. | |
| 107 */ | |
| 108 static INLINE uint8_t NCRemainingMemoryReadInline(NCRemainingMemory* memory) { | |
| 109 uint8_t byte = memory->next_byte; | |
| 110 if (memory->cur_pos == memory->mlimit) { | |
| 111 /* If reached, next_byte already set to 0 by last read. */ | |
| 112 if (0 == memory->overflow_count) { | |
| 113 memory->error_fn(NCRemainingMemoryOverflow, memory); | |
| 114 } | |
| 115 memory->overflow_count++; | |
| 116 } else { | |
| 117 memory->read_length++; | |
| 118 memory->cur_pos++; | |
| 119 memory->next_byte = NCRemainingMemoryPeekInline(memory); | |
| 120 } | |
| 121 return byte; | |
| 122 } | |
| 123 | |
| 124 /* Peek ahead and return the nth (zero based) byte from the current position | |
| 125 * in the sequence of bytes being parsed. | |
| 126 */ | |
| 127 static INLINE uint8_t NCInstBytesPeekInline(NCInstBytes* bytes, ssize_t n) { | |
| 128 return NCRemainingMemoryLookaheadInline(bytes->memory, n); | |
| 129 } | |
| 130 | |
| 131 /* Peek at the nth character in the sequence of bytes being parsed (independent | |
| 132 * of the current position). | |
| 133 */ | |
| 134 static INLINE uint8_t NCInstByteInline(NCInstBytes* bytes, ssize_t n) { | |
| 135 if (n < bytes->length) { | |
| 136 return bytes->byte[n]; | |
| 137 } else { | |
| 138 return NCRemainingMemoryLookaheadInline(bytes->memory, n - bytes->length); | |
| 139 } | |
| 140 } | |
| 141 | |
| 142 /* Reads a byte from the memory segment and adds it to the instruction buffer. | |
| 143 * Returns the read byte. | |
| 144 * Note: Assumes that NCInstBytesInitMemory has already been called to associate | |
| 145 * memory. | |
| 146 */ | |
| 147 static INLINE uint8_t NCInstBytesReadInline(NCInstBytes* bytes) { | |
| 148 uint8_t byte = NCRemainingMemoryReadInline(bytes->memory); | |
| 149 if (bytes->length < MAX_INST_LENGTH) { | |
| 150 bytes->byte[bytes->length++] = byte; | |
| 151 } else { | |
| 152 bytes->memory->error_fn(NCInstBufferOverflow, bytes->memory); | |
| 153 } | |
| 154 return byte; | |
| 155 } | |
| 156 | |
| 157 /* Reads n bytes from the memory segment and adds it to the instruction buffer. | |
| 158 * Note: Assumes that NCInstBytesInitMemory has already been called to associate | |
| 159 * memory. | |
| 160 */ | |
| 161 static INLINE void NCInstBytesReadBytesInline(ssize_t n, NCInstBytes* bytes) { | |
| 162 ssize_t i; | |
| 163 for (i = 0; i < n; ++i) { | |
| 164 NCInstBytesReadInline(bytes); | |
| 165 } | |
| 166 } | |
| 167 | |
| 168 /* Resets bytes back to the beginning of the current instruction. */ | |
| 169 static INLINE void NCInstBytesResetInline(NCInstBytes* buffer) { | |
| 170 #if NCBUF_CLEAR_CACHE | |
| 171 int i; | |
| 172 for (i = 0; i < MAX_INST_LENGTH; ++i) { | |
| 173 buffer->byte[i] = 0; | |
| 174 } | |
| 175 #endif | |
| 176 NCRemainingMemoryResetInline(buffer->memory); | |
| 177 buffer->length = 0; | |
| 178 } | |
| 179 | |
| 180 /* Initializes the instruction buffer as the empty buffer, and | |
| 181 * advances the memory segment so that one is beginning the | |
| 182 * parsing of the current instruction at the current position | |
| 183 * in the memory segment. | |
| 184 * Note: Assumes that NCInstBytesInitMemory has already been called to associate | |
| 185 * memory. | |
| 186 */ | |
| 187 static INLINE void NCInstBytesInitInline(NCInstBytes* buffer) { | |
| 188 #if NCBUF_CLEAR_CACHE | |
| 189 int i; | |
| 190 for (i = 0; i < MAX_INST_LENGTH; ++i) { | |
| 191 buffer->byte[i] = 0; | |
| 192 } | |
| 193 #endif | |
| 194 NCRemainingMemoryAdvanceInline(buffer->memory); | |
| 195 buffer->length = 0; | |
| 196 } | |
| 197 | |
| 198 /* Returns the indexed byte pointed to by the instruction buffer pointer. */ | |
| 199 static INLINE uint8_t NCInstBytesByteInline(const NCInstBytesPtr* ptr, int n) { | |
| 200 int index = ptr->pos + n; | |
| 201 if (index < NCBUF_BYTES_LENGTH(ptr->bytes)) { | |
| 202 return ptr->bytes->byte[index]; | |
| 203 } else { | |
| 204 ptr->bytes->memory->error_fn(NCInstBufferOverflow, ptr->bytes->memory); | |
| 205 return 0; | |
| 206 } | |
| 207 } | |
| 208 | |
| 209 #endif /* NATIVE_CLIENT_SRC_TRUSTED_VALIDATOR_X86_NCINSTBUFFER_INL_C__ */ | |
| OLD | NEW |