Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 /* | 1 /* |
| 2 * Copyright (c) 2012 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 <pthread.h> | 9 #include <pthread.h> |
| 10 #include <setjmp.h> | 10 #include <setjmp.h> |
| 11 #include <stdint.h> | 11 #include <stdint.h> |
| 12 #include <stdio.h> | 12 #include <stdio.h> |
| 13 #include <stdlib.h> | 13 #include <stdlib.h> |
| 14 #include <string.h> | 14 #include <string.h> |
| 15 | 15 |
| 16 #if !TESTS_USE_IRT && NONSFI_MODE | |
| 17 #include "native_client/src/nonsfi/linux/irt_exception_handling.h" | |
| 18 #endif | |
| 19 | |
| 16 #include "native_client/src/include/elf_constants.h" | 20 #include "native_client/src/include/elf_constants.h" |
| 17 #include "native_client/src/include/nacl/nacl_exception.h" | 21 #include "native_client/src/include/nacl/nacl_exception.h" |
| 18 #include "native_client/src/trusted/service_runtime/include/sys/nacl_syscalls.h" | 22 #include "native_client/src/trusted/service_runtime/include/sys/nacl_syscalls.h" |
| 19 #include "native_client/src/untrusted/nacl/syscall_bindings_trampoline.h" | 23 #include "native_client/src/untrusted/nacl/syscall_bindings_trampoline.h" |
| 20 #include "native_client/tests/common/register_set.h" | 24 #include "native_client/tests/common/register_set.h" |
| 21 #include "native_client/tests/inbrowser_test_runner/test_runner.h" | 25 #include "native_client/tests/inbrowser_test_runner/test_runner.h" |
| 22 | 26 |
| 23 | 27 |
| 24 /* | 28 /* |
| 25 * This is used for calculating the size of the exception stack frame | 29 * This is used for calculating the size of the exception stack frame |
| (...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 175 stack_top = g_registered_stack + g_registered_stack_size; | 179 stack_top = g_registered_stack + g_registered_stack_size; |
| 176 assert(g_registered_stack <= &local_var); | 180 assert(g_registered_stack <= &local_var); |
| 177 assert(&local_var < stack_top); | 181 assert(&local_var < stack_top); |
| 178 } | 182 } |
| 179 | 183 |
| 180 /* Check the exception handler's initial stack pointer more exactly. */ | 184 /* Check the exception handler's initial stack pointer more exactly. */ |
| 181 uintptr_t frame_base = entry_regs->stack_ptr + kReturnAddrSize; | 185 uintptr_t frame_base = entry_regs->stack_ptr + kReturnAddrSize; |
| 182 assert(frame_base % STACK_ALIGNMENT == 0); | 186 assert(frame_base % STACK_ALIGNMENT == 0); |
| 183 char *frame_top = (char *) (frame_base + kArgSizeOnStack + | 187 char *frame_top = (char *) (frame_base + kArgSizeOnStack + |
| 184 sizeof(struct CombinedContext)); | 188 sizeof(struct CombinedContext)); |
| 185 /* Check that no more than the stack alignment size is wasted. */ | 189 if (NONSFI_MODE) { |
| 186 assert(stack_top - STACK_ALIGNMENT < frame_top); | 190 /* |
| 191 * Non-SFI mode exception stack will have ucontext_t and | |
| 192 * siginfo_t, which would be anywhere from 400 bytes to 1.5k | |
| 193 */ | |
| 194 assert(stack_top - 1500 < frame_top); | |
| 195 } else { | |
| 196 /* Check that no more than the stack alignment size is wasted. */ | |
| 197 assert(stack_top - STACK_ALIGNMENT < frame_top); | |
| 198 } | |
| 187 assert(frame_top <= stack_top); | 199 assert(frame_top <= stack_top); |
| 188 | 200 |
| 189 #if defined(__x86_64__) | 201 #if defined(__x86_64__) |
| 190 /* Check that %rsp and %rbp have safe, %r15-extended values. */ | 202 /* Check that %rsp and %rbp have safe, %r15-extended values. */ |
| 191 assert(entry_regs->stack_ptr >> 32 == entry_regs->r15 >> 32); | 203 assert(entry_regs->stack_ptr >> 32 == entry_regs->r15 >> 32); |
| 192 assert(entry_regs->rbp >> 32 == entry_regs->r15 >> 32); | 204 assert(entry_regs->rbp >> 32 == entry_regs->r15 >> 32); |
| 193 #endif | 205 #endif |
| 194 | 206 |
| 195 return_from_exception_handler(); | 207 return_from_exception_handler(); |
| 196 } | 208 } |
| 197 | 209 |
| 198 void test_exception_stack_with_size(char *stack, size_t stack_size) { | 210 void test_exception_stack_with_size(char *stack, size_t stack_size) { |
| 199 if (0 != nacl_exception_set_handler(exception_handler)) { | 211 if (0 != nacl_exception_set_handler(exception_handler)) { |
| 200 printf("failed to set exception handler\n"); | 212 printf("failed to set exception handler\n"); |
| 201 exit(4); | 213 exit(4); |
| 202 } | 214 } |
| 215 #if !NONSFI_MODE | |
| 216 /* TODO(uekawa): Implement set_stack for Non-SFI mode. */ | |
| 203 if (0 != nacl_exception_set_stack(stack, stack_size)) { | 217 if (0 != nacl_exception_set_stack(stack, stack_size)) { |
| 204 printf("failed to set alt stack\n"); | 218 printf("failed to set alt stack\n"); |
| 205 exit(5); | 219 exit(5); |
| 206 } | 220 } |
| 207 g_registered_stack = stack; | 221 g_registered_stack = stack; |
| 208 g_registered_stack_size = stack_size; | 222 g_registered_stack_size = stack_size; |
| 223 #endif | |
| 209 | 224 |
| 210 char crash_stack[0x1000]; | 225 char crash_stack[0x1000]; |
| 211 RegsFillTestValues(&g_regs_at_crash, /* seed= */ 0); | 226 RegsFillTestValues(&g_regs_at_crash, /* seed= */ 0); |
| 212 g_regs_at_crash.stack_ptr = (uintptr_t) crash_stack + sizeof(crash_stack); | 227 g_regs_at_crash.stack_ptr = (uintptr_t) crash_stack + sizeof(crash_stack); |
| 213 g_regs_at_crash.prog_ctr = (uintptr_t) prog_ctr_at_crash; | 228 g_regs_at_crash.prog_ctr = (uintptr_t) prog_ctr_at_crash; |
| 214 RegsApplySandboxConstraints(&g_regs_at_crash); | 229 RegsApplySandboxConstraints(&g_regs_at_crash); |
| 215 #if defined(__arm__) | 230 #if defined(__arm__) |
| 216 /* crash_at_known_address clobbers r0. */ | 231 /* crash_at_known_address clobbers r0. */ |
| 217 g_regs_at_crash.r0 = 0; | 232 g_regs_at_crash.r0 = 0; |
| 218 #endif | 233 #endif |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 307 void test_catching_various_exception_types(void) { | 322 void test_catching_various_exception_types(void) { |
| 308 int rc = nacl_exception_set_handler(simple_exception_handler); | 323 int rc = nacl_exception_set_handler(simple_exception_handler); |
| 309 assert(rc == 0); | 324 assert(rc == 0); |
| 310 | 325 |
| 311 printf("Testing __builtin_trap()...\n"); | 326 printf("Testing __builtin_trap()...\n"); |
| 312 if (!setjmp(g_jmp_buf)) { | 327 if (!setjmp(g_jmp_buf)) { |
| 313 __builtin_trap(); | 328 __builtin_trap(); |
| 314 exit(1); | 329 exit(1); |
| 315 } | 330 } |
| 316 | 331 |
| 317 #if defined(__i386__) || defined(__x86_64__) | 332 #if !NONSFI_MODE && (defined(__i386__) || defined(__x86_64__)) |
| 318 printf("Testing hlt...\n"); | 333 printf("Testing hlt...\n"); |
| 319 if (!setjmp(g_jmp_buf)) { | 334 if (!setjmp(g_jmp_buf)) { |
| 320 __asm__("hlt"); | 335 __asm__("hlt"); |
| 321 exit(1); | 336 exit(1); |
| 322 } | 337 } |
| 323 printf("Testing ud2a (an illegal instruction)...\n"); | 338 printf("Testing ud2a (an illegal instruction)...\n"); |
| 324 if (!setjmp(g_jmp_buf)) { | 339 if (!setjmp(g_jmp_buf)) { |
| 325 __asm__("ud2a"); | 340 __asm__("ud2a"); |
| 326 exit(1); | 341 exit(1); |
| 327 } | 342 } |
| 328 printf("Testing integer division by zero...\n"); | 343 printf("Testing integer division by zero...\n"); |
| 329 if (!setjmp(g_jmp_buf)) { | 344 if (!setjmp(g_jmp_buf)) { |
| 330 uint32_t result; | 345 uint32_t result; |
| 331 __asm__ volatile("idivb %1" | 346 __asm__ volatile("idivb %1" |
| 332 : "=a"(result) | 347 : "=a"(result) |
| 333 : "r"((uint8_t) 0), "a"((uint16_t) 1)); | 348 : "r"((uint8_t) 0), "a"((uint16_t) 1)); |
| 334 exit(1); | 349 exit(1); |
| 335 } | 350 } |
| 336 #endif | 351 #endif |
| 337 | 352 |
| 338 /* Clear the jmp_buf to prevent it from being reused accidentally. */ | 353 /* Clear the jmp_buf to prevent it from being reused accidentally. */ |
| 339 memset(g_jmp_buf, 0, sizeof(g_jmp_buf)); | 354 memset(g_jmp_buf, 0, sizeof(g_jmp_buf)); |
| 340 } | 355 } |
| 341 | 356 |
| 342 | 357 |
| 343 #if defined(__i386__) || defined(__x86_64__) | 358 #if !NONSFI_MODE && (defined(__i386__) || defined(__x86_64__)) |
| 344 | 359 |
| 345 int get_x86_direction_flag(void); | 360 int get_x86_direction_flag(void); |
| 346 | 361 |
| 347 void test_get_x86_direction_flag(void) { | 362 void test_get_x86_direction_flag(void) { |
| 348 /* | 363 /* |
| 349 * Sanity check: Ensure that get_x86_direction_flag() works. We | 364 * Sanity check: Ensure that get_x86_direction_flag() works. We |
| 350 * avoid calling assert() with the flag set, because that might not | 365 * avoid calling assert() with the flag set, because that might not |
| 351 * work. | 366 * work. |
| 352 */ | 367 */ |
| 353 assert(get_x86_direction_flag() == 0); | 368 assert(get_x86_direction_flag() == 0); |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 389 | 404 |
| 390 void run_test(const char *test_name, void (*test_func)(void)) { | 405 void run_test(const char *test_name, void (*test_func)(void)) { |
| 391 printf("Running %s...\n", test_name); | 406 printf("Running %s...\n", test_name); |
| 392 test_func(); | 407 test_func(); |
| 393 } | 408 } |
| 394 | 409 |
| 395 #define RUN_TEST(test_func) (run_test(#test_func, test_func)) | 410 #define RUN_TEST(test_func) (run_test(#test_func, test_func)) |
| 396 | 411 |
| 397 int TestMain(void) { | 412 int TestMain(void) { |
| 398 RUN_TEST(test_exceptions_minimally); | 413 RUN_TEST(test_exceptions_minimally); |
| 399 RUN_TEST(test_exception_stack_alignments); | 414 if (!NONSFI_MODE) { |
| 400 RUN_TEST(test_getting_previous_handler); | 415 /* TODO(uekawa): Implement set_stack for Non-SFI mode. */ |
| 401 RUN_TEST(test_invalid_handlers); | 416 RUN_TEST(test_exception_stack_alignments); |
| 417 /* NACL_SYSCALL not supported on nonsfi mode */ | |
| 418 RUN_TEST(test_getting_previous_handler); | |
| 419 /* Those handlers are not invalid in NonSFI NaCl. */ | |
| 420 RUN_TEST(test_invalid_handlers); | |
| 421 } | |
| 402 /* pthread_join() is broken under qemu-arm. */ | 422 /* pthread_join() is broken under qemu-arm. */ |
| 403 if (getenv("UNDER_QEMU_ARM") == NULL) | 423 if (getenv("UNDER_QEMU_ARM") == NULL) |
| 404 RUN_TEST(test_exceptions_on_non_main_thread); | 424 RUN_TEST(test_exceptions_on_non_main_thread); |
| 405 RUN_TEST(test_catching_various_exception_types); | 425 RUN_TEST(test_catching_various_exception_types); |
| 406 | 426 |
| 407 #if defined(__i386__) || defined(__x86_64__) | 427 #if !NONSFI_MODE && (defined(__i386__) || defined(__x86_64__)) |
| 428 /* TODO(uekawa): Implement for Non-SFI mode. */ | |
| 408 RUN_TEST(test_get_x86_direction_flag); | 429 RUN_TEST(test_get_x86_direction_flag); |
| 409 RUN_TEST(test_unsetting_x86_direction_flag); | 430 RUN_TEST(test_unsetting_x86_direction_flag); |
| 410 #endif | 431 #endif |
| 411 | 432 |
| 412 fprintf(stderr, "** intended_exit_status=0\n"); | 433 fprintf(stderr, "** intended_exit_status=0\n"); |
| 413 return 0; | 434 return 0; |
| 414 } | 435 } |
| 415 | 436 |
| 416 int main(void) { | 437 int main(void) { |
| 438 #if !TESTS_USE_IRT && NONSFI_MODE | |
| 439 /* | |
| 440 * In Non-SFI mode Non-IRT loading version does not initialize | |
| 441 * signal handler. | |
| 442 */ | |
| 443 nonsfi_initialize_signal_handler(); | |
|
Junichi Uekawa
2014/09/29 07:32:30
I couldn't find a reasonable place to do initializ
| |
| 444 #endif | |
| 417 return RunTests(TestMain); | 445 return RunTests(TestMain); |
| 418 } | 446 } |
| OLD | NEW |