8387792: Enable PAC-RET for VM code on Windows/ARM64

Reviewed-by: haosun, erikj
This commit is contained in:
Ashay Rane
2026-08-13 22:21:44 +00:00
committed by David Holmes
parent 993f7b35cf
commit aa0fbef91a
7 changed files with 92 additions and 14 deletions
+7 -5
View File
@@ -366,11 +366,13 @@ free disk space is required.</p>
also possible to use <a href="#cross-compiling">cross-compiling</a>.</p>
<h4 id="branch-protection">Branch Protection</h4>
<p>In order to use Branch Protection features in the VM,
<code>--enable-branch-protection</code> must be used. This option
requires C++ compiler support (GCC 9.1.0+ or Clang 10+). The resulting
build can be run on both machines with and without support for branch
protection in hardware. Branch Protection is only supported for Linux
targets.</p>
<code>--enable-branch-protection</code> must be used. This option requires C++
compiler support for <code>-mbranch-protection=standard</code> in GCC 9.1.0+ or
Clang 10+ on Linux/AArch64 or for <code>/guard:signret</code> in Visual Studio
2019+ on Windows/ARM64. The resulting build can be run on both machines with and
without support for branch protection in hardware. Branch Protection is fully
supported for the Linux/AArch64 target and only partially supported for the
Windows/ARM64 targets.</p>
<h3 id="building-on-32-bit-arm">Building on 32-bit ARM</h3>
<p>This is not recommended. Instead, see the section on <a
href="#cross-compiling">Cross-compiling</a>.</p>
+5 -3
View File
@@ -171,9 +171,11 @@ possible to use [cross-compiling](#cross-compiling).
In order to use Branch Protection features in the VM,
`--enable-branch-protection` must be used. This option requires C++ compiler
support (GCC 9.1.0+ or Clang 10+). The resulting build can be run on both
machines with and without support for branch protection in hardware. Branch
Protection is only supported for Linux targets.
support for `-mbranch-protection=standard` in GCC 9.1.0+ or Clang 10+ on
Linux/AArch64 or for `/guard:signret` in Visual Studio 2019+ on Windows/ARM64.
The resulting build can be run on both machines with and without support for
branch protection in hardware. Branch Protection is fully supported for the
Linux/AArch64 target and only partially supported for the Windows/ARM64 target.
### Building on 32-bit ARM
+13 -3
View File
@@ -945,11 +945,21 @@ AC_DEFUN_ONCE([FLAGS_SETUP_BRANCH_PROTECTION],
[
# Is branch protection available?
BRANCH_PROTECTION_AVAILABLE=false
BRANCH_PROTECTION_FLAG="-mbranch-protection=standard"
BRANCH_PROTECTION_CFLAG=""
BRANCH_PROTECTION_ASFLAG=""
if test "x$OPENJDK_TARGET_CPU" = xaarch64; then
if test "x$TOOLCHAIN_TYPE" = xgcc || test "x$TOOLCHAIN_TYPE" = xclang; then
FLAGS_COMPILER_CHECK_ARGUMENTS(ARGUMENT: [$BRANCH_PROTECTION_FLAG],
BRANCH_PROTECTION_CFLAG="-mbranch-protection=standard"
# The GCC/Clang assembler accepts the same flag as the compiler.
BRANCH_PROTECTION_ASFLAG="$BRANCH_PROTECTION_CFLAG"
FLAGS_COMPILER_CHECK_ARGUMENTS(ARGUMENT: [$BRANCH_PROTECTION_CFLAG],
IF_TRUE: [BRANCH_PROTECTION_AVAILABLE=true])
elif test "x$TOOLCHAIN_TYPE" = xmicrosoft; then
BRANCH_PROTECTION_CFLAG="/guard:signret"
# MSVC's assembler does not support branch protection flags, so
# BRANCH_PROTECTION_ASFLAG is intentionally left empty.
FLAGS_COMPILER_CHECK_ARGUMENTS(ARGUMENT: [$BRANCH_PROTECTION_CFLAG],
IF_TRUE: [BRANCH_PROTECTION_AVAILABLE=true])
fi
fi
@@ -957,5 +967,5 @@ AC_DEFUN_ONCE([FLAGS_SETUP_BRANCH_PROTECTION],
UTIL_ARG_ENABLE(NAME: branch-protection, DEFAULT: false,
RESULT: BRANCH_PROTECTION_ENABLED, AVAILABLE: $BRANCH_PROTECTION_AVAILABLE,
DESC: [enable branch protection when compiling C/C++],
IF_ENABLED: [BRANCH_PROTECTION_CFLAGS=$BRANCH_PROTECTION_FLAG])
IF_ENABLED: [BRANCH_PROTECTION_CFLAGS=$BRANCH_PROTECTION_CFLAG])
])
+1 -1
View File
@@ -211,7 +211,7 @@ AC_DEFUN([FLAGS_SETUP_ASFLAGS_CPU_DEP],
fi
if test "x$BRANCH_PROTECTION_ENABLED" = "xtrue"; then
$2JVM_ASFLAGS="${$2JVM_ASFLAGS} $BRANCH_PROTECTION_FLAG"
$2JVM_ASFLAGS="${$2JVM_ASFLAGS} $BRANCH_PROTECTION_ASFLAG"
fi
AC_SUBST($2JVM_ASFLAGS)
+16
View File
@@ -79,6 +79,9 @@
#include "utilities/population_count.hpp"
#include "utilities/vmError.hpp"
#include "windbghelp.hpp"
#if defined(_M_ARM64)
#include CPU_HEADER(pauth)
#endif
#if INCLUDE_JFR
#include "jfr/jfrEvents.hpp"
#include "jfr/support/jfrNativeLibraryLoadEvent.hpp"
@@ -6637,6 +6640,19 @@ bool os::win32::platform_print_native_stack(outputStream* st, const void* contex
int count = 0;
address lastpc_internal = 0;
while (count++ < StackPrintLimit) {
#if defined(_M_ARM64)
// On Windows/ARM64, when the CPU is using authenticated pointers, return
// addresses are signed. Unfortunately, `StackWalk64()` does not strip the
// pointer signature, so we need to do this ourself. Since stripping the
// signature is an idempotent operation, we don't need to guard this call
// based on whether pointer authentication is enabled.
address original = (address)stk.AddrPC.Offset;
address stripped = pauth_strip_pointer(original);
stk.AddrPC.Offset = (DWORD64)(uintptr_t)stripped;
// We updated the stack frame's PC, so keep the context's PC in sync.
ctx.Pc = stk.AddrPC.Offset;
#endif
intptr_t* sp = (intptr_t*)stk.AddrStack.Offset;
intptr_t* fp = (intptr_t*)stk.AddrFrame.Offset; // NOT necessarily the same as ctx.Rbp!
address pc = (address)stk.AddrPC.Offset;
@@ -0,0 +1,47 @@
;
; Copyright (c) 2026, Microsoft 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.
;
; Remove the AArch64 pointer signature from the pointer argument
;
; Both XPACI and XPACLRI can get the job done, with XPACI being more
; convenient since it can work with any general purpose register. However,
; unlike XPACI, XPACLRI can be encoded using hint instructions, thus letting
; us compile this function using older compilers.
;
; Since XPACLRI implicitly uses the link register (x30) and we instead want
; to remove the signature from the function argument (in x0), we temporarily
; save x30 before restoring it at the end.
ALIGN 4
EXPORT pauth_drop_signature_win_arm64
AREA pauth_text, CODE
pauth_drop_signature_win_arm64
mov x9, x30
mov x30, x0
hint #7
mov x0, x30
mov x30, x9
ret
END
@@ -28,9 +28,10 @@
// OS specific Support for ROP Protection in VM code.
// For more details on PAC see pauth_aarch64.hpp.
extern "C" address pauth_drop_signature_win_arm64(address p);
inline address pauth_strip_pointer(address ptr) {
// No PAC support in windows as of yet.
return ptr;
return pauth_drop_signature_win_arm64(ptr);
}
inline address pauth_sign_return_address(address ret_addr) {