< prev index next >

src/share/vm/utilities/debug.cpp

Print this page
rev 7424 : improve secondary signal handling

*** 306,333 **** } #ifndef PRODUCT #include <signal.h> void test_error_handler() { ! uintx test_num = ErrorHandlerTest; ! if (test_num == 0) return; // If asserts are disabled, use the corresponding guarantee instead. ! size_t n = test_num; ! NOT_DEBUG(if (n <= 2) n += 2); const char* const str = "hello"; const size_t num = (size_t)os::vm_page_size(); const char* const eol = os::line_separator(); const char* const msg = "this message should be truncated during formatting"; char * const dataPtr = NULL; // bad data pointer const void (*funcPtr)(void) = (const void(*)()) 0xF; // bad function pointer // Keep this in sync with test/runtime/6888954/vmerrors.sh. ! switch (n) { case 1: assert(str == NULL, "expected null"); case 2: assert(num == 1023 && *str == 'X', err_msg("num=" SIZE_FORMAT " str=\"%s\"", num, str)); case 3: guarantee(str == NULL, "expected null"); case 4: guarantee(num == 1023 && *str == 'X', --- 306,412 ---- } #ifndef PRODUCT #include <signal.h> + typedef void (*voidfun_t)(); + // Crash with an authentic sigill at a known PC. + static void crash_with_sigill() { + bool rc = false; + const size_t size = os::vm_page_size(); + static void* pc = NULL; + + // prepare a "blob" with an illegal instruction sequence which + // we then execute. Have to use os::reserve_memory to be able to + // make the memory executable. + if (!pc) { + void* p = os::reserve_memory(size, NULL, 0); + if (p) { + bool rc = os::commit_memory((char*)p, size, true); + if (rc) { + if (get_illegal_instruction_sequence((uint8_t*)p)) { + pc = p; + } + } + } + } + + // Fallback: if there is no implementation for get_illegal_instruction_sequence + // for the current platform, just do a raise(SIGILL). Raising a signal is + // different from triggering it naturaly (e.g. raised synchronous signals can + // be blocked) but for the test purposes it is better than nothing. + if (pc == NULL) { + tty->print_cr("will raise a SIGILL"); + tty->flush(); + raise(SIGILL); + ShouldNotReachHere(); + } + + tty->print_cr("will jump to PC " PTR_FORMAT + ", which should cause a SIGILL.", pc); + tty->flush(); + + volatile voidfun_t g_voidfun = NULL; + + #if defined(IA64) || defined(PPC64) + // on ia64 and on ppc we have function descriptors. + struct { void* p1; void* p2; } fundes = + { pc, pc }; + void* p = (void*)(&fundes); + g_voidfun = (voidfun_t) (p); + #else + g_voidfun = (voidfun_t)pc; + #endif + + g_voidfun(); // boom. + + } // end: crash_with_sigill + + // crash with sigsegv at non-null address. + static void crash_with_segfault() { + + char* const crash_addr = (char*) get_segfault_address(); + + tty->print_cr("will access address " PTR_FORMAT + ", which should cause a SIGSEGV.", crash_addr); + tty->flush(); + + *crash_addr = 'X'; + + } // end: crash_with_segfault + + // returns an address which is guaranteed to generate a SIGSEGV on read, + // for test purposes, which is not NULL and contains bits in every word + void* get_segfault_address() { + return (void*) + #ifdef _LP64 + 0xABC0000000000ABCULL; + #else + 0x00000ABC; + #endif + } + void test_error_handler() { ! controlled_crash(ErrorHandlerTest); ! } ! ! void controlled_crash(int how) { ! if (how == 0) return; // If asserts are disabled, use the corresponding guarantee instead. ! NOT_DEBUG(if (how <= 2) how += 2); const char* const str = "hello"; const size_t num = (size_t)os::vm_page_size(); const char* const eol = os::line_separator(); const char* const msg = "this message should be truncated during formatting"; char * const dataPtr = NULL; // bad data pointer const void (*funcPtr)(void) = (const void(*)()) 0xF; // bad function pointer // Keep this in sync with test/runtime/6888954/vmerrors.sh. ! switch (how) { case 1: assert(str == NULL, "expected null"); case 2: assert(num == 1023 && *str == 'X', err_msg("num=" SIZE_FORMAT " str=\"%s\"", num, str)); case 3: guarantee(str == NULL, "expected null"); case 4: guarantee(num == 1023 && *str == 'X',
*** 348,359 **** // so "break" out to the ShouldNotReachHere(). case 12: *dataPtr = '\0'; break; // There's no guarantee the bad function pointer will crash us // so "break" out to the ShouldNotReachHere(). case 13: (*funcPtr)(); break; ! default: tty->print_cr("ERROR: %d: unexpected test_num value.", n); } ShouldNotReachHere(); } #endif // !PRODUCT --- 427,440 ---- // so "break" out to the ShouldNotReachHere(). case 12: *dataPtr = '\0'; break; // There's no guarantee the bad function pointer will crash us // so "break" out to the ShouldNotReachHere(). case 13: (*funcPtr)(); break; + case 14: crash_with_segfault(); break; + case 15: crash_with_sigill(); break; ! default: tty->print_cr("ERROR: %d: unexpected test_num value.", how); } ShouldNotReachHere(); } #endif // !PRODUCT
< prev index next >