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

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 /* On x86-64, template functions do not fit in 32-byte buffers */
22 #define BUF_SIZE 64
23 #elif defined(__i386__) || defined(__arm__)
24 #define BUF_SIZE 32
25 #else
26 #error "Unknown Platform"
27 #endif
28
29 #if defined(__i386__) || defined(__x86_64__)
20 #define NACL_BUNDLE_SIZE 32 30 #define NACL_BUNDLE_SIZE 32
31 #elif defined(__arm__)
32 #define NACL_BUNDLE_SIZE 16
33 #else
34 #error "Unknown Platform"
35 #endif
36
21 /* 37 /*
22 * TODO(bsy): get this value from the toolchain. Get the toolchain 38 * TODO(bsy): get this value from the toolchain. Get the toolchain
23 * team to provide this value. 39 * team to provide this value.
24 */ 40 */
25 #define NUM_BUNDLES_FOR_HLT 3 41 #define NUM_BUNDLES_FOR_HLT 3
26 42
27 /* 43 /*
28 * This is an address that is well into the dynamic code region and page 44 * 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 45 * aligned. There is a test below specifically for installing a function
30 * at the very beginning of the dynamic code region. 46 * at the very beginning of the dynamic code region.
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
86 /* Getting the assembler to pad our code fragments in templates.S is 102 /* 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 103 awkward because we have to output them in data mode, in which the
88 assembler wants to output zeroes instead of NOPs for padding. 104 assembler wants to output zeroes instead of NOPs for padding.
89 Also, the assembler won't put in a terminating HLT, which we need 105 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. */ 106 on x86-32. So we do the padding at run time. */
91 void copy_and_pad_fragment(void *dest, 107 void copy_and_pad_fragment(void *dest,
92 int dest_size, 108 int dest_size,
93 const char *fragment_start, 109 const char *fragment_start,
94 const char *fragment_end) { 110 const char *fragment_end) {
95 int fragment_size = fragment_end - fragment_start; 111 int fragment_size = fragment_end - fragment_start;
96 assert(dest_size % 32 == 0); 112 assert(dest_size % NACL_BUNDLE_SIZE == 0);
97 assert(fragment_size < dest_size); 113 assert(fragment_size <= dest_size);
98 fill_nops(dest, dest_size); 114 fill_nops(dest, dest_size);
99 memcpy(dest, fragment_start, fragment_size); 115 memcpy(dest, fragment_start, fragment_size);
100 } 116 }
101 117
102 /* Check that we can load and run code. */ 118 /* Check that we can load and run code. */
103 void test_loading_code() { 119 void test_loading_code() {
104 void *load_area = allocate_code_space(1); 120 void *load_area = allocate_code_space(1);
105 uint8_t buf[32]; 121 uint8_t buf[BUF_SIZE];
106 int rc; 122 int rc;
107 int (*func)(); 123 int (*func)();
108 124
109 copy_and_pad_fragment(buf, sizeof(buf), &template_func, &template_func_end); 125 copy_and_pad_fragment(buf, sizeof(buf), &template_func, &template_func_end);
110 126
111 rc = nacl_load_code(load_area, buf, sizeof(buf)); 127 rc = nacl_load_code(load_area, buf, sizeof(buf));
112 assert(rc == 0); 128 assert(rc == 0);
113 assert(memcmp(load_area, buf, sizeof(buf)) == 0); 129 assert(memcmp(load_area, buf, sizeof(buf)) == 0);
114 /* Need double cast otherwise gcc complains with "ISO C forbids 130 /* Need double cast otherwise gcc complains with "ISO C forbids
115 conversion of object pointer to function pointer type 131 conversion of object pointer to function pointer type
116 [-pedantic]". */ 132 [-pedantic]". */
117 func = (int (*)()) (uintptr_t) load_area; 133 func = (int (*)()) (uintptr_t) load_area;
118 rc = func(); 134 rc = func();
119 assert(rc == 1234); 135 assert(rc == 1234);
120 } 136 }
121 137
122 /* The syscall may have to mmap() shared memory temporarily, 138 /* The syscall may have to mmap() shared memory temporarily,
123 so there is some interaction with page size. 139 so there is some interaction with page size.
124 Check that we can load to non-page-aligned addresses. */ 140 Check that we can load to non-page-aligned addresses. */
125 void test_loading_code_non_page_aligned() { 141 void test_loading_code_non_page_aligned() {
126 char *load_area = allocate_code_space(1); 142 char *load_area = allocate_code_space(1);
127 uint8_t buf[32]; 143 uint8_t buf[BUF_SIZE];
128 int rc; 144 int rc;
129 145
130 copy_and_pad_fragment(buf, sizeof(buf), &template_func, &template_func_end); 146 copy_and_pad_fragment(buf, sizeof(buf), &template_func, &template_func_end);
131 147
132 rc = nacl_load_code(load_area, buf, sizeof(buf)); 148 rc = nacl_load_code(load_area, buf, sizeof(buf));
133 assert(rc == 0); 149 assert(rc == 0);
134 assert(memcmp(load_area, buf, sizeof(buf)) == 0); 150 assert(memcmp(load_area, buf, sizeof(buf)) == 0);
135 151
136 load_area += 32; 152 load_area += sizeof(buf);
137 rc = nacl_load_code(load_area, buf, sizeof(buf)); 153 rc = nacl_load_code(load_area, buf, sizeof(buf));
138 assert(rc == 0); 154 assert(rc == 0);
139 assert(memcmp(load_area, buf, sizeof(buf)) == 0); 155 assert(memcmp(load_area, buf, sizeof(buf)) == 0);
140 } 156 }
141 157
142 /* Since there is an interaction with page size, we also test loading 158 /* Since there is an interaction with page size, we also test loading
143 a multi-page chunk of code. */ 159 a multi-page chunk of code. */
144 void test_loading_large_chunk() { 160 void test_loading_large_chunk() {
145 char *load_area = allocate_code_space(2); 161 char *load_area = allocate_code_space(2);
146 int size = 0x20000; 162 int size = 0x20000;
147 uint8_t *data = alloca(size); 163 uint8_t *data = alloca(size);
148 int rc; 164 int rc;
149 165
150 fill_nops(data, size); 166 fill_nops(data, size);
151 rc = nacl_load_code(load_area, data, size); 167 rc = nacl_load_code(load_area, data, size);
152 assert(rc == 0); 168 assert(rc == 0);
153 assert(memcmp(load_area, data, size) == 0); 169 assert(memcmp(load_area, data, size) == 0);
154 } 170 }
155 171
156 void test_loading_zero_size() { 172 void test_loading_zero_size() {
157 char *load_area = allocate_code_space(1); 173 char *load_area = allocate_code_space(1);
158 int rc = nacl_load_code(load_area, &template_func, 0); 174 int rc = nacl_load_code(load_area, &template_func, 0);
159 assert(rc == 0); 175 assert(rc == 0);
160 } 176 }
161 177
162 /* Check that we can load code at the very beginning of the dynamic section. */ 178 /* Check that we can load code at the very beginning of the dynamic section. */
163 void test_loading_code_on_first_dynamic_page() { 179 void test_loading_code_on_first_dynamic_page() {
164 const unsigned int kPageMask = 0xFFFF; 180 const unsigned int kPageMask = 0xFFFF;
165 void *load_area = (void*)((uintptr_t)(etext + kPageMask) & ~kPageMask); 181 void *load_area = (void*)((uintptr_t)(etext + kPageMask) & ~kPageMask);
166 uint8_t buf[32]; 182 uint8_t buf[BUF_SIZE];
167 int rc; 183 int rc;
168 int (*func)(); 184 int (*func)();
169 185
170 copy_and_pad_fragment(buf, sizeof(buf), &template_func, &template_func_end); 186 copy_and_pad_fragment(buf, sizeof(buf), &template_func, &template_func_end);
171 187
172 rc = nacl_load_code(load_area, buf, sizeof(buf)); 188 rc = nacl_load_code(load_area, buf, sizeof(buf));
173 assert(rc == 0); 189 assert(rc == 0);
174 assert(memcmp(load_area, buf, sizeof(buf)) == 0); 190 assert(memcmp(load_area, buf, sizeof(buf)) == 0);
175 /* Need double cast otherwise gcc complains with "ISO C forbids 191 /* Need double cast otherwise gcc complains with "ISO C forbids
176 conversion of object pointer to function pointer type 192 conversion of object pointer to function pointer type
177 [-pedantic]". */ 193 [-pedantic]". */
178 func = (int (*)()) (uintptr_t) load_area; 194 func = (int (*)()) (uintptr_t) load_area;
179 rc = func(); 195 rc = func();
180 assert(rc == 1234); 196 assert(rc == 1234);
181 } 197 }
182 198
183 /* In general, the failure tests don't check that loading fails for 199 /* In general, the failure tests don't check that loading fails for
184 the reason we expect. TODO(mseaborn): We could do this by 200 the reason we expect. TODO(mseaborn): We could do this by
185 comparing with expected log output. */ 201 comparing with expected log output. */
186 202
187 void test_fail_on_validation_error() { 203 void test_fail_on_validation_error() {
188 void *load_area = allocate_code_space(1); 204 void *load_area = allocate_code_space(1);
189 uint8_t buf[32]; 205 uint8_t buf[BUF_SIZE];
190 int rc; 206 int rc;
191 207
192 copy_and_pad_fragment(buf, sizeof(buf), &invalid_code, &invalid_code_end); 208 copy_and_pad_fragment(buf, sizeof(buf), &invalid_code, &invalid_code_end);
193 209
194 rc = nacl_load_code(load_area, buf, sizeof(buf)); 210 rc = nacl_load_code(load_area, buf, sizeof(buf));
195 assert(rc == -EINVAL); 211 assert(rc == -EINVAL);
196 } 212 }
197 213
198 void test_fail_on_non_bundle_aligned_dest_addresses() { 214 void test_fail_on_non_bundle_aligned_dest_addresses() {
199 char *load_area = allocate_code_space(1); 215 char *load_area = allocate_code_space(1);
200 int rc; 216 int rc;
201 uint8_t nops[32]; 217 uint8_t nops[BUF_SIZE];
202 218
203 fill_nops(nops, sizeof(nops)); 219 fill_nops(nops, sizeof(nops));
204 220
205 /* Test unaligned destination. */ 221 /* Test unaligned destination. */
206 rc = nacl_load_code(load_area + 1, nops, 32); 222 rc = nacl_load_code(load_area + 1, nops, NACL_BUNDLE_SIZE);
207 assert(rc == -EINVAL); 223 assert(rc == -EINVAL);
208 rc = nacl_load_code(load_area + 4, nops, 32); 224 rc = nacl_load_code(load_area + 4, nops, NACL_BUNDLE_SIZE);
209 assert(rc == -EINVAL); 225 assert(rc == -EINVAL);
210 226
211 /* Test unaligned size. */ 227 /* Test unaligned size. */
212 rc = nacl_load_code(load_area, nops + 1, 31); 228 rc = nacl_load_code(load_area, nops + 1, NACL_BUNDLE_SIZE - 1);
213 assert(rc == -EINVAL); 229 assert(rc == -EINVAL);
214 rc = nacl_load_code(load_area, nops + 4, 28); 230 rc = nacl_load_code(load_area, nops + 4, NACL_BUNDLE_SIZE - 4);
215 assert(rc == -EINVAL); 231 assert(rc == -EINVAL);
216 232
217 /* Check that the code we're trying works otherwise. */ 233 /* Check that the code we're trying works otherwise. */
218 rc = nacl_load_code(load_area, nops, 32); 234 rc = nacl_load_code(load_area, nops, NACL_BUNDLE_SIZE);
219 assert(rc == 0); 235 assert(rc == 0);
220 } 236 }
221 237
222 /* In principle we could load into the initially-loaded executable's 238 /* In principle we could load into the initially-loaded executable's
223 code area, but at the moment we don't allow it. */ 239 code area, but at the moment we don't allow it. */
224 void test_fail_on_load_to_static_code_area() { 240 void test_fail_on_load_to_static_code_area() {
225 int size = &hlts_end - &hlts; 241 int size = &hlts_end - &hlts;
226 int rc = nacl_load_code(&hlts, &hlts, size); 242 int rc = nacl_load_code(&hlts, &hlts, size);
227 assert(rc == -EFAULT); 243 assert(rc == -EFAULT);
228 } 244 }
229 245
230 uint8_t block_in_data_segment[64]; 246 uint8_t block_in_data_segment[64];
231 247
232 void test_fail_on_load_to_data_area() { 248 void test_fail_on_load_to_data_area() {
233 uint8_t *data; 249 uint8_t *data;
234 int rc; 250 int rc;
235 251
236 fill_hlts(block_in_data_segment, sizeof(block_in_data_segment)); 252 fill_hlts(block_in_data_segment, sizeof(block_in_data_segment));
237 253
238 /* Align to 32 byte boundary so that we don't fail for a reason 254 /* Align to bundle size so that we don't fail for a reason
239 we're not testing for. */ 255 we're not testing for. */
240 data = block_in_data_segment; 256 data = block_in_data_segment;
241 while (((int) data) % 32 != 0) 257 while (((int) data) % NACL_BUNDLE_SIZE != 0)
242 data++; 258 data++;
243 rc = nacl_load_code(data, data, 32); 259 rc = nacl_load_code(data, data, NACL_BUNDLE_SIZE);
244 assert(rc == -EFAULT); 260 assert(rc == -EFAULT);
245 } 261 }
246 262
247 void test_fail_on_overwrite() { 263 void test_fail_on_overwrite() {
248 void *load_area = allocate_code_space(1); 264 void *load_area = allocate_code_space(1);
249 uint8_t buf[32]; 265 uint8_t buf[BUF_SIZE];
250 int rc; 266 int rc;
251 267
252 copy_and_pad_fragment(buf, sizeof(buf), &template_func, &template_func_end); 268 copy_and_pad_fragment(buf, sizeof(buf), &template_func, &template_func_end);
253 269
254 rc = nacl_load_code(load_area, buf, sizeof(buf)); 270 rc = nacl_load_code(load_area, buf, sizeof(buf));
255 assert(rc == 0); 271 assert(rc == 0);
256 272
257 copy_and_pad_fragment(buf, sizeof(buf), &template_func, 273 copy_and_pad_fragment(buf, sizeof(buf), &template_func,
258 &template_func_end); 274 &template_func_end);
259 275
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
291 307
292 rc = nacl_load_code(load_area, &branch_forwards, size); 308 rc = nacl_load_code(load_area, &branch_forwards, size);
293 assert(rc == 0); 309 assert(rc == 0);
294 rc = nacl_load_code(load_area + size, &branch_backwards, size); 310 rc = nacl_load_code(load_area + size, &branch_backwards, size);
295 assert(rc == 0); 311 assert(rc == 0);
296 } 312 }
297 313
298 void test_end_of_code_region() { 314 void test_end_of_code_region() {
299 int rc; 315 int rc;
300 void *dest; 316 void *dest;
301 uint8_t data[32]; 317 uint8_t data[BUF_SIZE];
302 fill_nops(data, sizeof(data)); 318 fill_nops(data, sizeof(data));
303 319
304 /* This tries to load into the data segment, which is definitely not 320 /* This tries to load into the data segment, which is definitely not
305 allowed. */ 321 allowed. */
306 dest = (uint8_t *) DYNAMIC_CODE_SEGMENT_END; 322 dest = (uint8_t *) DYNAMIC_CODE_SEGMENT_END;
307 rc = nacl_load_code(dest, data, sizeof(data)); 323 rc = nacl_load_code(dest, data, sizeof(data));
308 assert(rc == -EFAULT); 324 assert(rc == -EFAULT);
309 325
310 /* This tries to load into the last bundle of the code region, which 326 /* 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 327 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 383
368 /* Test again to make sure we didn't run out of space. */ 384 /* Test again to make sure we didn't run out of space. */
369 RUN_TEST(test_loading_code); 385 RUN_TEST(test_loading_code);
370 386
371 return 0; 387 return 0;
372 } 388 }
373 389
374 int main() { 390 int main() {
375 return RunTests(TestMain); 391 return RunTests(TestMain);
376 } 392 }
OLDNEW
« no previous file with comments | « src/trusted/validator_x86/ncvalidate_iter.c ('k') | tests/dynamic_code_loading/dynamic_modify_test.c » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698