< prev index next >

src/share/vm/utilities/debug.cpp

Print this page
rev 7417 : improve secondary signal handling

@@ -306,28 +306,95 @@
 }
 
 #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;
+  if (!pc) {
+    void* p = os::reserve_memory(size, NULL, 0);
+    if (p) {
+      bool rc = os::commit_memory((char*)p, size, true);
+      if (rc) {
+        memset(p, 0, size);
+        memcpy(p, illegal_instruction_sequence, 
+          sizeof(illegal_instruction_sequence));
+        pc = p;
+      }
+    }
+  }
+  
+  guarantee(pc, "failed to initialized sigill test blob");
+
+  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() {
-  uintx test_num = ErrorHandlerTest;
-  if (test_num == 0) return;
+  controlled_crash(ErrorHandlerTest);
+}
+
+void controlled_crash(int how) {
+  if (how == 0) return;
 
   // If asserts are disabled, use the corresponding guarantee instead.
-  size_t n = test_num;
-  NOT_DEBUG(if (n <= 2) n += 2);
+  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 (n) {
+  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,12 +415,14 @@
     // 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.", n);
+    default: tty->print_cr("ERROR: %d: unexpected test_num value.", how);
   }
   ShouldNotReachHere();
 }
 #endif // !PRODUCT
 
< prev index next >