# HG changeset patch # User stuefe # Date 1522384276 -7200 # Node ID a569cb4425f3e6e4be3d4249820e71ab8a87f362 # Parent a74836b05c2856d3192fa1c1f53cf3b03467d21a 8191101: Show register content in hs-err file on assert Reviewed-by: adinn, clanger, simonis diff -r a74836b05c28 -r a569cb4425f3 src/hotspot/os/posix/vmError_posix.cpp --- 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 @@ -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); } diff -r a74836b05c28 -r a569cb4425f3 src/hotspot/os_cpu/linux_aarch64/os_linux_aarch64.cpp --- 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) { diff -r a74836b05c28 -r a569cb4425f3 src/hotspot/os_cpu/linux_arm/os_linux_arm.cpp --- 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) { diff -r a74836b05c28 -r a569cb4425f3 src/hotspot/os_cpu/linux_ppc/os_linux_ppc.cpp --- 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) { diff -r a74836b05c28 -r a569cb4425f3 src/hotspot/os_cpu/linux_s390/os_linux_s390.cpp --- 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) { diff -r a74836b05c28 -r a569cb4425f3 src/hotspot/os_cpu/linux_sparc/os_linux_sparc.cpp --- 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) { diff -r a74836b05c28 -r a569cb4425f3 src/hotspot/os_cpu/linux_x86/os_linux_x86.cpp --- 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) { diff -r a74836b05c28 -r a569cb4425f3 src/hotspot/share/runtime/arguments.cpp --- 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; } diff -r a74836b05c28 -r a569cb4425f3 src/hotspot/share/runtime/globals.hpp --- 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.") \ + \ diff -r a74836b05c28 -r a569cb4425f3 src/hotspot/share/runtime/thread.cpp --- 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; diff -r a74836b05c28 -r a569cb4425f3 src/hotspot/share/utilities/debug.cpp --- 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 +// 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 + diff -r a74836b05c28 -r a569cb4425f3 src/hotspot/share/utilities/debug.hpp --- 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 +// 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) diff -r a74836b05c28 -r a569cb4425f3 src/hotspot/share/utilities/vmError.cpp --- 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 diff -r a74836b05c28 -r a569cb4425f3 src/hotspot/share/utilities/vmError.hpp --- 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, diff -r a74836b05c28 -r a569cb4425f3 test/hotspot/jtreg/runtime/ErrorHandling/ShowRegistersOnAssertTest.java --- /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); + } + +} +