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 |