Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(243)

Side by Side Diff: tests/dynamic_code_loading/dynamic_load_test.c

Issue 3975001: Dynamic code modification support for x64 NaCl modules... (Closed) Base URL: svn://svn.chromium.org/native_client/trunk/src/native_client/
Patch Set: '' Created 10 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
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
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 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698