package com.oracle.svm.core.windows;
import static com.oracle.svm.core.annotate.RestrictHeapAccess.Access.NO_ALLOCATION;
import static com.oracle.svm.core.annotate.RestrictHeapAccess.Access.NO_HEAP_ACCESS;
import org.graalvm.nativeimage.ImageSingletons;
import org.graalvm.nativeimage.c.function.CEntryPoint;
import org.graalvm.nativeimage.c.function.CEntryPointLiteral;
import org.graalvm.nativeimage.c.function.CFunctionPointer;
import org.graalvm.nativeimage.hosted.Feature;
import com.oracle.svm.core.SubstrateSegfaultHandler;
import com.oracle.svm.core.annotate.AutomaticFeature;
import com.oracle.svm.core.annotate.RestrictHeapAccess;
import com.oracle.svm.core.annotate.Uninterruptible;
import com.oracle.svm.core.c.function.CEntryPointOptions;
import com.oracle.svm.core.c.function.CEntryPointOptions.NoEpilogue;
import com.oracle.svm.core.c.function.CEntryPointOptions.NoPrologue;
import com.oracle.svm.core.c.function.CEntryPointOptions.NotIncludedAutomatically;
import com.oracle.svm.core.c.function.CEntryPointOptions.Publish;
import com.oracle.svm.core.util.VMError;
import com.oracle.svm.core.windows.headers.ErrHandlingAPI;
@AutomaticFeature
class WindowsSubstrateSegfaultHandlerFeature implements Feature {
@Override
public void afterRegistration(AfterRegistrationAccess access) {
ImageSingletons.add(SubstrateSegfaultHandler.class, new WindowsSubstrateSegfaultHandler());
}
}
class WindowsSubstrateSegfaultHandler extends SubstrateSegfaultHandler {
@Override
protected void install() {
if (ErrHandlingAPI.AddVectoredContinueHandler(0, HANDLER_LITERAL.getFunctionPointer()).isNull()) {
VMError.shouldNotReachHere("SubstrateSegfaultHandler installation failed.");
}
}
private static final CEntryPointLiteral<CFunctionPointer> HANDLER_LITERAL = CEntryPointLiteral.create(WindowsSubstrateSegfaultHandler.class,
"handler", ErrHandlingAPI.EXCEPTION_POINTERS.class);
@CEntryPoint
@CEntryPointOptions(prologue = NoPrologue.class, epilogue = NoEpilogue.class, publishAs = Publish.SymbolOnly, include = NotIncludedAutomatically.class)
@Uninterruptible(reason = "Must be uninterruptible until we get immune to safepoints.")
@RestrictHeapAccess(access = NO_HEAP_ACCESS, reason = "We have yet to enter the isolate.")
private static int handler(ErrHandlingAPI.EXCEPTION_POINTERS exceptionInfo) {
ErrHandlingAPI.EXCEPTION_RECORD exceptionRecord = exceptionInfo.ExceptionRecord();
if (exceptionRecord.ExceptionCode() != ErrHandlingAPI.EXCEPTION_ACCESS_VIOLATION()) {
return ErrHandlingAPI.EXCEPTION_CONTINUE_SEARCH();
}
ErrHandlingAPI.CONTEXT context = exceptionInfo.ContextRecord();
if (tryEnterIsolate(context)) {
dump(context);
throw shouldNotReachHere();
}
return ErrHandlingAPI.EXCEPTION_CONTINUE_SEARCH();
}
@Uninterruptible(reason = "Called from uninterruptible code.")
@RestrictHeapAccess(access = NO_ALLOCATION, reason = "Must not allocate in segfault handler.", overridesCallers = true)
private static RuntimeException shouldNotReachHere() {
return VMError.shouldNotReachHere();
}
}