Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 15 additions & 37 deletions src/hotspot/os/windows/os_windows.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2628,14 +2628,13 @@ LONG WINAPI topLevelExceptionFilter(struct _EXCEPTION_POINTERS* exceptionInfo) {
DWORD exception_code = exception_record->ExceptionCode;
#if defined(_M_ARM64)
address pc = (address) exceptionInfo->ContextRecord->Pc;

if (handle_safefetch(exception_code, pc, (void*)exceptionInfo->ContextRecord)) {
return EXCEPTION_CONTINUE_EXECUTION;
}
#elif defined(_M_AMD64)
address pc = (address) exceptionInfo->ContextRecord->Rip;
#else
#error unknown architecture
#endif
Thread* t = Thread::current_or_null_safe();

#if defined(_M_AMD64)
if ((exception_code == EXCEPTION_ACCESS_VIOLATION) &&
VM_Version::is_cpuinfo_segv_addr(pc)) {
// Verify that OS save/restore AVX registers.
Expand All @@ -2648,6 +2647,8 @@ LONG WINAPI topLevelExceptionFilter(struct _EXCEPTION_POINTERS* exceptionInfo) {
VM_Version::clear_apx_test_state();
return Handle_Exception(exceptionInfo, VM_Version::cpuinfo_cont_addr_apx());
}
#else
#error unknown architecture
#endif

#ifdef CAN_SHOW_REGISTERS_ON_ASSERT
Expand All @@ -2658,6 +2659,7 @@ LONG WINAPI topLevelExceptionFilter(struct _EXCEPTION_POINTERS* exceptionInfo) {
}
#endif

Thread* t = Thread::current_or_null_safe();
if (t != nullptr && t->is_Java_thread()) {
JavaThread* thread = JavaThread::cast(t);
bool in_java = thread->thread_state() == _thread_in_Java;
Expand Down Expand Up @@ -2688,10 +2690,8 @@ LONG WINAPI topLevelExceptionFilter(struct _EXCEPTION_POINTERS* exceptionInfo) {
// Fatal red zone violation.
overflow_state->disable_stack_red_zone();
tty->print_raw_cr("An unrecoverable stack overflow has occurred.");
#if !defined(USE_VECTORED_EXCEPTION_HANDLING)
report_error(t, exception_code, pc, exception_record,
exceptionInfo->ContextRecord);
#endif
return EXCEPTION_CONTINUE_SEARCH;
}
} else if (exception_code == EXCEPTION_ACCESS_VIOLATION) {
Expand Down Expand Up @@ -2743,10 +2743,8 @@ LONG WINAPI topLevelExceptionFilter(struct _EXCEPTION_POINTERS* exceptionInfo) {
}

// Stack overflow or null pointer exception in native code.
#if !defined(USE_VECTORED_EXCEPTION_HANDLING)
report_error(t, exception_code, pc, exception_record,
exceptionInfo->ContextRecord);
#endif
return EXCEPTION_CONTINUE_SEARCH;
} // /EXCEPTION_ACCESS_VIOLATION
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Expand Down Expand Up @@ -2821,41 +2819,21 @@ LONG WINAPI topLevelExceptionFilter(struct _EXCEPTION_POINTERS* exceptionInfo) {
}
}

#if !defined(USE_VECTORED_EXCEPTION_HANDLING)
if (exception_code != EXCEPTION_BREAKPOINT) {
report_error(t, exception_code, pc, exception_record,
exceptionInfo->ContextRecord);
}
#endif
return EXCEPTION_CONTINUE_SEARCH;
}
bool should_report_error = (exception_code != EXCEPTION_BREAKPOINT);

#if defined(USE_VECTORED_EXCEPTION_HANDLING)
LONG WINAPI topLevelVectoredExceptionFilter(struct _EXCEPTION_POINTERS* exceptionInfo) {
PEXCEPTION_RECORD exceptionRecord = exceptionInfo->ExceptionRecord;
#if defined(_M_ARM64)
address pc = (address) exceptionInfo->ContextRecord->Pc;
#elif defined(_M_AMD64)
address pc = (address) exceptionInfo->ContextRecord->Rip;
#else
#error unknown architecture
should_report_error = should_report_error &&
FAILED(exception_code) &&
(exception_code != EXCEPTION_UNCAUGHT_CXX_EXCEPTION);
#endif

// Fast path for code part of the code cache
if (CodeCache::low_bound() <= pc && pc < CodeCache::high_bound()) {
return topLevelExceptionFilter(exceptionInfo);
}

// If the exception occurred in the codeCache, pass control
// to our normal exception handler.
CodeBlob* cb = CodeCache::find_blob(pc);
if (cb != nullptr) {
return topLevelExceptionFilter(exceptionInfo);
if (should_report_error) {
report_error(t, exception_code, pc, exception_record,
exceptionInfo->ContextRecord);
}

return EXCEPTION_CONTINUE_SEARCH;
}
#endif

#if defined(USE_VECTORED_EXCEPTION_HANDLING)
LONG WINAPI topLevelUnhandledExceptionFilter(struct _EXCEPTION_POINTERS* exceptionInfo) {
Expand Down Expand Up @@ -4488,7 +4466,7 @@ jint os::init_2(void) {
// Setup Windows Exceptions

#if defined(USE_VECTORED_EXCEPTION_HANDLING)
topLevelVectoredExceptionHandler = AddVectoredExceptionHandler(1, topLevelVectoredExceptionFilter);
topLevelVectoredExceptionHandler = AddVectoredExceptionHandler(1, topLevelExceptionFilter);
previousUnhandledExceptionFilter = SetUnhandledExceptionFilter(topLevelUnhandledExceptionFilter);
#endif

Expand Down
2 changes: 2 additions & 0 deletions src/hotspot/os/windows/os_windows.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,8 @@ class os::win32 {
// signal support
static void* install_signal_handler(int sig, signal_handler_t handler);
static void* user_handler();

static void context_set_pc(CONTEXT* uc, address pc);
};

#endif // OS_WINDOWS_OS_WINDOWS_HPP
64 changes: 64 additions & 0 deletions src/hotspot/os/windows/safefetch_static_windows.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
/*
* Copyright (c) 2022 SAP SE. All rights reserved.
* Copyright (c) 2022, 2025, 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.
*
*/


#include "os_windows.hpp"
#include "runtime/os.hpp"
#include "runtime/safefetch.hpp"
#include "utilities/globalDefinitions.hpp"

#ifdef SAFEFETCH_METHOD_STATIC_ASSEMBLY

// SafeFetch handling, static assembly style:
//
// SafeFetch32 and SafeFetchN are implemented via static assembly
// and live in os_cpu/xx_xx/safefetch_xx_xx.S

extern "C" char _SafeFetch32_continuation[];
extern "C" char _SafeFetch32_fault[];

#ifdef _LP64
extern "C" char _SafeFetchN_continuation[];
extern "C" char _SafeFetchN_fault[];
#endif // _LP64

bool handle_safefetch(int exception_code, address pc, void* context) {
CONTEXT* ctx = (CONTEXT*)context;
if (exception_code == EXCEPTION_ACCESS_VIOLATION && ctx != nullptr) {
if (pc == (address)_SafeFetch32_fault) {
os::win32::context_set_pc(ctx, (address)_SafeFetch32_continuation);
return true;
}
#ifdef _LP64
if (pc == (address)_SafeFetchN_fault) {
os::win32::context_set_pc(ctx, (address)_SafeFetchN_continuation);
return true;
}
#endif
}
return false;
}

#endif // SAFEFETCH_METHOD_STATIC_ASSEMBLY
4 changes: 4 additions & 0 deletions src/hotspot/os_cpu/windows_aarch64/os_windows_aarch64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,10 @@ intptr_t* os::fetch_bcp_from_context(const void* ucVoid) {
return reinterpret_cast<intptr_t*>(uc->REG_BCP);
}

void os::win32::context_set_pc(CONTEXT* uc, address pc) {
uc->Pc = (intptr_t)pc;
}

bool os::win32::get_frame_at_stack_banging_point(JavaThread* thread,
struct _EXCEPTION_POINTERS* exceptionInfo, address pc, frame* fr) {
PEXCEPTION_RECORD exceptionRecord = exceptionInfo->ExceptionRecord;
Expand Down
65 changes: 65 additions & 0 deletions src/hotspot/os_cpu/windows_aarch64/safefetch_windows_aarch64.S
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
;
; Copyright (c) 2022 SAP SE. All rights reserved.
; Copyright (c) 2022, 2025, 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.
;

; Support for int SafeFetch32(int* address, int defaultval);
;
; x0 : address
; w1 : defaultval

; needed to align function start to 4 byte
ALIGN 4
EXPORT _SafeFetch32_fault
EXPORT _SafeFetch32_continuation
EXPORT SafeFetch32_impl
AREA safefetch_text, CODE

SafeFetch32_impl
_SafeFetch32_fault
ldr w0, [x0]
ret

_SafeFetch32_continuation
mov x0, x1
ret

; Support for intptr_t SafeFetchN(intptr_t* address, intptr_t defaultval);
;
; x0 : address
; x1 : defaultval

ALIGN 4
EXPORT _SafeFetchN_fault
EXPORT _SafeFetchN_continuation
EXPORT SafeFetchN_impl

SafeFetchN_impl
_SafeFetchN_fault
ldr x0, [x0]
ret

_SafeFetchN_continuation
mov x0, x1
ret

END
4 changes: 2 additions & 2 deletions src/hotspot/share/runtime/safefetch.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@
// Safefetch allows to load a value from a location that's not known
// to be valid. If the load causes a fault, the error value is returned.

#ifdef _WIN32
// Windows uses Structured Exception Handling
#if defined(_WIN32) && !defined(_M_ARM64)
// Windows x86_64 uses Structured Exception Handling
#include "safefetch_windows.hpp"
#elif defined(ZERO) || defined (_AIX)
// These platforms implement safefetch via Posix sigsetjmp/longjmp.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ public void testNativeExceptionReporting() throws Exception {
assertTrue(Files.exists(hsErrPath));

Pattern[] positivePatterns = {
Pattern.compile(".*Internal Error \\(0x2a\\).*")
Pattern.compile(".*Internal Error \\(0xdeadbeef\\).*")
};
HsErrFileUtils.checkHsErrFileContent(hsErrFile, positivePatterns, null, true /* check end marker */, false /* verbose */);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,10 @@

#include <Windows.h>

const DWORD EX_CODE = 42;
// Use an exception code that causes the Windows FAILED() macro to return true.
// Windows AArch64 uses vectored exception handling and therefore runs error
// reporting only for failed exception codes.
const DWORD EX_CODE = 0xdeadbeef;

JNIEXPORT void JNICALL Java_UncaughtNativeExceptionTest_00024Crasher_throwException(JNIEnv* env, jclass cls) {
RaiseException(EX_CODE, EXCEPTION_NONCONTINUABLE, 0, NULL);
Expand Down