Testing Variadics on Windows ABI
I’ve been testing some changes based on feedback from PR 8295290: Add Windows ARM64 ABI support to the Foreign Function & Memory API · Pull Request #754 · openjdk/panama-foreign (github.com). I’m using my scratchpad repo to run tests against my local build. The java commands generates upcall and downcall log files. I (re?-)discovered that hsdis is required to disassemble the instructions when I accidentally built without it.
cd scratchpad/compilers/tests/aarch64/abi/intrinsics/
cp /d/java/forks/panama-foreign/build/windows-x86_64-server-slowdebug/support/test/jdk/jtreg/native/lib/Intrinsics.dll .
/d/java/forks/panama-foreign/build/windows-x86_64-server-slowdebug/jdk/bin/javac -g --enable-preview --release 20 MinimizedTestIntrinsics.java
/d/java/forks/panama-foreign/build/windows-x86_64-server-slowdebug/jdk/bin/java.exe --enable-preview -Xlog:foreign+downcall=trace:file=downcall.txt::filecount=0 -Xlog:foreign+upcall=trace:file=upcall.txt::filecount=0 MinimizedTestIntrinsics
The MinimizedTestIntrinsics test works just fine. The VarArgs test is the problematic one.
cp /d/java/forks/panama-foreign/build/windows-x86_64-server-slowdebug/support/test/jdk/jtreg/native/lib/varargs.dll .
/d/java/forks/panama-foreign/build/windows-x86_64-server-slowdebug/jdk/bin/javac -g --enable-preview --release 20 MinimizedTestVarArgs.java
/d/java/forks/panama-foreign/build/windows-x86_64-server-slowdebug/jdk/bin/java.exe --enable-preview -Xlog:foreign+downcall=trace:file=downcall.txt::filecount=0 -Xlog:foreign+upcall=trace:file=upcall.txt::filecount=0 MinimizedTestVarArgs
Since both upcall and downcall logs are generated, debugging the JDK in Visual Studio can hit the breakpoint in panama-foreign/downcallLinker_x86_64.cpp at 617198dbbbbed1a7fdb9fdfe981ca09fec8bcf5b (github.com) as expected. However, Visual Studio doesn’t hit the breakpoint in panama-foreign/libVarArgs.c at 617198dbbbbed1a7fdb9fdfe981ca09fec8bcf5b (github.com). Switching back to WinDbg shows that the downcall actually happens.
bp varargs!varargs
Disassemble the VarArgs function to simplify stepping through the code (this enables me to interpret the assembly instructions, mapping them to the source code):
cd build\windows-aarch64-server-slowdebug\support\test\jdk\jtreg\native\support\libVarArgs\
dumpbin /disasm /out:libVarArgs.asm libVarArgs.obj
dumpbin /all /out:libVarArgs.txt libVarArgs.obj
Now stepping through the code, we observe that the process terminates.
Here’s a breakdown of the VarArgs code on x64:
...
0053: EB 0A jmp 000000000000005F
// i++
0055: 8B 44 24 28 mov eax,dword ptr [rsp+28h]
0059: FF C0 inc eax
005B: 89 44 24 28 mov dword ptr [rsp+28h],eax
// load num
005F: 8B 84 24 C8 06 00 mov eax,dword ptr [rsp+6C8h]
00
// i < num
0066: 39 44 24 28 cmp dword ptr [rsp+28h],eax
// jump to last line of function: va_end(a_list)
006A: 0F 8D D1 15 00 00 jge 0000000000001641
// load i into rax
0070: 48 63 44 24 28 movsxd rax,dword ptr [rsp+28h]
0075: 48 8B 8C 24 C0 06 mov rcx,qword ptr [rsp+6C0h]
00 00
007D: 48 8B 49 08 mov rcx,qword ptr [rcx+8]
// load id into eax
0081: 8B 04 81 mov eax,dword ptr [rcx+rax*4]
0084: 89 44 24 3C mov dword ptr [rsp+3Ch],eax
0088: 8B 44 24 3C mov eax,dword ptr [rsp+3Ch]
008C: 89 44 24 38 mov dword ptr [rsp+38h],eax
// There are 88 (0x58) enums.
0090: 83 7C 24 38 57 cmp dword ptr [rsp+38h],57h
0095: 0F 87 96 15 00 00 ja 0000000000001631
009B: 48 63 44 24 38 movsxd rax,dword ptr [rsp+38h]
00A0: 48 8D 0D 00 00 00 lea rcx,[__ImageBase]
00
00A7: 8B 84 81 00 00 00 mov eax,dword ptr $LN97[rcx+rax*4]
00
00AE: 48 03 C1 add rax,rcx
00B1: FF E0 jmp rax
...
1631: B9 FF FF FF FF mov ecx,0FFFFFFFFh
1636: FF 15 00 00 00 00 call qword ptr [__imp_exit]
163C: E9 14 EA FF FF jmp 0000000000000055
From the assembly, what appears to be happening is the switch statement is immediately jumping to the default case, which calls exit(-1). So, pretty simple test failure. Why did I think it was a crash? I assumed that a crash was the only reason the JVM would terminate prematurely but this was actually a clean exit, by design. Perhaps an assertion failure would have made the issue more visible.
Leave a Reply