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 2711772 : static INLINE uint8_t NCRemainingMemoryPeekInline(NCRemainingMemory* memory) {
70 8135316 : 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 527987 : static INLINE void NCRemainingMemoryAdvanceInline(NCRemainingMemory* memory) {
78 527987 : memory->mpc = memory->cur_pos;
79 527987 : memory->read_length = 0;
80 527987 : memory->overflow_count = 0;
81 527987 : }
82 :
83 : /* Moves back to the beginning of the current instruction in
84 : * the memory segment.
85 : */
86 1599404 : static INLINE void NCRemainingMemoryResetInline(NCRemainingMemory* memory) {
87 1599404 : memory->cur_pos = memory->mpc;
88 1599404 : memory->next_byte = NCRemainingMemoryPeekInline(memory);
89 1599404 : memory->read_length = 0;
90 1599404 : memory->overflow_count = 0;
91 1599404 : }
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 21312 : NCRemainingMemory* memory, ssize_t n) {
98 21312 : if ((memory->cur_pos + n) < memory->mlimit) {
99 20574 : return memory->cur_pos[n];
100 : } else {
101 738 : return NC_MEMORY_OVERFLOW;
102 : }
103 21312 : }
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 1110922 : static INLINE uint8_t NCRemainingMemoryReadInline(NCRemainingMemory* memory) {
109 1110922 : uint8_t byte = memory->next_byte;
110 1110922 : if (memory->cur_pos == memory->mlimit) {
111 : /* If reached, next_byte already set to 0 by last read. */
112 878 : if (0 == memory->overflow_count) {
113 122 : memory->error_fn(NCRemainingMemoryOverflow, memory);
114 122 : }
115 878 : memory->overflow_count++;
116 878 : } else {
117 1110044 : memory->read_length++;
118 1110044 : memory->cur_pos++;
119 1110044 : memory->next_byte = NCRemainingMemoryPeekInline(memory);
120 : }
121 1110922 : 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 6982 : static INLINE uint8_t NCInstBytesPeekInline(NCInstBytes* bytes, ssize_t n) {
128 6982 : 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 4639 : static INLINE uint8_t NCInstByteInline(NCInstBytes* bytes, ssize_t n) {
135 4639 : if (n < bytes->length) {
136 3939 : return bytes->byte[n];
137 : } else {
138 700 : return NCRemainingMemoryLookaheadInline(bytes->memory, n - bytes->length);
139 : }
140 4639 : }
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 1109279 : static INLINE uint8_t NCInstBytesReadInline(NCInstBytes* bytes) {
148 1109279 : uint8_t byte = NCRemainingMemoryReadInline(bytes->memory);
149 1109279 : if (bytes->length < MAX_INST_LENGTH) {
150 1109276 : bytes->byte[bytes->length++] = byte;
151 1109276 : } else {
152 3 : bytes->memory->error_fn(NCInstBufferOverflow, bytes->memory);
153 : }
154 1109279 : 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 6914 : static INLINE void NCInstBytesReadBytesInline(ssize_t n, NCInstBytes* bytes) {
162 6914 : ssize_t i;
163 37402 : for (i = 0; i < n; ++i) {
164 11787 : NCInstBytesReadInline(bytes);
165 11787 : }
166 6914 : }
167 :
168 : /* Resets bytes back to the beginning of the current instruction. */
169 522490 : static INLINE void NCInstBytesResetInline(NCInstBytes* buffer) {
170 : #if NCBUF_CLEAR_CACHE
171 522490 : int i;
172 16719680 : for (i = 0; i < MAX_INST_LENGTH; ++i) {
173 7837350 : buffer->byte[i] = 0;
174 7837350 : }
175 : #endif
176 522490 : NCRemainingMemoryResetInline(buffer->memory);
177 522490 : buffer->length = 0;
178 522490 : }
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 525645 : static INLINE void NCInstBytesInitInline(NCInstBytes* buffer) {
188 : #if NCBUF_CLEAR_CACHE
189 525645 : int i;
190 16820640 : for (i = 0; i < MAX_INST_LENGTH; ++i) {
191 7884675 : buffer->byte[i] = 0;
192 7884675 : }
193 : #endif
194 525645 : NCRemainingMemoryAdvanceInline(buffer->memory);
195 525645 : buffer->length = 0;
196 525645 : }
197 :
198 : /* Returns the indexed byte pointed to by the instruction buffer pointer. */
199 0 : static INLINE uint8_t NCInstBytesByteInline(const NCInstBytesPtr* ptr, int n) {
200 0 : int index = ptr->pos + n;
201 0 : if (index < NCBUF_BYTES_LENGTH(ptr->bytes)) {
202 0 : return ptr->bytes->byte[index];
203 : } else {
204 0 : ptr->bytes->memory->error_fn(NCInstBufferOverflow, ptr->bytes->memory);
205 0 : return 0;
206 : }
207 0 : }
208 :
209 : #endif /* NATIVE_CLIENT_SRC_TRUSTED_VALIDATOR_X86_NCINSTBUFFER_INL_C__ */
|