JDK-8263512 : [macos_aarch64] issues with calling va_args functions from invoke_native
  • Type: Bug
  • Component: hotspot
  • Sub-Component: runtime
  • Affected Version: 17
  • Priority: P3
  • Status: Resolved
  • Resolution: Fixed
  • OS: os_x
  • CPU: aarch64
  • Submitted: 2021-03-12
  • Updated: 2021-06-11
  • Resolved: 2021-06-05
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 17
17 b26Fixed
Related Reports
Relates :  
Relates :  
Relates :  
Relates :  
Relates :  
Sub Tasks
JDK-8265112 :  
Description
Testing https://github.com/openjdk/jdk/pull/2200 reveals this crash in java/foreign/StdLibTest.java
java/foreign/TestVarArgs.java
java/foreign/valist/VaListTest.java
The root cause of all three crashes is the same

snipets of stack traces:

StdLibTest.java

Current thread (0x000000012d009200):  JavaThread "MainThread" [_thread_in_native, id=24579, stack(0x000000016e190000,0x000000016e393000)]

Stack: [0x000000016e190000,0x000000016e393000],  sp=0x000000016e390480,  free space=2049k
Native frames: (J=compiled Java code, A=aot compiled Java code, j=interpreted, Vv=VM code, C=native code)
C  [libsystem_platform.dylib+0xfa4]  _platform_strlen+0x4
C  [libsystem_c.dylib+0x6796c]  __v2printf+0x194
C  [libsystem_c.dylib+0x42c4c]  vfprintf_l+0x44
C  [libsystem_c.dylib+0x411b8]  printf+0x54
C  0x047c80011209f27c
V  [libjvm.dylib+0x974590]  ProgrammableInvoker::invoke_native(void (*)(unsigned char*), unsigned char*, JavaThread*)+0xb8
V  [libjvm.dylib+0x97473c]  PI_invokeNative+0x104

printf is va_arg function as we all know.

VaListTest.java

Current thread (0x000000015c04dc00):  JavaThread "MainThread" [_thread_in_native, id=39939, stack(0x0000000171644000,0x0000000171847000)]

Stack: [0x0000000171644000,0x0000000171847000],  sp=0x0000000171844830,  free space=2050k
Native frames: (J=compiled Java code, A=aot compiled Java code, j=interpreted, Vv=VM code, C=native code)
C  [libVaList.dylib+0x3ac4]  sumHugeStruct+0x4
V  [libjvm.dylib+0x974590]  ProgrammableInvoker::invoke_native(void (*)(unsigned char*), unsigned char*, JavaThread*)+0xb8
V  [libjvm.dylib+0x97473c]  PI_invokeNative+0x104
j  jdk.internal.foreign.abi.ProgrammableInvoker.invokeNative(JJ)V+0 jdk.incubator.foreign@17-internal

where sumHugeStruct is va_arg function:

EXPORT long long sumHugeStruct(va_list list) {
    HugePoint point = va_arg(list, HugePoint);
    return point.x + point.y + point.z;
}



va_args work diferently on macos_aarch64 then on intel
fixed part is passed in regs/on stack
variable part is passed on stack always

https://developer.apple.com/documentation/apple-silicon/addressing-architectural-differences-in-your-macos-code

"On arm64, the compiler always places variadic parameters on the stack, regardless of whether registers are available. If you implement a function with fixed parameters, but redeclare it with variadic parameters, the mismatch causes unexpected behavior at runtime."
Comments
Changeset: 76b54a19 Author: Nick Gasson <ngasson@openjdk.org> Date: 2021-06-04 23:55:12 +0000 URL: https://git.openjdk.java.net/jdk/commit/76b54a19955cd93f071cf1fb45c6d01bb57b84eb
05-06-2021

We have integrated https://git.openjdk.java.net/jdk/pull/3699 (JEP-412)
02-06-2021

@Monica OK sure. There's a work-in-progress PR here to split up the AArch64 ABI backend into per-OS variants, but it's paused until the latest Panama JEP is integrated: https://github.com/openjdk/jdk/pull/3617
19-05-2021

+1 to @Maurizio. Also @Nick, we can enable the Arm64 + Windows (and Linux and macOS) testing at our end.
18-05-2021

I believe we should introduce a new enum constant, yes. That is the more robust solution going forward. Internally, the linkers can find ways to reuse code as required - but they are different linkers. I believe, for instance, that two different linkers on ARM64 might be able to use the same call arranger with different flavors - but the enum constant is needed anyway to: * get the right CLinker instance * get the right layout types (e.g. ARM64/Windows will still have C_LONG be 32 bits I think?) * implement right flavor of VaList * ... So, yes we need an enum constant for Arm64/MacOs, and, I think another one for Arm64/Windows.
20-04-2021

Maurizio, do you think we should introduce a completely separate MacAArch64 CABI enum value or just add a "flavor" argument to the existing AArch64Linker? The Linux AArch64 CallArranger works mostly as-is except for some differences in how < 8-byte types are packed on the stack. The va_list implementation is different - I have that working now using a slightly modified WinVaList. I don't have an Arm64 Windows environment to test at moment, but from the document below, it also appears to use the same simplified va_list structure as macOS: https://docs.microsoft.com/en-us/cpp/build/arm64-windows-abi-conventions
20-04-2021

yeah, variadic args are always on stack, fixed args follow the usual calling convention
19-04-2021

Thanks for filing this - so, it seems like ARM64/MacOs is using similar way to pass variadic arguments as Windows? E.g. everything passed on the stack, and va_list decays to a char* ? If that's the case we need a different VaList implementation, as well as different CallArranger classification - note that CLinker exposes a method "asVarArg" which takes a layout and returns a layout augmented with a variadic attribute, so that classification can occur correctly. Seems like similar thing is needed here. More generally, right now the implementation assumes that Aarch64 == Aarch64/Linux. I think we need to break up the implementation to have different packages - windows, linux, macos - to support slightly different calling conventions on these OSs.
19-04-2021

The root cause looks the same for me (wrong calling convention in Foreign API implementation), but I had no chance to look closer. @Nick, then I'm happily assigning this to you :) Feel free to ping us, if you'd see something interesting compared to Apple ABI in the interpreter. E.g. it does not need to support va_args, in contrast with the Foreign API.
15-04-2021

I think we need to extend jdk.internal.foreign.abi.aarch64.CallArranger to know about the differences between Apple's ABI and the standard AArch64 ABI. Towards the end of this page there's a summary of points where the ABI differs: https://developer.apple.com/documentation/xcode/writing_arm64_code_for_apple_platforms @Anton are you planning to work on this? I'm happy to do it if you like as I ported the panama-foreign APIs to AArch64 originally.
15-04-2021

These new apis were introduced by JEP-389
16-03-2021

ILW = HLM = P3
16-03-2021