8074552: SafeFetch32 and SafeFetchN do not work in error handling
Reviewed-by: dholmes, goetz
Contributed-by: Thomas Stufe <thomas.stuefe@gmail.com>
--- a/hotspot/src/os/aix/vm/vmError_aix.cpp Wed Mar 11 18:49:22 2015 -0400
+++ b/hotspot/src/os/aix/vm/vmError_aix.cpp Thu Mar 12 19:34:50 2015 -0400
@@ -109,7 +109,15 @@
}
sigthreadmask(SIG_UNBLOCK, &newset, NULL);
- VMError err(NULL, sig, NULL, info, ucVoid);
+ // support safefetch faults in error handling
+ ucontext_t* const uc = (ucontext_t*) ucVoid;
+ address const pc = uc ? os::Aix::ucontext_get_pc(uc) : NULL;
+ if (uc && pc && StubRoutines::is_safefetch_fault(pc)) {
+ os::Aix::ucontext_set_pc(uc, StubRoutines::continuation_for_safefetch_fault(pc));
+ return;
+ }
+
+ VMError err(NULL, sig, pc, info, ucVoid);
err.report_and_die();
}
--- a/hotspot/src/os/bsd/vm/os_bsd.hpp Wed Mar 11 18:49:22 2015 -0400
+++ b/hotspot/src/os/bsd/vm/os_bsd.hpp Thu Mar 12 19:34:50 2015 -0400
@@ -99,6 +99,7 @@
static void set_page_size(int val) { _page_size = val; }
static address ucontext_get_pc(ucontext_t* uc);
+ static void ucontext_set_pc(ucontext_t* uc, address pc);
static intptr_t* ucontext_get_sp(ucontext_t* uc);
static intptr_t* ucontext_get_fp(ucontext_t* uc);
--- a/hotspot/src/os/bsd/vm/vmError_bsd.cpp Wed Mar 11 18:49:22 2015 -0400
+++ b/hotspot/src/os/bsd/vm/vmError_bsd.cpp Thu Mar 12 19:34:50 2015 -0400
@@ -112,7 +112,16 @@
}
pthread_sigmask(SIG_UNBLOCK, &newset, NULL);
- VMError err(NULL, sig, NULL, info, ucVoid);
+ // support safefetch faults in error handling
+ ucontext_t* const uc = (ucontext_t*) ucVoid;
+ address const pc = uc ? os::Bsd::ucontext_get_pc(uc) : NULL;
+
+ if (uc && pc && StubRoutines::is_safefetch_fault(pc)) {
+ os::Bsd::ucontext_set_pc(uc, StubRoutines::continuation_for_safefetch_fault(pc));
+ return;
+ }
+
+ VMError err(NULL, sig, pc, info, ucVoid);
err.report_and_die();
}
--- a/hotspot/src/os/linux/vm/os_linux.hpp Wed Mar 11 18:49:22 2015 -0400
+++ b/hotspot/src/os/linux/vm/os_linux.hpp Thu Mar 12 19:34:50 2015 -0400
@@ -143,6 +143,7 @@
static int vm_default_page_size(void) { return _vm_default_page_size; }
static address ucontext_get_pc(ucontext_t* uc);
+ static void ucontext_set_pc(ucontext_t* uc, address pc);
static intptr_t* ucontext_get_sp(ucontext_t* uc);
static intptr_t* ucontext_get_fp(ucontext_t* uc);
--- a/hotspot/src/os/linux/vm/vmError_linux.cpp Wed Mar 11 18:49:22 2015 -0400
+++ b/hotspot/src/os/linux/vm/vmError_linux.cpp Thu Mar 12 19:34:50 2015 -0400
@@ -112,7 +112,16 @@
}
pthread_sigmask(SIG_UNBLOCK, &newset, NULL);
- VMError err(NULL, sig, NULL, info, ucVoid);
+ // support safefetch faults in error handling
+ ucontext_t* const uc = (ucontext_t*) ucVoid;
+ address const pc = uc ? os::Linux::ucontext_get_pc(uc) : NULL;
+
+ if (uc && pc && StubRoutines::is_safefetch_fault(pc)) {
+ os::Linux::ucontext_set_pc(uc, StubRoutines::continuation_for_safefetch_fault(pc));
+ return;
+ }
+
+ VMError err(NULL, sig, pc, info, ucVoid);
err.report_and_die();
}
--- a/hotspot/src/os/solaris/vm/os_solaris.hpp Wed Mar 11 18:49:22 2015 -0400
+++ b/hotspot/src/os/solaris/vm/os_solaris.hpp Thu Mar 12 19:34:50 2015 -0400
@@ -137,6 +137,7 @@
// ucontext_get_fp() is only used by Solaris X86 (see note below)
static intptr_t* ucontext_get_fp(ucontext_t* uc);
static address ucontext_get_pc(ucontext_t* uc);
+ static void ucontext_set_pc(ucontext_t* uc, address pc);
// For Analyzer Forte AsyncGetCallTrace profiling support:
// Parameter ret_fp is only used by Solaris X86.
--- a/hotspot/src/os/solaris/vm/vmError_solaris.cpp Wed Mar 11 18:49:22 2015 -0400
+++ b/hotspot/src/os/solaris/vm/vmError_solaris.cpp Thu Mar 12 19:34:50 2015 -0400
@@ -109,7 +109,15 @@
}
thr_sigsetmask(SIG_UNBLOCK, &newset, NULL);
- VMError err(NULL, sig, NULL, info, ucVoid);
+ // support safefetch faults in error handling
+ ucontext_t* const uc = (ucontext_t*) ucVoid;
+ address const pc = uc ? os::Solaris::ucontext_get_pc(uc) : NULL;
+ if (uc && pc && StubRoutines::is_safefetch_fault(pc)) {
+ os::Solaris::ucontext_set_pc(uc, StubRoutines::continuation_for_safefetch_fault(pc));
+ return;
+ }
+
+ VMError err(NULL, sig, pc, info, ucVoid);
err.report_and_die();
}
--- a/hotspot/src/os_cpu/aix_ppc/vm/os_aix_ppc.cpp Wed Mar 11 18:49:22 2015 -0400
+++ b/hotspot/src/os_cpu/aix_ppc/vm/os_aix_ppc.cpp Thu Mar 12 19:34:50 2015 -0400
@@ -397,7 +397,7 @@
// continue at the next instruction after the faulting read. Returning
// garbage from this read is ok.
thread->set_pending_unsafe_access_error();
- uc->uc_mcontext.jmp_context.iar = ((unsigned long)pc) + 4;
+ os::Aix::ucontext_set_pc(uc, pc + 4);
return 1;
}
}
@@ -420,7 +420,7 @@
// continue at the next instruction after the faulting read. Returning
// garbage from this read is ok.
thread->set_pending_unsafe_access_error();
- uc->uc_mcontext.jmp_context.iar = ((unsigned long)pc) + 4;
+ os::Aix::ucontext_set_pc(uc, pc + 4);
return 1;
}
}
@@ -445,7 +445,7 @@
if (stub != NULL) {
// Save all thread context in case we need to restore it.
if (thread != NULL) thread->set_saved_exception_pc(pc);
- uc->uc_mcontext.jmp_context.iar = (unsigned long)stub;
+ os::Aix::ucontext_set_pc(uc, stub);
return 1;
}
--- a/hotspot/src/os_cpu/bsd_x86/vm/os_bsd_x86.cpp Wed Mar 11 18:49:22 2015 -0400
+++ b/hotspot/src/os_cpu/bsd_x86/vm/os_bsd_x86.cpp Thu Mar 12 19:34:50 2015 -0400
@@ -309,6 +309,10 @@
return (address)uc->context_pc;
}
+void os::Bsd::ucontext_set_pc(ucontext_t * uc, address pc) {
+ uc->context_pc = (intptr_t)pc ;
+}
+
intptr_t* os::Bsd::ucontext_get_sp(ucontext_t * uc) {
return (intptr_t*)uc->context_sp;
}
@@ -463,7 +467,7 @@
pc = (address) os::Bsd::ucontext_get_pc(uc);
if (StubRoutines::is_safefetch_fault(pc)) {
- uc->context_pc = intptr_t(StubRoutines::continuation_for_safefetch_fault(pc));
+ os::Bsd::ucontext_set_pc(uc, StubRoutines::continuation_for_safefetch_fault(pc));
return 1;
}
@@ -703,7 +707,7 @@
// save all thread context in case we need to restore it
if (thread != NULL) thread->set_saved_exception_pc(pc);
- uc->context_pc = (intptr_t)stub;
+ os::Bsd::ucontext_set_pc(uc, stub);
return true;
}
--- a/hotspot/src/os_cpu/bsd_zero/vm/os_bsd_zero.cpp Wed Mar 11 18:49:22 2015 -0400
+++ b/hotspot/src/os_cpu/bsd_zero/vm/os_bsd_zero.cpp Thu Mar 12 19:34:50 2015 -0400
@@ -107,6 +107,10 @@
return NULL;
}
+void os::Bsd::ucontext_set_pc(ucontext_t * uc, address pc) {
+ ShouldNotCallThis();
+}
+
ExtendedPC os::fetch_frame_from_context(void* ucVoid,
intptr_t** ret_sp,
intptr_t** ret_fp) {
--- a/hotspot/src/os_cpu/linux_ppc/vm/os_linux_ppc.cpp Wed Mar 11 18:49:22 2015 -0400
+++ b/hotspot/src/os_cpu/linux_ppc/vm/os_linux_ppc.cpp Thu Mar 12 19:34:50 2015 -0400
@@ -113,6 +113,14 @@
return (address)uc->uc_mcontext.regs->nip;
}
+// modify PC in ucontext.
+// Note: Only use this for an ucontext handed down to a signal handler. See comment
+// in ucontext_get_pc.
+void os::Linux::ucontext_set_pc(ucontext_t * uc, address pc) {
+ guarantee(uc->uc_mcontext.regs != NULL, "only use ucontext_set_pc in sigaction context");
+ uc->uc_mcontext.regs->nip = (unsigned long)pc;
+}
+
intptr_t* os::Linux::ucontext_get_sp(ucontext_t * uc) {
return (intptr_t*)uc->uc_mcontext.regs->gpr[1/*REG_SP*/];
}
@@ -213,7 +221,7 @@
if (uc) {
address const pc = os::Linux::ucontext_get_pc(uc);
if (pc && StubRoutines::is_safefetch_fault(pc)) {
- uc->uc_mcontext.regs->nip = (unsigned long)StubRoutines::continuation_for_safefetch_fault(pc);
+ os::Linux::ucontext_set_pc(uc, StubRoutines::continuation_for_safefetch_fault(pc));
return true;
}
}
@@ -360,7 +368,7 @@
// continue at the next instruction after the faulting read. Returning
// garbage from this read is ok.
thread->set_pending_unsafe_access_error();
- uc->uc_mcontext.regs->nip = ((unsigned long)pc) + 4;
+ os::Linux::ucontext_set_pc(uc, pc + 4);
return true;
}
}
@@ -379,7 +387,7 @@
// continue at the next instruction after the faulting read. Returning
// garbage from this read is ok.
thread->set_pending_unsafe_access_error();
- uc->uc_mcontext.regs->nip = ((unsigned long)pc) + 4;
+ os::Linux::ucontext_set_pc(uc, pc + 4);
return true;
}
}
@@ -402,7 +410,7 @@
if (stub != NULL) {
// Save all thread context in case we need to restore it.
if (thread != NULL) thread->set_saved_exception_pc(pc);
- uc->uc_mcontext.regs->nip = (unsigned long)stub;
+ os::Linux::ucontext_set_pc(uc, stub);
return true;
}
--- a/hotspot/src/os_cpu/linux_sparc/vm/os_linux_sparc.cpp Wed Mar 11 18:49:22 2015 -0400
+++ b/hotspot/src/os_cpu/linux_sparc/vm/os_linux_sparc.cpp Thu Mar 12 19:34:50 2015 -0400
@@ -85,11 +85,6 @@
CON_O7,
};
-static inline void set_cont_address(sigcontext* ctx, address addr) {
- SIG_PC(ctx) = (intptr_t)addr;
- SIG_NPC(ctx) = (intptr_t)(addr+4);
-}
-
// For Forte Analyzer AsyncGetCallTrace profiling support - thread is
// currently interrupted by SIGPROF.
// os::Solaris::fetch_frame_from_ucontext() tries to skip nested
@@ -351,6 +346,12 @@
return (address) SIG_PC((sigcontext*)uc);
}
+void os::Linux::ucontext_set_pc(ucontext_t* uc, address pc) {
+ sigcontext_t* ctx = (sigcontext_t*) uc;
+ SIG_PC(ctx) = (intptr_t)addr;
+ SIG_NPC(ctx) = (intptr_t)(addr+4);
+}
+
intptr_t* os::Linux::ucontext_get_sp(ucontext_t *uc) {
return (intptr_t*)
((intptr_t)SIG_REGS((sigcontext*)uc).u_regs[CON_O6] + STACK_BIAS);
@@ -366,7 +367,7 @@
inline static bool checkPrefetch(sigcontext* uc, address pc) {
if (StubRoutines::is_safefetch_fault(pc)) {
- set_cont_address(uc, address(StubRoutines::continuation_for_safefetch_fault(pc)));
+ os::Linux::ucontext_set_pc((ucontext_t*)uc, StubRoutines::continuation_for_safefetch_fault(pc));
return true;
}
return false;
@@ -666,7 +667,7 @@
// save all thread context in case we need to restore it
thread->set_saved_exception_pc(pc);
thread->set_saved_exception_npc(npc);
- set_cont_address(uc, stub);
+ os::Linux::ucontext_set_pc((ucontext_t*)uc, stub);
return true;
}
}
--- a/hotspot/src/os_cpu/linux_x86/vm/os_linux_x86.cpp Wed Mar 11 18:49:22 2015 -0400
+++ b/hotspot/src/os_cpu/linux_x86/vm/os_linux_x86.cpp Thu Mar 12 19:34:50 2015 -0400
@@ -122,6 +122,10 @@
return (address)uc->uc_mcontext.gregs[REG_PC];
}
+void os::Linux::ucontext_set_pc(ucontext_t * uc, address pc) {
+ uc->uc_mcontext.gregs[REG_PC] = (intptr_t)pc;
+}
+
intptr_t* os::Linux::ucontext_get_sp(ucontext_t * uc) {
return (intptr_t*)uc->uc_mcontext.gregs[REG_SP];
}
@@ -279,7 +283,7 @@
pc = (address) os::Linux::ucontext_get_pc(uc);
if (StubRoutines::is_safefetch_fault(pc)) {
- uc->uc_mcontext.gregs[REG_PC] = intptr_t(StubRoutines::continuation_for_safefetch_fault(pc));
+ os::Linux::ucontext_set_pc(uc, StubRoutines::continuation_for_safefetch_fault(pc));
return 1;
}
@@ -514,7 +518,7 @@
// save all thread context in case we need to restore it
if (thread != NULL) thread->set_saved_exception_pc(pc);
- uc->uc_mcontext.gregs[REG_PC] = (greg_t)stub;
+ os::Linux::ucontext_set_pc(uc, stub);
return true;
}
--- a/hotspot/src/os_cpu/linux_zero/vm/os_linux_zero.cpp Wed Mar 11 18:49:22 2015 -0400
+++ b/hotspot/src/os_cpu/linux_zero/vm/os_linux_zero.cpp Thu Mar 12 19:34:50 2015 -0400
@@ -100,6 +100,10 @@
ShouldNotCallThis();
}
+void os::Linux::ucontext_set_pc(ucontext_t * uc, address pc) {
+ ShouldNotCallThis();
+}
+
ExtendedPC os::fetch_frame_from_context(void* ucVoid,
intptr_t** ret_sp,
intptr_t** ret_fp) {
--- a/hotspot/src/os_cpu/solaris_sparc/vm/os_solaris_sparc.cpp Wed Mar 11 18:49:22 2015 -0400
+++ b/hotspot/src/os_cpu/solaris_sparc/vm/os_solaris_sparc.cpp Thu Mar 12 19:34:50 2015 -0400
@@ -184,6 +184,11 @@
return ExtendedPC(pc);
}
+void os::Solaris::ucontext_set_pc(ucontext_t* uc, address pc) {
+ uc->uc_mcontext.gregs [REG_PC] = (greg_t) pc;
+ uc->uc_mcontext.gregs [REG_nPC] = (greg_t) (pc + 4);
+}
+
// Assumes ucontext is valid
intptr_t* os::Solaris::ucontext_get_sp(ucontext_t *uc) {
return (intptr_t*)((intptr_t)uc->uc_mcontext.gregs[REG_SP] + STACK_BIAS);
@@ -355,8 +360,7 @@
// SafeFetch() support
if (StubRoutines::is_safefetch_fault(pc)) {
- uc->uc_mcontext.gregs[REG_PC] = intptr_t(StubRoutines::continuation_for_safefetch_fault(pc));
- uc->uc_mcontext.gregs[REG_nPC] = uc->uc_mcontext.gregs[REG_PC] + 4;
+ os::Solaris::ucontext_set_pc(uc, StubRoutines::continuation_for_safefetch_fault(pc));
return 1;
}
@@ -494,8 +498,7 @@
// simulate a branch to the stub (a "call" in the safepoint stub case)
// factor me: setPC
- uc->uc_mcontext.gregs[REG_PC ] = (greg_t)stub;
- uc->uc_mcontext.gregs[REG_nPC] = (greg_t)(stub + 4);
+ os::Solaris::ucontext_set_pc(uc, stub);
#ifndef PRODUCT
if (TraceJumps) thread->record_jump(stub, NULL, __FILE__, __LINE__);
--- a/hotspot/src/os_cpu/solaris_x86/vm/os_solaris_x86.cpp Wed Mar 11 18:49:22 2015 -0400
+++ b/hotspot/src/os_cpu/solaris_x86/vm/os_solaris_x86.cpp Thu Mar 12 19:34:50 2015 -0400
@@ -174,6 +174,10 @@
return ExtendedPC((address)uc->uc_mcontext.gregs[REG_PC]);
}
+void os::Solaris::ucontext_set_pc(ucontext_t* uc, address pc) {
+ uc->uc_mcontext.gregs [REG_PC] = (greg_t) pc;
+}
+
// Assumes ucontext is valid
intptr_t* os::Solaris::ucontext_get_sp(ucontext_t *uc) {
return (intptr_t*)uc->uc_mcontext.gregs[REG_SP];
@@ -411,7 +415,7 @@
pc = (address) uc->uc_mcontext.gregs[REG_PC];
if (StubRoutines::is_safefetch_fault(pc)) {
- uc->uc_mcontext.gregs[REG_PC] = intptr_t(StubRoutines::continuation_for_safefetch_fault(pc));
+ os::Solaris::ucontext_set_pc(uc, StubRoutines::continuation_for_safefetch_fault(pc));
return true;
}
@@ -614,8 +618,7 @@
if (thread != NULL) thread->set_saved_exception_pc(pc);
// 12/02/99: On Sparc it appears that the full context is also saved
// but as yet, no one looks at or restores that saved context
- // factor me: setPC
- uc->uc_mcontext.gregs[REG_PC] = (greg_t)stub;
+ os::Solaris::ucontext_set_pc(uc, stub);
return true;
}
--- a/hotspot/src/share/vm/runtime/globals.hpp Wed Mar 11 18:49:22 2015 -0400
+++ b/hotspot/src/share/vm/runtime/globals.hpp Thu Mar 12 19:34:50 2015 -0400
@@ -921,6 +921,9 @@
"If > 0, provokes an error inside VM error handler (a secondary " \
"crash). see test_error_handler() in debug.cpp.") \
\
+ notproduct(bool, TestSafeFetchInErrorHandler, false, \
+ "If true, tests SafeFetch inside error handler.") \
+ \
develop(bool, Verbose, false, \
"Print additional debugging information from other modes") \
\
--- a/hotspot/src/share/vm/runtime/stubRoutines.cpp Wed Mar 11 18:49:22 2015 -0400
+++ b/hotspot/src/share/vm/runtime/stubRoutines.cpp Thu Mar 12 19:34:50 2015 -0400
@@ -210,8 +210,36 @@
assert(fbuffer[i] == v && fbuffer2[i] == v2, "shouldn't have copied anything");
}
}
+
+// simple test for SafeFetch32
+static void test_safefetch32() {
+ int dummy = 17;
+ int* const p_invalid = (int*) get_segfault_address();
+ int* const p_valid = &dummy;
+ int result_invalid = SafeFetch32(p_invalid, 0xABC);
+ assert(result_invalid == 0xABC, "SafeFetch32 error");
+ int result_valid = SafeFetch32(p_valid, 0xABC);
+ assert(result_valid == 17, "SafeFetch32 error");
+}
+
+// simple test for SafeFetchN
+static void test_safefetchN() {
+#ifdef _LP64
+ const intptr_t v1 = UCONST64(0xABCD00000000ABCD);
+ const intptr_t v2 = UCONST64(0xDEFD00000000DEFD);
+#else
+ const intptr_t v1 = 0xABCDABCD;
+ const intptr_t v2 = 0xDEFDDEFD;
#endif
-
+ intptr_t dummy = v1;
+ intptr_t* const p_invalid = (intptr_t*) get_segfault_address();
+ intptr_t* const p_valid = &dummy;
+ intptr_t result_invalid = SafeFetchN(p_invalid, v2);
+ assert(result_invalid == v2, "SafeFetchN error");
+ intptr_t result_valid = SafeFetchN(p_valid, v2);
+ assert(result_valid == v1, "SafeFetchN error");
+}
+#endif
void StubRoutines::initialize2() {
if (_code2 == NULL) {
@@ -300,6 +328,13 @@
test_arraycopy_func(CAST_FROM_FN_PTR(address, Copy::aligned_conjoint_words), sizeof(jlong));
test_arraycopy_func(CAST_FROM_FN_PTR(address, Copy::aligned_disjoint_words), sizeof(jlong));
+ // test safefetch routines
+ // Not on Windows 32bit until 8074860 is fixed
+#if ! (defined(_WIN32) && defined(_M_IX86))
+ test_safefetch32();
+ test_safefetchN();
+#endif
+
#endif
}
--- a/hotspot/src/share/vm/runtime/stubRoutines.hpp Wed Mar 11 18:49:22 2015 -0400
+++ b/hotspot/src/share/vm/runtime/stubRoutines.hpp Thu Mar 12 19:34:50 2015 -0400
@@ -458,4 +458,9 @@
return StubRoutines::SafeFetchN_stub()(adr, errValue);
}
+
+// returns true if SafeFetch32 and SafeFetchN can be used safely (stubroutines are already generated)
+inline bool CanUseSafeFetch32() { return StubRoutines::SafeFetch32_stub() ? true : false; }
+inline bool CanUseSafeFetchN() { return StubRoutines::SafeFetchN_stub() ? true : false; }
+
#endif // SHARE_VM_RUNTIME_STUBROUTINES_HPP
--- a/hotspot/src/share/vm/utilities/vmError.cpp Wed Mar 11 18:49:22 2015 -0400
+++ b/hotspot/src/share/vm/utilities/vmError.cpp Thu Mar 12 19:34:50 2015 -0400
@@ -358,18 +358,38 @@
// test secondary error handling. Test it twice, to test that resetting
// error handler after a secondary crash works.
- STEP(13, "(test secondary crash 1)")
+ STEP(11, "(test secondary crash 1)")
+ if (_verbose && TestCrashInErrorHandler != 0) {
+ st->print_cr("Will crash now (TestCrashInErrorHandler=%d)...",
+ TestCrashInErrorHandler);
+ controlled_crash(TestCrashInErrorHandler);
+ }
+
+ STEP(12, "(test secondary crash 2)")
if (_verbose && TestCrashInErrorHandler != 0) {
st->print_cr("Will crash now (TestCrashInErrorHandler=%d)...",
TestCrashInErrorHandler);
controlled_crash(TestCrashInErrorHandler);
}
- STEP(14, "(test secondary crash 2)")
- if (_verbose && TestCrashInErrorHandler != 0) {
- st->print_cr("Will crash now (TestCrashInErrorHandler=%d)...",
- TestCrashInErrorHandler);
- controlled_crash(TestCrashInErrorHandler);
+ STEP(13, "(test safefetch in error handler)")
+ // test whether it is safe to use SafeFetch32 in Crash Handler. Test twice
+ // to test that resetting the signal handler works correctly.
+ if (_verbose && TestSafeFetchInErrorHandler) {
+ st->print_cr("Will test SafeFetch...");
+ if (CanUseSafeFetch32()) {
+ int* const invalid_pointer = (int*) get_segfault_address();
+ const int x = 0x76543210;
+ int i1 = SafeFetch32(invalid_pointer, x);
+ int i2 = SafeFetch32(invalid_pointer, x);
+ if (i1 == x && i2 == x) {
+ st->print_cr("SafeFetch OK."); // Correctly deflected and returned default pattern
+ } else {
+ st->print_cr("??");
+ }
+ } else {
+ st->print_cr("not possible; skipped.");
+ }
}
#endif // PRODUCT
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/ErrorHandling/SafeFetchInErrorHandlingTest.java Thu Mar 12 19:34:50 2015 -0400
@@ -0,0 +1,92 @@
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.InputStreamReader;
+import java.util.regex.Pattern;
+
+import com.oracle.java.testlibrary.OutputAnalyzer;
+import com.oracle.java.testlibrary.Platform;
+import com.oracle.java.testlibrary.ProcessTools;
+
+/*
+ * @test
+ * @bug 8074552
+ * @summary SafeFetch32 and SafeFetchN do not work in error handling
+ * @library /testlibrary
+ * @author Thomas Stuefe (SAP)
+ */
+
+public class SafeFetchInErrorHandlingTest {
+
+
+ public static void main(String[] args) throws Exception {
+
+ if (!Platform.isDebugBuild()) {
+ return;
+ }
+
+ ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(
+ "-XX:+UnlockDiagnosticVMOptions",
+ "-Xmx100M",
+ "-XX:ErrorHandlerTest=14",
+ "-XX:+TestSafeFetchInErrorHandler",
+ "-version");
+
+ OutputAnalyzer output_detail = new OutputAnalyzer(pb.start());
+
+ // we should have crashed with a SIGSEGV
+ output_detail.shouldMatch("# A fatal error has been detected by the Java Runtime Environment:.*");
+ output_detail.shouldMatch("# +(?:SIGSEGV|EXCEPTION_ACCESS_VIOLATION).*");
+
+ // extract hs-err file
+ String hs_err_file = output_detail.firstMatch("# *(\\S*hs_err_pid\\d+\\.log)", 1);
+ if (hs_err_file == null) {
+ throw new RuntimeException("Did not find hs-err file in output.\n");
+ }
+
+ File f = new File(hs_err_file);
+ if (!f.exists()) {
+ throw new RuntimeException("hs-err file missing at "
+ + f.getAbsolutePath() + ".\n");
+ }
+
+ System.out.println("Found hs_err file. Scanning...");
+
+ FileInputStream fis = new FileInputStream(f);
+ BufferedReader br = new BufferedReader(new InputStreamReader(fis));
+ String line = null;
+
+ Pattern [] pattern = new Pattern[] {
+ Pattern.compile("Will test SafeFetch..."),
+ Pattern.compile("SafeFetch OK."),
+ };
+ int currentPattern = 0;
+
+ String lastLine = null;
+ while ((line = br.readLine()) != null) {
+ if (currentPattern < pattern.length) {
+ if (pattern[currentPattern].matcher(line).matches()) {
+ System.out.println("Found: " + line + ".");
+ currentPattern ++;
+ }
+ }
+ lastLine = line;
+ }
+ br.close();
+
+ if (currentPattern < pattern.length) {
+ throw new RuntimeException("hs-err file incomplete (first missing pattern: " + currentPattern + ")");
+ }
+
+ if (!lastLine.equals("END.")) {
+ throw new RuntimeException("hs-err file incomplete (missing END marker.)");
+ } else {
+ System.out.println("End marker found.");
+ }
+
+ System.out.println("OK.");
+
+ }
+
+}
+