JVM crashes in JIT compiled code without hs_err_pid file
Alexandr Miloslavskiy
alexandr.miloslavskiy at syntevo.com
Sun Feb 19 15:57:21 UTC 2023
Hi Thomas,
> someone in the process may have established a competing signal
handler via AddVectoredExceptionHandler
I tested it and you were right, if 'AddVectoredExceptionHandler()' is
present then it's called instead of 'RtlAddFunctionTable()'.
See attached code for a demo.
I'll try to figure if this was the case for the customer.
> Possibility 2: registering code cache did not work
Sounds unlikely, because in the dump, I can see that it's registered
(when a dump is created, it also collects all function tables). Also, in
such case, application wouldn't run longer than a second or two before
crashing.
-------------- next part --------------
#include <windows.h>
#include <stdio.h>
#include <stdint.h>
#pragma comment(linker, "/SUBSYSTEM:console /ENTRY:mainCRTStartup")
LONG FunctionableHandler(IN PEXCEPTION_RECORD ExceptionRecord, IN ULONG64 EstablisherFrame, IN OUT PCONTEXT ContextRecord, IN OUT PDISPATCHER_CONTEXT DispatcherContext)
{
printf(
"FunctionableHandler: exception %08X at %p\n",
ExceptionRecord->ExceptionCode,
ExceptionRecord->ExceptionAddress
);
TerminateProcess(GetCurrentProcess(), 0);
return 0;
}
LONG VectoredExceptionHandler(_EXCEPTION_POINTERS *ExceptionInfo)
{
printf(
"VectoredExceptionHandler: exception %08X at %p\n",
ExceptionInfo->ExceptionRecord->ExceptionCode,
ExceptionInfo->ExceptionRecord->ExceptionAddress
);
TerminateProcess(GetCurrentProcess(), 0);
return 0;
}
// Same as in OpenJDK
typedef unsigned char UBYTE;
typedef struct _UNWIND_INFO_EH_ONLY {
UBYTE Version : 3;
UBYTE Flags : 5;
UBYTE SizeOfProlog;
UBYTE CountOfCodes;
UBYTE FrameRegister : 4;
UBYTE FrameOffset : 4;
union {
OPTIONAL ULONG ExceptionHandler;
OPTIONAL ULONG FunctionEntry;
};
OPTIONAL ULONG ExceptionData[1];
} UNWIND_INFO_EH_ONLY, *PUNWIND_INFO_EH_ONLY;
struct CodePageContents
{
UNWIND_INFO_EH_ONLY unwind;
RUNTIME_FUNCTION runtimeFunction;
uint8_t exceptionHandlerCode[16];
uint8_t jitCode[64];
};
typedef void (*PlainFunction)();
PlainFunction createJitCode()
{
const uint32_t codePageSize = 0x1000;
CodePageContents* memoryPage = (CodePageContents*)VirtualAlloc(0, codePageSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
// Set up exception handling
{
UNWIND_INFO_EH_ONLY* punwind = &memoryPage->unwind;
punwind->Version = 1;
punwind->Flags = UNW_FLAG_EHANDLER;
punwind->SizeOfProlog = 0;
punwind->CountOfCodes = 0;
punwind->FrameRegister = 0;
punwind->FrameOffset = 0;
punwind->ExceptionHandler = (ULONG)((char*)memoryPage->exceptionHandlerCode - (char*)memoryPage);
punwind->ExceptionData[0] = 0;
RUNTIME_FUNCTION* prt = &memoryPage->runtimeFunction;
prt->BeginAddress = 0;
prt->EndAddress = codePageSize;
prt->UnwindData = (DWORD)((char*)&memoryPage->unwind - (char*)memoryPage);
RtlAddFunctionTable(prt, 1, (DWORD64)memoryPage);
uint8_t* code = memoryPage->exceptionHandlerCode;
// mov rax, FunctionableHandler
code[0] = 0x48;
code[1] = 0xb8;
code += 2;
*(uint64_t*)code = (uint64_t)FunctionableHandler;
code += 8;
// jmp rax
code[0] = 0xff;
code[1] = 0xe0;
}
// "JIT" code
{
uint8_t* code = memoryPage->jitCode;
// xor eax, eax
code[0] = 0x31;
code[1] = 0xc0;
code += 2;
// mov eax,DWORD PTR [eax]
code[0] = 0x67;
code[1] = 0x8b;
code[2] = 0x00;
code += 3;
}
return (PlainFunction)&memoryPage->jitCode;
}
int main()
{
PlainFunction function = createJitCode();
// Comment/uncomment as needed
AddVectoredExceptionHandler(TRUE, VectoredExceptionHandler);
// Run "jit" code and crash
function();
return 0;
}
More information about the hotspot-dev
mailing list