OLD | NEW |
1 /* | 1 /* |
2 * Copyright (c) 2011 The Native Client Authors. All rights reserved. | 2 * Copyright (c) 2012 The Native Client Authors. All rights reserved. |
3 * Use of this source code is governed by a BSD-style license that can be | 3 * Use of this source code is governed by a BSD-style license that can be |
4 * found in the LICENSE file. | 4 * 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 <stdio.h> | 9 #include <stdio.h> |
10 #include <stdint.h> | 10 #include <stdint.h> |
11 #include <stdlib.h> | 11 #include <stdlib.h> |
12 #include <string.h> | 12 #include <string.h> |
(...skipping 291 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
304 first_diff++; | 304 first_diff++; |
305 } | 305 } |
306 rc = nacl_dyncode_modify(load_area+first_diff, buf+first_diff, | 306 rc = nacl_dyncode_modify(load_area+first_diff, buf+first_diff, |
307 sizeof(buf)-first_diff); | 307 sizeof(buf)-first_diff); |
308 assert(rc != 0); | 308 assert(rc != 0); |
309 func = (int (*)()) (uintptr_t) load_area; | 309 func = (int (*)()) (uintptr_t) load_area; |
310 rc = func(); | 310 rc = func(); |
311 assert(rc == 1234); | 311 assert(rc == 1234); |
312 } | 312 } |
313 | 313 |
| 314 #if defined(__i386__) || defined(__x86_64__) |
| 315 void test_jump_into_super_inst_create() { |
| 316 uint8_t *load_area = allocate_code_space(1); |
| 317 uint8_t buf[BUF_SIZE]; |
| 318 int rc; |
| 319 |
| 320 /* A direct jump into a bundle is invalid. */ |
| 321 copy_and_pad_fragment(buf, sizeof(buf), &jump_into_super_inst_modified, |
| 322 &jump_into_super_inst_modified_end); |
| 323 rc = nacl_dyncode_create(load_area, buf, sizeof(buf)); |
| 324 assert(rc != 0); |
| 325 assert(errno == EINVAL); |
| 326 } |
| 327 |
| 328 void test_start_with_super_inst_replace() { |
| 329 uint8_t *load_area = allocate_code_space(1); |
| 330 uint8_t buf[BUF_SIZE]; |
| 331 int rc; |
| 332 |
| 333 /* The original version is fine. */ |
| 334 copy_and_pad_fragment(buf, sizeof(buf), &jump_into_super_inst_original, |
| 335 &jump_into_super_inst_original_end); |
| 336 rc = nacl_dyncode_create(load_area, buf, sizeof(buf)); |
| 337 assert(rc == 0); |
| 338 |
| 339 /* Replace the code with itself. This makes sure that replacement code can |
| 340 * start with a super instruction. |
| 341 */ |
| 342 copy_and_pad_fragment(buf, sizeof(buf), &jump_into_super_inst_original, |
| 343 &jump_into_super_inst_original_end); |
| 344 rc = nacl_dyncode_modify(load_area, buf, sizeof(buf)); |
| 345 assert(rc == 0); |
| 346 } |
| 347 |
| 348 void test_jump_into_super_inst_replace() { |
| 349 uint8_t *load_area = allocate_code_space(1); |
| 350 uint8_t buf[BUF_SIZE]; |
| 351 int rc; |
| 352 |
| 353 /* The original version is fine. */ |
| 354 copy_and_pad_fragment(buf, sizeof(buf), &jump_into_super_inst_original, |
| 355 &jump_into_super_inst_original_end); |
| 356 rc = nacl_dyncode_create(load_area, buf, sizeof(buf)); |
| 357 assert(rc == 0); |
| 358 |
| 359 /* The modified version cannot be used as a replacement. |
| 360 * See: http://code.google.com/p/nativeclient/issues/detail?id=2563 |
| 361 */ |
| 362 copy_and_pad_fragment(buf, sizeof(buf), &jump_into_super_inst_modified, |
| 363 &jump_into_super_inst_modified_end); |
| 364 rc = nacl_dyncode_modify(load_area, buf, sizeof(buf)); |
| 365 assert(rc != 0); |
| 366 assert(errno == EINVAL); |
| 367 } |
| 368 #endif |
314 | 369 |
315 void run_test(const char *test_name, void (*test_func)(void)) { | 370 void run_test(const char *test_name, void (*test_func)(void)) { |
316 printf("Running %s...\n", test_name); | 371 printf("Running %s...\n", test_name); |
317 test_func(); | 372 test_func(); |
318 } | 373 } |
319 | 374 |
320 int is_replacement_enabled() { | 375 int is_replacement_enabled() { |
321 char trash; | 376 char trash; |
322 return (0 == nacl_dyncode_modify(allocate_code_space(1), &trash, 0)); | 377 return (0 == nacl_dyncode_modify(allocate_code_space(1), &trash, 0)); |
323 } | 378 } |
324 | 379 |
325 #define RUN_TEST(test_func) (run_test(#test_func, test_func)) | 380 #define RUN_TEST(test_func) (run_test(#test_func, test_func)) |
326 | 381 |
327 int TestMain() { | 382 int TestMain() { |
328 /* Turn off stdout buffering to aid debugging in case of a crash. */ | 383 /* Turn off stdout buffering to aid debugging in case of a crash. */ |
329 setvbuf(stdout, NULL, _IONBF, 0); | 384 setvbuf(stdout, NULL, _IONBF, 0); |
330 | 385 |
331 assert(is_replacement_enabled()); | 386 assert(is_replacement_enabled()); |
332 | 387 |
333 RUN_TEST(test_replacing_code); | 388 RUN_TEST(test_replacing_code); |
334 RUN_TEST(test_replacing_code_unaligned); | 389 RUN_TEST(test_replacing_code_unaligned); |
335 #if defined(__i386__) || defined(__x86_64__) | 390 #if defined(__i386__) || defined(__x86_64__) |
336 RUN_TEST(test_replacing_code_slowpaths); | 391 RUN_TEST(test_replacing_code_slowpaths); |
| 392 RUN_TEST(test_jump_into_super_inst_create); |
| 393 RUN_TEST(test_start_with_super_inst_replace); |
| 394 RUN_TEST(test_jump_into_super_inst_replace); |
337 #endif | 395 #endif |
338 RUN_TEST(test_illegal_code_replacment); | 396 RUN_TEST(test_illegal_code_replacment); |
339 RUN_TEST(test_external_jump_target_replacement); | 397 RUN_TEST(test_external_jump_target_replacement); |
340 | 398 |
341 return 0; | 399 return 0; |
342 } | 400 } |
343 | 401 |
344 int main() { | 402 int main() { |
345 return RunTests(TestMain); | 403 return RunTests(TestMain); |
346 } | 404 } |
OLD | NEW |