8191101: Show register content in hs-err file on assert
authorstuefe
Fri, 30 Mar 2018 06:31:16 +0200
changeset 49653 a569cb4425f3
parent 49652 a74836b05c28
child 49654 16f53c9c7493
8191101: Show register content in hs-err file on assert Reviewed-by: adinn, clanger, simonis
src/hotspot/os/posix/vmError_posix.cpp
src/hotspot/os_cpu/linux_aarch64/os_linux_aarch64.cpp
src/hotspot/os_cpu/linux_arm/os_linux_arm.cpp
src/hotspot/os_cpu/linux_ppc/os_linux_ppc.cpp
src/hotspot/os_cpu/linux_s390/os_linux_s390.cpp
src/hotspot/os_cpu/linux_sparc/os_linux_sparc.cpp
src/hotspot/os_cpu/linux_x86/os_linux_x86.cpp
src/hotspot/share/runtime/arguments.cpp
src/hotspot/share/runtime/globals.hpp
src/hotspot/share/runtime/thread.cpp
src/hotspot/share/utilities/debug.cpp
src/hotspot/share/utilities/debug.hpp
src/hotspot/share/utilities/vmError.cpp
src/hotspot/share/utilities/vmError.hpp
test/hotspot/jtreg/runtime/ErrorHandling/ShowRegistersOnAssertTest.java
--- a/src/hotspot/os/posix/vmError_posix.cpp	Thu Mar 29 21:48:38 2018 -0700
+++ b/src/hotspot/os/posix/vmError_posix.cpp	Fri Mar 30 06:31:16 2018 +0200
@@ -27,6 +27,7 @@
 #include "runtime/arguments.hpp"
 #include "runtime/os.hpp"
 #include "runtime/thread.hpp"
+#include "utilities/debug.hpp"
 #include "utilities/vmError.hpp"
 
 #include <sys/types.h>
@@ -122,11 +123,20 @@
     pc = (address) info->si_addr;
   }
 
+  // Needed to make it possible to call SafeFetch.. APIs in error handling.
   if (uc && pc && StubRoutines::is_safefetch_fault(pc)) {
     os::Posix::ucontext_set_pc(uc, StubRoutines::continuation_for_safefetch_fault(pc));
     return;
   }
 
+  // Needed because asserts may happen in error handling too.
+#ifdef CAN_SHOW_REGISTERS_ON_ASSERT
+  if ((sig == SIGSEGV || sig == SIGBUS) && info != NULL && info->si_addr == g_assert_poison) {
+    handle_assert_poison_fault(ucVoid, info->si_addr);
+    return;
+  }
+#endif // CAN_SHOW_REGISTERS_ON_ASSERT
+
   VMError::report_and_die(NULL, sig, pc, info, ucVoid);
 }
 
--- a/src/hotspot/os_cpu/linux_aarch64/os_linux_aarch64.cpp	Thu Mar 29 21:48:38 2018 -0700
+++ b/src/hotspot/os_cpu/linux_aarch64/os_linux_aarch64.cpp	Fri Mar 30 06:31:16 2018 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2018, Oracle and/or its affiliates. All rights reserved.
  * Copyright (c) 2014, Red Hat Inc. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
@@ -50,6 +50,7 @@
 #include "runtime/stubRoutines.hpp"
 #include "runtime/thread.inline.hpp"
 #include "runtime/timer.hpp"
+#include "utilities/debug.hpp"
 #include "utilities/events.hpp"
 #include "utilities/vmError.hpp"
 #ifdef BUILTIN_SIM
@@ -306,6 +307,13 @@
     }
   }
 
+#ifdef CAN_SHOW_REGISTERS_ON_ASSERT
+  if ((sig == SIGSEGV || sig == SIGBUS) && info != NULL && info->si_addr == g_assert_poison) {
+    handle_assert_poison_fault(ucVoid, info->si_addr);
+    return 1;
+  }
+#endif
+
   JavaThread* thread = NULL;
   VMThread* vmthread = NULL;
   if (os::Linux::signal_handlers_are_installed) {
--- a/src/hotspot/os_cpu/linux_arm/os_linux_arm.cpp	Thu Mar 29 21:48:38 2018 -0700
+++ b/src/hotspot/os_cpu/linux_arm/os_linux_arm.cpp	Fri Mar 30 06:31:16 2018 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -47,6 +47,7 @@
 #include "runtime/sharedRuntime.hpp"
 #include "runtime/stubRoutines.hpp"
 #include "runtime/timer.hpp"
+#include "utilities/debug.hpp"
 #include "utilities/events.hpp"
 #include "utilities/vmError.hpp"
 
@@ -311,6 +312,13 @@
     }
   }
 
+#ifdef CAN_SHOW_REGISTERS_ON_ASSERT
+  if ((sig == SIGSEGV || sig == SIGBUS) && info != NULL && info->si_addr == g_assert_poison) {
+    handle_assert_poison_fault(ucVoid, info->si_addr);
+    return 1;
+  }
+#endif
+
   JavaThread* thread = NULL;
   VMThread* vmthread = NULL;
   if (os::Linux::signal_handlers_are_installed) {
--- a/src/hotspot/os_cpu/linux_ppc/os_linux_ppc.cpp	Thu Mar 29 21:48:38 2018 -0700
+++ b/src/hotspot/os_cpu/linux_ppc/os_linux_ppc.cpp	Fri Mar 30 06:31:16 2018 +0200
@@ -51,6 +51,7 @@
 #include "runtime/stubRoutines.hpp"
 #include "runtime/thread.inline.hpp"
 #include "runtime/timer.hpp"
+#include "utilities/debug.hpp"
 #include "utilities/events.hpp"
 #include "utilities/vmError.hpp"
 
@@ -266,6 +267,13 @@
     }
   }
 
+#ifdef CAN_SHOW_REGISTERS_ON_ASSERT
+  if ((sig == SIGSEGV || sig == SIGBUS) && info != NULL && info->si_addr == g_assert_poison) {
+    handle_assert_poison_fault(ucVoid, info->si_addr);
+    return 1;
+  }
+#endif
+
   JavaThread* thread = NULL;
   VMThread* vmthread = NULL;
   if (os::Linux::signal_handlers_are_installed) {
--- a/src/hotspot/os_cpu/linux_s390/os_linux_s390.cpp	Thu Mar 29 21:48:38 2018 -0700
+++ b/src/hotspot/os_cpu/linux_s390/os_linux_s390.cpp	Fri Mar 30 06:31:16 2018 +0200
@@ -54,6 +54,7 @@
 #include "runtime/thread.inline.hpp"
 #include "runtime/timer.hpp"
 #include "utilities/events.hpp"
+#include "utilities/debug.hpp"
 #include "utilities/vmError.hpp"
 
 // put OS-includes here
@@ -270,6 +271,13 @@
     }
   }
 
+#ifdef CAN_SHOW_REGISTERS_ON_ASSERT
+  if ((sig == SIGSEGV || sig == SIGBUS) && info != NULL && info->si_addr == g_assert_poison) {
+    handle_assert_poison_fault(ucVoid, info->si_addr);
+    return 1;
+  }
+#endif
+
   JavaThread* thread = NULL;
   VMThread* vmthread = NULL;
   if (os::Linux::signal_handlers_are_installed) {
--- a/src/hotspot/os_cpu/linux_sparc/os_linux_sparc.cpp	Thu Mar 29 21:48:38 2018 -0700
+++ b/src/hotspot/os_cpu/linux_sparc/os_linux_sparc.cpp	Fri Mar 30 06:31:16 2018 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -49,6 +49,7 @@
 #include "runtime/stubRoutines.hpp"
 #include "runtime/thread.inline.hpp"
 #include "runtime/timer.hpp"
+#include "utilities/debug.hpp"
 #include "utilities/events.hpp"
 #include "utilities/vmError.hpp"
 
@@ -513,6 +514,13 @@
     }
   }
 
+#ifdef CAN_SHOW_REGISTERS_ON_ASSERT
+  if ((sig == SIGSEGV || sig == SIGBUS) && info != NULL && info->si_addr == g_assert_poison) {
+    handle_assert_poison_fault(ucVoid, info->si_addr);
+    return 1;
+  }
+#endif
+
   JavaThread* thread = NULL;
   VMThread* vmthread = NULL;
   if (os::Linux::signal_handlers_are_installed) {
--- a/src/hotspot/os_cpu/linux_x86/os_linux_x86.cpp	Thu Mar 29 21:48:38 2018 -0700
+++ b/src/hotspot/os_cpu/linux_x86/os_linux_x86.cpp	Fri Mar 30 06:31:16 2018 +0200
@@ -51,6 +51,7 @@
 #include "runtime/timer.hpp"
 #include "services/memTracker.hpp"
 #include "utilities/align.hpp"
+#include "utilities/debug.hpp"
 #include "utilities/events.hpp"
 #include "utilities/vmError.hpp"
 
@@ -304,6 +305,13 @@
     }
   }
 
+#ifdef CAN_SHOW_REGISTERS_ON_ASSERT
+  if ((sig == SIGSEGV || sig == SIGBUS) && info != NULL && info->si_addr == g_assert_poison) {
+    handle_assert_poison_fault(ucVoid, info->si_addr);
+    return 1;
+  }
+#endif
+
   JavaThread* thread = NULL;
   VMThread* vmthread = NULL;
   if (os::Linux::signal_handlers_are_installed) {
--- a/src/hotspot/share/runtime/arguments.cpp	Thu Mar 29 21:48:38 2018 -0700
+++ b/src/hotspot/share/runtime/arguments.cpp	Fri Mar 30 06:31:16 2018 +0200
@@ -3412,6 +3412,10 @@
   }
 #endif
 
+#ifndef CAN_SHOW_REGISTERS_ON_ASSERT
+  UNSUPPORTED_OPTION(ShowRegistersOnAssert);
+#endif // CAN_SHOW_REGISTERS_ON_ASSERT
+
   return JNI_OK;
 }
 
--- a/src/hotspot/share/runtime/globals.hpp	Thu Mar 29 21:48:38 2018 -0700
+++ b/src/hotspot/share/runtime/globals.hpp	Fri Mar 30 06:31:16 2018 +0200
@@ -4062,6 +4062,9 @@
   develop(bool, VerifyMetaspace, false,                                     \
           "Verify metaspace on chunk movements.")                           \
                                                                             \
+  diagnostic(bool, ShowRegistersOnAssert, false,                            \
+          "On internal errors, include registers in error report.")         \
+                                                                            \
 
 
 
--- a/src/hotspot/share/runtime/thread.cpp	Thu Mar 29 21:48:38 2018 -0700
+++ b/src/hotspot/share/runtime/thread.cpp	Fri Mar 30 06:31:16 2018 +0200
@@ -3661,6 +3661,13 @@
   // Timing (must come after argument parsing)
   TraceTime timer("Create VM", TRACETIME_LOG(Info, startuptime));
 
+#ifdef CAN_SHOW_REGISTERS_ON_ASSERT
+  // Initialize assert poison page mechanism.
+  if (ShowRegistersOnAssert) {
+    initialize_assert_poison();
+  }
+#endif // CAN_SHOW_REGISTERS_ON_ASSERT
+
   // Initialize the os module after parsing the args
   jint os_init_2_result = os::init_2();
   if (os_init_2_result != JNI_OK) return os_init_2_result;
--- a/src/hotspot/share/utilities/debug.cpp	Thu Mar 29 21:48:38 2018 -0700
+++ b/src/hotspot/share/utilities/debug.cpp	Fri Mar 30 06:31:16 2018 +0200
@@ -54,11 +54,20 @@
 #include "utilities/defaultStream.hpp"
 #include "utilities/events.hpp"
 #include "utilities/formatBuffer.hpp"
+#include "utilities/globalDefinitions.hpp"
 #include "utilities/macros.hpp"
 #include "utilities/vmError.hpp"
 
 #include <stdio.h>
 
+// Support for showing register content on asserts/guarantees.
+#ifdef CAN_SHOW_REGISTERS_ON_ASSERT
+static char g_dummy;
+char* g_assert_poison = &g_dummy;
+static intx g_asserting_thread = 0;
+static void* g_assertion_context = NULL;
+#endif // CAN_SHOW_REGISTERS_ON_ASSERT
+
 #ifndef ASSERT
 #  ifdef _DEBUG
    // NOTE: don't turn the lines below into a comment -- if you're getting
@@ -212,7 +221,13 @@
   if (Debugging || error_is_suppressed(file, line)) return;
   va_list detail_args;
   va_start(detail_args, detail_fmt);
-  VMError::report_and_die(Thread::current_or_null(), file, line, error_msg, detail_fmt, detail_args);
+  void* context = NULL;
+#ifdef CAN_SHOW_REGISTERS_ON_ASSERT
+  if (g_assertion_context != NULL && os::current_thread_id() == g_asserting_thread) {
+    context = g_assertion_context;
+  }
+#endif // CAN_SHOW_REGISTERS_ON_ASSERT
+  VMError::report_and_die(Thread::current_or_null(), context, file, line, error_msg, detail_fmt, detail_args);
   va_end(detail_args);
 }
 
@@ -226,7 +241,13 @@
   if (Debugging || error_is_suppressed(file, line)) return;
   va_list detail_args;
   va_start(detail_args, detail_fmt);
-  VMError::report_and_die(Thread::current_or_null(), file, line, "fatal error", detail_fmt, detail_args);
+  void* context = NULL;
+#ifdef CAN_SHOW_REGISTERS_ON_ASSERT
+  if (g_assertion_context != NULL && os::current_thread_id() == g_asserting_thread) {
+    context = g_assertion_context;
+  }
+#endif // CAN_SHOW_REGISTERS_ON_ASSERT
+  VMError::report_and_die(Thread::current_or_null(), context, file, line, "fatal error", detail_fmt, detail_args);
   va_end(detail_args);
 }
 
@@ -676,3 +697,50 @@
 };
 
 #endif // !PRODUCT
+
+// Support for showing register content on asserts/guarantees.
+#ifdef CAN_SHOW_REGISTERS_ON_ASSERT
+
+static ucontext_t g_stored_assertion_context;
+
+void initialize_assert_poison() {
+  char* page = os::reserve_memory(os::vm_page_size());
+  if (page) {
+    if (os::commit_memory(page, os::vm_page_size(), false) &&
+        os::protect_memory(page, os::vm_page_size(), os::MEM_PROT_NONE)) {
+      g_assert_poison = page;
+    }
+  }
+}
+
+static bool store_context(const void* context) {
+  if (memcpy(&g_stored_assertion_context, context, sizeof(ucontext_t)) == false) {
+    return false;
+  }
+#if defined(__linux) && defined(PPC64)
+  // on Linux ppc64, ucontext_t contains pointers into itself which have to be patched up
+  //  after copying the context (see comment in sys/ucontext.h):
+  *((void**) &g_stored_assertion_context.uc_mcontext.regs) = &(g_stored_assertion_context.uc_mcontext.gp_regs);
+#endif
+  return true;
+}
+
+bool handle_assert_poison_fault(const void* ucVoid, const void* faulting_address) {
+  if (faulting_address == g_assert_poison) {
+    // Disarm poison page.
+    os::protect_memory((char*)g_assert_poison, os::vm_page_size(), os::MEM_PROT_RWX);
+    // Store Context away.
+    if (ucVoid) {
+      const jlong my_tid = os::current_thread_id();
+      if (Atomic::cmpxchg(my_tid, &g_asserting_thread, (intx)0) == 0) {
+        if (store_context(ucVoid)) {
+          g_assertion_context = &g_stored_assertion_context;
+        }
+      }
+    }
+    return true;
+  }
+  return false;
+}
+#endif // CAN_SHOW_REGISTERS_ON_ASSERT
+
--- a/src/hotspot/share/utilities/debug.hpp	Thu Mar 29 21:48:38 2018 -0700
+++ b/src/hotspot/share/utilities/debug.hpp	Fri Mar 30 06:31:16 2018 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -31,6 +31,17 @@
 
 #include <stddef.h>
 
+// ShowRegistersOnAssert support (for now Linux only)
+#if defined(LINUX) && !defined(ZERO)
+#define CAN_SHOW_REGISTERS_ON_ASSERT
+extern char* g_assert_poison;
+#define TOUCH_ASSERT_POISON (*g_assert_poison) = 'X';
+void initialize_assert_poison();
+bool handle_assert_poison_fault(const void* ucVoid, const void* faulting_address);
+#else
+#define TOUCH_ASSERT_POISON
+#endif // CAN_SHOW_REGISTERS_ON_ASSERT
+
 // assertions
 #ifndef ASSERT
 #define vmassert(p, ...)
@@ -42,6 +53,7 @@
 #define vmassert(p, ...)                                                       \
 do {                                                                           \
   if (!(p)) {                                                                  \
+    TOUCH_ASSERT_POISON;                                                       \
     if (is_executing_unit_tests()) {                                           \
       report_assert_msg(__VA_ARGS__);                                          \
     }                                                                          \
@@ -67,6 +79,7 @@
 #define vmassert_status(p, status, msg) \
 do {                                                                           \
   if (!(p)) {                                                                  \
+    TOUCH_ASSERT_POISON;                                                       \
     report_vm_status_error(__FILE__, __LINE__, "assert(" #p ") failed",        \
                            status, msg);                                       \
     BREAKPOINT;                                                                \
@@ -83,6 +96,7 @@
 #define guarantee(p, ...)                                                         \
 do {                                                                              \
   if (!(p)) {                                                                     \
+    TOUCH_ASSERT_POISON;                                                          \
     report_vm_error(__FILE__, __LINE__, "guarantee(" #p ") failed", __VA_ARGS__); \
     BREAKPOINT;                                                                   \
   }                                                                               \
@@ -90,6 +104,7 @@
 
 #define fatal(...)                                                                \
 do {                                                                              \
+  TOUCH_ASSERT_POISON;                                                            \
   report_fatal(__FILE__, __LINE__, __VA_ARGS__);                                  \
   BREAKPOINT;                                                                     \
 } while (0)
@@ -103,18 +118,21 @@
 
 #define ShouldNotCallThis()                                                       \
 do {                                                                              \
+  TOUCH_ASSERT_POISON;                                                            \
   report_should_not_call(__FILE__, __LINE__);                                     \
   BREAKPOINT;                                                                     \
 } while (0)
 
 #define ShouldNotReachHere()                                                      \
 do {                                                                              \
+  TOUCH_ASSERT_POISON;                                                            \
   report_should_not_reach_here(__FILE__, __LINE__);                               \
   BREAKPOINT;                                                                     \
 } while (0)
 
 #define Unimplemented()                                                           \
 do {                                                                              \
+  TOUCH_ASSERT_POISON;                                                            \
   report_unimplemented(__FILE__, __LINE__);                                       \
   BREAKPOINT;                                                                     \
 } while (0)
--- a/src/hotspot/share/utilities/vmError.cpp	Thu Mar 29 21:48:38 2018 -0700
+++ b/src/hotspot/share/utilities/vmError.cpp	Fri Mar 30 06:31:16 2018 +0200
@@ -1238,10 +1238,10 @@
   report_and_die(message, "%s", "");
 }
 
-void VMError::report_and_die(Thread* thread, const char* filename, int lineno, const char* message,
+void VMError::report_and_die(Thread* thread, void* context, const char* filename, int lineno, const char* message,
                              const char* detail_fmt, va_list detail_args)
 {
-  report_and_die(INTERNAL_ERROR, message, detail_fmt, detail_args, thread, NULL, NULL, NULL, filename, lineno, 0);
+  report_and_die(INTERNAL_ERROR, message, detail_fmt, detail_args, thread, NULL, NULL, context, filename, lineno, 0);
 }
 
 void VMError::report_and_die(Thread* thread, const char* filename, int lineno, size_t size,
@@ -1674,24 +1674,24 @@
   // Case 16 is tested by test/hotspot/jtreg/runtime/ErrorHandling/ThreadsListHandleInErrorHandlingTest.java.
   // Case 17 is tested by test/hotspot/jtreg/runtime/ErrorHandling/NestedThreadsListHandleInErrorHandlingTest.java.
   switch (how) {
-    case  1: vmassert(str == NULL, "expected null");
+    case  1: vmassert(str == NULL, "expected null"); break;
     case  2: vmassert(num == 1023 && *str == 'X',
-                      "num=" SIZE_FORMAT " str=\"%s\"", num, str);
-    case  3: guarantee(str == NULL, "expected null");
+                      "num=" SIZE_FORMAT " str=\"%s\"", num, str); break;
+    case  3: guarantee(str == NULL, "expected null"); break;
     case  4: guarantee(num == 1023 && *str == 'X',
-                       "num=" SIZE_FORMAT " str=\"%s\"", num, str);
-    case  5: fatal("expected null");
-    case  6: fatal("num=" SIZE_FORMAT " str=\"%s\"", num, str);
+                       "num=" SIZE_FORMAT " str=\"%s\"", num, str); break;
+    case  5: fatal("expected null"); break;
+    case  6: fatal("num=" SIZE_FORMAT " str=\"%s\"", num, str); break;
     case  7: fatal("%s%s#    %s%s#    %s%s#    %s%s#    %s%s#    "
                    "%s%s#    %s%s#    %s%s#    %s%s#    %s%s#    "
                    "%s%s#    %s%s#    %s%s#    %s%s#    %s",
                    msg, eol, msg, eol, msg, eol, msg, eol, msg, eol,
                    msg, eol, msg, eol, msg, eol, msg, eol, msg, eol,
-                   msg, eol, msg, eol, msg, eol, msg, eol, msg);
-    case  8: vm_exit_out_of_memory(num, OOM_MALLOC_ERROR, "ChunkPool::allocate");
-    case  9: ShouldNotCallThis();
-    case 10: ShouldNotReachHere();
-    case 11: Unimplemented();
+                   msg, eol, msg, eol, msg, eol, msg, eol, msg); break;
+    case  8: vm_exit_out_of_memory(num, OOM_MALLOC_ERROR, "ChunkPool::allocate"); break;
+    case  9: ShouldNotCallThis(); break;
+    case 10: ShouldNotReachHere(); break;
+    case 11: Unimplemented(); break;
     // There's no guarantee the bad data pointer will crash us
     // so "break" out to the ShouldNotReachHere().
     case 12: *dataPtr = '\0'; break;
@@ -1714,6 +1714,7 @@
 
     default: tty->print_cr("ERROR: %d: unexpected test_num value.", how);
   }
+  tty->print_cr("VMError::controlled_crash: survived intentional crash. Did you suppress the assert?");
   ShouldNotReachHere();
 }
 #endif // !PRODUCT
--- a/src/hotspot/share/utilities/vmError.hpp	Thu Mar 29 21:48:38 2018 -0700
+++ b/src/hotspot/share/utilities/vmError.hpp	Fri Mar 30 06:31:16 2018 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -158,8 +158,8 @@
   static void report_and_die(Thread* thread, unsigned int sig, address pc,
                              void* siginfo, void* context);
 
-  static void report_and_die(Thread* thread,const char* filename, int lineno, const char* message,
-                             const char* detail_fmt, va_list detail_args) ATTRIBUTE_PRINTF(5, 0);
+  static void report_and_die(Thread* thread, void* context, const char* filename, int lineno, const char* message,
+                             const char* detail_fmt, va_list detail_args) ATTRIBUTE_PRINTF(6, 0);
 
   static void report_and_die(Thread* thread, const char* filename, int lineno, size_t size,
                              VMErrorType vm_err_type, const char* detail_fmt,
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/ErrorHandling/ShowRegistersOnAssertTest.java	Fri Mar 30 06:31:16 2018 +0200
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+
+/*
+ * @test
+ * @bug 8191101
+ * @summary Show Registers on assert/guarantee
+ * @library /test/lib
+ * @requires (vm.debug == true) & (os.family == "linux")
+ * @author Thomas Stuefe (SAP)
+ * @modules java.base/jdk.internal.misc
+ *          java.management
+ */
+
+// Note: this test can only run on debug since it relies on VMError::controlled_crash() which
+// only exists in debug builds.
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.InputStreamReader;
+import java.util.regex.Pattern;
+
+import jdk.test.lib.process.OutputAnalyzer;
+import jdk.test.lib.Platform;
+import jdk.test.lib.process.ProcessTools;
+
+public class ShowRegistersOnAssertTest {
+
+    private static void do_test(boolean do_assert, // true - assert, false - guarantee
+        boolean suppress_assert,
+        boolean show_registers_on_assert) throws Exception
+    {
+        System.out.println("Testing " + (suppress_assert ? "suppressed" : "normal") + " " + (do_assert ? "assert" : "guarantee") +
+                           " with " + (show_registers_on_assert ? "-XX:+ShowRegistersOnAssert" : "-XX:-ShowRegistersOnAssert") + "...");
+        ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(
+            "-XX:+UnlockDiagnosticVMOptions", "-Xmx100M", "-XX:-CreateCoredumpOnCrash",
+            "-XX:ErrorHandlerTest=" + (do_assert ? "1" : "3"),
+            (suppress_assert ? "-XX:SuppressErrorAt=/vmError.cpp" : ""),
+            (show_registers_on_assert ? "-XX:+ShowRegistersOnAssert" : "-XX:-ShowRegistersOnAssert"),
+            "-version");
+
+        OutputAnalyzer output_detail = new OutputAnalyzer(pb.start());
+
+        if (suppress_assert) {
+            // we should have not have crashed. See VMError::controlled_crash().
+            output_detail.shouldMatch(".*survived intentional crash.*");
+        } else {
+            // we should have crashed with an internal error. We should definitly NOT have crashed with a segfault
+            // (which would be a sign that the assert poison page mechanism does not work).
+            output_detail.shouldMatch("# A fatal error has been detected by the Java Runtime Environment:.*");
+            output_detail.shouldMatch("# +Internal Error.*");
+        }
+    }
+
+    public static void main(String[] args) throws Exception {
+        // Note: for now, this is only a regression test testing that the addition of ShowRegistersOnAssert does
+        // not break normal assert/guarantee handling. The feature is not implemented on all platforms and really testing
+        // it requires more effort.
+        do_test(false, false, false);
+        do_test(false, false, true);
+        do_test(false, true, false);
+        do_test(false, true, true);
+        do_test(true, false, false);
+        do_test(true, false, true);
+        do_test(true, true, false);
+        do_test(true, true, true);
+    }
+
+}
+