8191101: Show register content in hs-err file on assert
Reviewed-by: adinn, clanger, simonis
--- 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);
+ }
+
+}
+