< 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 >