OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright 2010 The Native Client Authors. All rights reserved. | 2 * Copyright 2010 The Native Client Authors. All rights reserved. |
3 * Use of this source code is governed by a BSD-style license that can | 3 * Use of this source code is governed by a BSD-style license that can |
4 * be found in the LICENSE file. | 4 * be found in the LICENSE file. |
5 */ | 5 */ |
6 | 6 |
7 #include <assert.h> | 7 #include <assert.h> |
8 #include <errno.h> | 8 #include <errno.h> |
9 #include <stdint.h> | 9 #include <stdint.h> |
10 #include <stdio.h> | 10 #include <stdio.h> |
11 #include <stdlib.h> | 11 #include <stdlib.h> |
12 #include <string.h> | 12 #include <string.h> |
13 #include <sys/mman.h> | 13 #include <sys/mman.h> |
14 | 14 |
15 #include <sys/nacl_syscalls.h> | 15 #include <sys/nacl_syscalls.h> |
16 | 16 |
17 #include "native_client/tests/dynamic_code_loading/templates.h" | 17 #include "native_client/tests/dynamic_code_loading/templates.h" |
18 #include "native_client/tests/inbrowser_test_runner/test_runner.h" | 18 #include "native_client/tests/inbrowser_test_runner/test_runner.h" |
19 | 19 |
20 #if defined(__x86_64__) | |
21 #define BUF_SIZE 64 | |
bsy
2010/11/11 21:27:21
why should code buffers be 64 bytes on x86-64 cpus
petr
2010/11/12 18:11:06
on X86-64 we operate with code samples that do not
| |
22 #else | |
23 #define BUF_SIZE 32 | |
24 #endif | |
25 | |
20 #define NACL_BUNDLE_SIZE 32 | 26 #define NACL_BUNDLE_SIZE 32 |
21 /* | 27 /* |
22 * TODO(bsy): get this value from the toolchain. Get the toolchain | 28 * TODO(bsy): get this value from the toolchain. Get the toolchain |
23 * team to provide this value. | 29 * team to provide this value. |
24 */ | 30 */ |
25 #define NUM_BUNDLES_FOR_HLT 3 | 31 #define NUM_BUNDLES_FOR_HLT 3 |
26 | 32 |
27 /* | 33 /* |
28 * This is an address that is well into the dynamic code region and page | 34 * This is an address that is well into the dynamic code region and page |
29 * aligned. There is a test below specifically for installing a function | 35 * aligned. There is a test below specifically for installing a function |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
86 /* Getting the assembler to pad our code fragments in templates.S is | 92 /* Getting the assembler to pad our code fragments in templates.S is |
87 awkward because we have to output them in data mode, in which the | 93 awkward because we have to output them in data mode, in which the |
88 assembler wants to output zeroes instead of NOPs for padding. | 94 assembler wants to output zeroes instead of NOPs for padding. |
89 Also, the assembler won't put in a terminating HLT, which we need | 95 Also, the assembler won't put in a terminating HLT, which we need |
90 on x86-32. So we do the padding at run time. */ | 96 on x86-32. So we do the padding at run time. */ |
91 void copy_and_pad_fragment(void *dest, | 97 void copy_and_pad_fragment(void *dest, |
92 int dest_size, | 98 int dest_size, |
93 const char *fragment_start, | 99 const char *fragment_start, |
94 const char *fragment_end) { | 100 const char *fragment_end) { |
95 int fragment_size = fragment_end - fragment_start; | 101 int fragment_size = fragment_end - fragment_start; |
96 assert(dest_size % 32 == 0); | 102 assert(dest_size % 32 == 0); |
bsy
2010/11/11 21:27:21
is this 32 (always) correct? should it be 16 or 3
petr
2010/11/12 18:11:06
Done.
| |
97 assert(fragment_size < dest_size); | 103 assert(fragment_size <= dest_size); |
98 fill_nops(dest, dest_size); | 104 fill_nops(dest, dest_size); |
99 memcpy(dest, fragment_start, fragment_size); | 105 memcpy(dest, fragment_start, fragment_size); |
100 } | 106 } |
101 | 107 |
102 /* Check that we can load and run code. */ | 108 /* Check that we can load and run code. */ |
103 void test_loading_code() { | 109 void test_loading_code() { |
104 void *load_area = allocate_code_space(1); | 110 void *load_area = allocate_code_space(1); |
105 uint8_t buf[32]; | 111 uint8_t buf[BUF_SIZE]; |
106 int rc; | 112 int rc; |
107 int (*func)(); | 113 int (*func)(); |
108 | 114 |
109 copy_and_pad_fragment(buf, sizeof(buf), &template_func, &template_func_end); | 115 copy_and_pad_fragment(buf, sizeof(buf), &template_func, &template_func_end); |
110 | 116 |
111 rc = nacl_load_code(load_area, buf, sizeof(buf)); | 117 rc = nacl_load_code(load_area, buf, sizeof(buf)); |
112 assert(rc == 0); | 118 assert(rc == 0); |
113 assert(memcmp(load_area, buf, sizeof(buf)) == 0); | 119 assert(memcmp(load_area, buf, sizeof(buf)) == 0); |
114 /* Need double cast otherwise gcc complains with "ISO C forbids | 120 /* Need double cast otherwise gcc complains with "ISO C forbids |
115 conversion of object pointer to function pointer type | 121 conversion of object pointer to function pointer type |
116 [-pedantic]". */ | 122 [-pedantic]". */ |
117 func = (int (*)()) (uintptr_t) load_area; | 123 func = (int (*)()) (uintptr_t) load_area; |
118 rc = func(); | 124 rc = func(); |
119 assert(rc == 1234); | 125 assert(rc == 1234); |
120 } | 126 } |
121 | 127 |
122 /* The syscall may have to mmap() shared memory temporarily, | 128 /* The syscall may have to mmap() shared memory temporarily, |
123 so there is some interaction with page size. | 129 so there is some interaction with page size. |
124 Check that we can load to non-page-aligned addresses. */ | 130 Check that we can load to non-page-aligned addresses. */ |
125 void test_loading_code_non_page_aligned() { | 131 void test_loading_code_non_page_aligned() { |
126 char *load_area = allocate_code_space(1); | 132 char *load_area = allocate_code_space(1); |
127 uint8_t buf[32]; | 133 uint8_t buf[BUF_SIZE]; |
128 int rc; | 134 int rc; |
129 | 135 |
130 copy_and_pad_fragment(buf, sizeof(buf), &template_func, &template_func_end); | 136 copy_and_pad_fragment(buf, sizeof(buf), &template_func, &template_func_end); |
131 | 137 |
132 rc = nacl_load_code(load_area, buf, sizeof(buf)); | 138 rc = nacl_load_code(load_area, buf, sizeof(buf)); |
133 assert(rc == 0); | 139 assert(rc == 0); |
134 assert(memcmp(load_area, buf, sizeof(buf)) == 0); | 140 assert(memcmp(load_area, buf, sizeof(buf)) == 0); |
135 | 141 |
136 load_area += 32; | 142 load_area += sizeof(buf); |
137 rc = nacl_load_code(load_area, buf, sizeof(buf)); | 143 rc = nacl_load_code(load_area, buf, sizeof(buf)); |
138 assert(rc == 0); | 144 assert(rc == 0); |
139 assert(memcmp(load_area, buf, sizeof(buf)) == 0); | 145 assert(memcmp(load_area, buf, sizeof(buf)) == 0); |
140 } | 146 } |
141 | 147 |
142 /* Since there is an interaction with page size, we also test loading | 148 /* Since there is an interaction with page size, we also test loading |
143 a multi-page chunk of code. */ | 149 a multi-page chunk of code. */ |
144 void test_loading_large_chunk() { | 150 void test_loading_large_chunk() { |
145 char *load_area = allocate_code_space(2); | 151 char *load_area = allocate_code_space(2); |
146 int size = 0x20000; | 152 int size = 0x20000; |
147 uint8_t *data = alloca(size); | 153 uint8_t *data = alloca(size); |
148 int rc; | 154 int rc; |
149 | 155 |
150 fill_nops(data, size); | 156 fill_nops(data, size); |
151 rc = nacl_load_code(load_area, data, size); | 157 rc = nacl_load_code(load_area, data, size); |
152 assert(rc == 0); | 158 assert(rc == 0); |
153 assert(memcmp(load_area, data, size) == 0); | 159 assert(memcmp(load_area, data, size) == 0); |
154 } | 160 } |
155 | 161 |
156 void test_loading_zero_size() { | 162 void test_loading_zero_size() { |
157 char *load_area = allocate_code_space(1); | 163 char *load_area = allocate_code_space(1); |
158 int rc = nacl_load_code(load_area, &template_func, 0); | 164 int rc = nacl_load_code(load_area, &template_func, 0); |
159 assert(rc == 0); | 165 assert(rc == 0); |
160 } | 166 } |
161 | 167 |
162 /* Check that we can load code at the very beginning of the dynamic section. */ | 168 /* Check that we can load code at the very beginning of the dynamic section. */ |
163 void test_loading_code_on_first_dynamic_page() { | 169 void test_loading_code_on_first_dynamic_page() { |
164 const unsigned int kPageMask = 0xFFFF; | 170 const unsigned int kPageMask = 0xFFFF; |
165 void *load_area = (void*)((uintptr_t)(etext + kPageMask) & ~kPageMask); | 171 void *load_area = (void*)((uintptr_t)(etext + kPageMask) & ~kPageMask); |
166 uint8_t buf[32]; | 172 uint8_t buf[32]; |
bsy
2010/11/11 21:27:21
should this be BUF_SIZE? if not, a comment would
petr
2010/11/12 18:11:06
Done.
| |
167 int rc; | 173 int rc; |
168 int (*func)(); | 174 int (*func)(); |
169 | 175 |
170 copy_and_pad_fragment(buf, sizeof(buf), &template_func, &template_func_end); | 176 copy_and_pad_fragment(buf, sizeof(buf), &template_func, &template_func_end); |
171 | 177 |
172 rc = nacl_load_code(load_area, buf, sizeof(buf)); | 178 rc = nacl_load_code(load_area, buf, sizeof(buf)); |
173 assert(rc == 0); | 179 assert(rc == 0); |
174 assert(memcmp(load_area, buf, sizeof(buf)) == 0); | 180 assert(memcmp(load_area, buf, sizeof(buf)) == 0); |
175 /* Need double cast otherwise gcc complains with "ISO C forbids | 181 /* Need double cast otherwise gcc complains with "ISO C forbids |
176 conversion of object pointer to function pointer type | 182 conversion of object pointer to function pointer type |
177 [-pedantic]". */ | 183 [-pedantic]". */ |
178 func = (int (*)()) (uintptr_t) load_area; | 184 func = (int (*)()) (uintptr_t) load_area; |
179 rc = func(); | 185 rc = func(); |
180 assert(rc == 1234); | 186 assert(rc == 1234); |
181 } | 187 } |
182 | 188 |
183 /* In general, the failure tests don't check that loading fails for | 189 /* In general, the failure tests don't check that loading fails for |
184 the reason we expect. TODO(mseaborn): We could do this by | 190 the reason we expect. TODO(mseaborn): We could do this by |
185 comparing with expected log output. */ | 191 comparing with expected log output. */ |
186 | 192 |
187 void test_fail_on_validation_error() { | 193 void test_fail_on_validation_error() { |
188 void *load_area = allocate_code_space(1); | 194 void *load_area = allocate_code_space(1); |
189 uint8_t buf[32]; | 195 uint8_t buf[BUF_SIZE]; |
190 int rc; | 196 int rc; |
191 | 197 |
192 copy_and_pad_fragment(buf, sizeof(buf), &invalid_code, &invalid_code_end); | 198 copy_and_pad_fragment(buf, sizeof(buf), &invalid_code, &invalid_code_end); |
193 | 199 |
194 rc = nacl_load_code(load_area, buf, sizeof(buf)); | 200 rc = nacl_load_code(load_area, buf, sizeof(buf)); |
195 assert(rc == -EINVAL); | 201 assert(rc == -EINVAL); |
196 } | 202 } |
197 | 203 |
198 void test_fail_on_non_bundle_aligned_dest_addresses() { | 204 void test_fail_on_non_bundle_aligned_dest_addresses() { |
199 char *load_area = allocate_code_space(1); | 205 char *load_area = allocate_code_space(1); |
200 int rc; | 206 int rc; |
201 uint8_t nops[32]; | 207 uint8_t nops[32]; |
bsy
2010/11/11 21:27:21
should this be BUF_SIZE too? if not, a comment wo
petr
2010/11/12 18:11:06
Done.
| |
202 | 208 |
203 fill_nops(nops, sizeof(nops)); | 209 fill_nops(nops, sizeof(nops)); |
204 | 210 |
205 /* Test unaligned destination. */ | 211 /* Test unaligned destination. */ |
206 rc = nacl_load_code(load_area + 1, nops, 32); | 212 rc = nacl_load_code(load_area + 1, nops, 32); |
bsy
2010/11/11 21:27:21
NACL_ARRAY_SIZE(nops) or sizeof nops instead of 32
petr
2010/11/12 18:11:06
we are testing that the size of a segment is bundl
| |
207 assert(rc == -EINVAL); | 213 assert(rc == -EINVAL); |
208 rc = nacl_load_code(load_area + 4, nops, 32); | 214 rc = nacl_load_code(load_area + 4, nops, 32); |
bsy
2010/11/11 21:27:21
ditto
petr
2010/11/12 18:11:06
ditto
On 2010/11/11 21:27:21, bsy wrote:
| |
209 assert(rc == -EINVAL); | 215 assert(rc == -EINVAL); |
210 | 216 |
211 /* Test unaligned size. */ | 217 /* Test unaligned size. */ |
212 rc = nacl_load_code(load_area, nops + 1, 31); | 218 rc = nacl_load_code(load_area, nops + 1, 31); |
bsy
2010/11/11 21:27:21
NACL_ARRAY_SIZE(nops) - 1 instead of 31?
petr
2010/11/12 18:11:06
ditto
On 2010/11/11 21:27:21, bsy wrote:
| |
213 assert(rc == -EINVAL); | 219 assert(rc == -EINVAL); |
214 rc = nacl_load_code(load_area, nops + 4, 28); | 220 rc = nacl_load_code(load_area, nops + 4, 28); |
bsy
2010/11/11 21:27:21
similar to above
petr
2010/11/12 18:11:06
ditto
On 2010/11/11 21:27:21, bsy wrote:
| |
215 assert(rc == -EINVAL); | 221 assert(rc == -EINVAL); |
216 | 222 |
217 /* Check that the code we're trying works otherwise. */ | 223 /* Check that the code we're trying works otherwise. */ |
218 rc = nacl_load_code(load_area, nops, 32); | 224 rc = nacl_load_code(load_area, nops, 32); |
bsy
2010/11/11 21:27:21
!!
petr
2010/11/12 18:11:06
probably, it is just an additional check (maybe re
| |
219 assert(rc == 0); | 225 assert(rc == 0); |
220 } | 226 } |
221 | 227 |
222 /* In principle we could load into the initially-loaded executable's | 228 /* In principle we could load into the initially-loaded executable's |
223 code area, but at the moment we don't allow it. */ | 229 code area, but at the moment we don't allow it. */ |
224 void test_fail_on_load_to_static_code_area() { | 230 void test_fail_on_load_to_static_code_area() { |
225 int size = &hlts_end - &hlts; | 231 int size = &hlts_end - &hlts; |
226 int rc = nacl_load_code(&hlts, &hlts, size); | 232 int rc = nacl_load_code(&hlts, &hlts, size); |
227 assert(rc == -EFAULT); | 233 assert(rc == -EFAULT); |
228 } | 234 } |
229 | 235 |
230 uint8_t block_in_data_segment[64]; | 236 uint8_t block_in_data_segment[64]; |
231 | 237 |
232 void test_fail_on_load_to_data_area() { | 238 void test_fail_on_load_to_data_area() { |
233 uint8_t *data; | 239 uint8_t *data; |
234 int rc; | 240 int rc; |
235 | 241 |
236 fill_hlts(block_in_data_segment, sizeof(block_in_data_segment)); | 242 fill_hlts(block_in_data_segment, sizeof(block_in_data_segment)); |
237 | 243 |
238 /* Align to 32 byte boundary so that we don't fail for a reason | 244 /* Align to 32 byte boundary so that we don't fail for a reason |
239 we're not testing for. */ | 245 we're not testing for. */ |
240 data = block_in_data_segment; | 246 data = block_in_data_segment; |
241 while (((int) data) % 32 != 0) | 247 while (((int) data) % 32 != 0) |
242 data++; | 248 data++; |
243 rc = nacl_load_code(data, data, 32); | 249 rc = nacl_load_code(data, data, 32); |
bsy
2010/11/11 21:27:21
!!
petr
2010/11/12 18:11:06
s/32/NACL_BUNDLE_SIZE/
On 2010/11/11 21:27:21, bsy
| |
244 assert(rc == -EFAULT); | 250 assert(rc == -EFAULT); |
245 } | 251 } |
246 | 252 |
247 void test_fail_on_overwrite() { | 253 void test_fail_on_overwrite() { |
248 void *load_area = allocate_code_space(1); | 254 void *load_area = allocate_code_space(1); |
249 uint8_t buf[32]; | 255 uint8_t buf[BUF_SIZE]; |
250 int rc; | 256 int rc; |
251 | 257 |
252 copy_and_pad_fragment(buf, sizeof(buf), &template_func, &template_func_end); | 258 copy_and_pad_fragment(buf, sizeof(buf), &template_func, &template_func_end); |
253 | 259 |
254 rc = nacl_load_code(load_area, buf, sizeof(buf)); | 260 rc = nacl_load_code(load_area, buf, sizeof(buf)); |
255 assert(rc == 0); | 261 assert(rc == 0); |
256 | 262 |
257 copy_and_pad_fragment(buf, sizeof(buf), &template_func, | 263 copy_and_pad_fragment(buf, sizeof(buf), &template_func, |
258 &template_func_end); | 264 &template_func_end); |
259 | 265 |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
291 | 297 |
292 rc = nacl_load_code(load_area, &branch_forwards, size); | 298 rc = nacl_load_code(load_area, &branch_forwards, size); |
293 assert(rc == 0); | 299 assert(rc == 0); |
294 rc = nacl_load_code(load_area + size, &branch_backwards, size); | 300 rc = nacl_load_code(load_area + size, &branch_backwards, size); |
295 assert(rc == 0); | 301 assert(rc == 0); |
296 } | 302 } |
297 | 303 |
298 void test_end_of_code_region() { | 304 void test_end_of_code_region() { |
299 int rc; | 305 int rc; |
300 void *dest; | 306 void *dest; |
301 uint8_t data[32]; | 307 uint8_t data[32]; |
bsy
2010/11/11 21:27:21
!!
petr
2010/11/12 18:11:06
Done.
| |
302 fill_nops(data, sizeof(data)); | 308 fill_nops(data, sizeof(data)); |
303 | 309 |
304 /* This tries to load into the data segment, which is definitely not | 310 /* This tries to load into the data segment, which is definitely not |
305 allowed. */ | 311 allowed. */ |
306 dest = (uint8_t *) DYNAMIC_CODE_SEGMENT_END; | 312 dest = (uint8_t *) DYNAMIC_CODE_SEGMENT_END; |
307 rc = nacl_load_code(dest, data, sizeof(data)); | 313 rc = nacl_load_code(dest, data, sizeof(data)); |
308 assert(rc == -EFAULT); | 314 assert(rc == -EFAULT); |
309 | 315 |
310 /* This tries to load into the last bundle of the code region, which | 316 /* This tries to load into the last bundle of the code region, which |
311 sel_ldr disallows just in case there is some CPU bug in which the | 317 sel_ldr disallows just in case there is some CPU bug in which the |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
367 | 373 |
368 /* Test again to make sure we didn't run out of space. */ | 374 /* Test again to make sure we didn't run out of space. */ |
369 RUN_TEST(test_loading_code); | 375 RUN_TEST(test_loading_code); |
370 | 376 |
371 return 0; | 377 return 0; |
372 } | 378 } |
373 | 379 |
374 int main() { | 380 int main() { |
375 return RunTests(TestMain); | 381 return RunTests(TestMain); |
376 } | 382 } |
OLD | NEW |