// Called by sigtramp from Windows VEH handler. // Return value signals whether the exception has been handled (EXCEPTION_CONTINUE_EXECUTION) // or should be made available to other handlers in the chain (EXCEPTION_CONTINUE_SEARCH). uint32 runtime·exceptionhandler(ExceptionRecord *info, Context *r, G *gp) { uintptr *sp; if(!runtime·isgoexception(info, r)) return EXCEPTION_CONTINUE_SEARCH; // Make it look like a call to the signal func. // Have to pass arguments out of band since // augmenting the stack frame would break // the unwinding code. gp->sig = info->ExceptionCode; gp->sigcode0 = info->ExceptionInformation[0]; gp->sigcode1 = info->ExceptionInformation[1]; gp->sigpc = r->Eip; // Only push runtime·sigpanic if r->eip != 0. // If r->eip == 0, probably panicked because of a // call to a nil func. Not pushing that onto sp will // make the trace look like a call to runtime·sigpanic instead. // (Otherwise the trace will end at runtime·sigpanic and we // won't get to see who faulted.) if(r->Eip != 0) { sp = (uintptr*)r->Esp; *--sp = r->Eip; r->Esp = (uintptr)sp; } r->Eip = (uintptr)runtime·sigpanic; return EXCEPTION_CONTINUE_EXECUTION; }
// It seems Windows searches ContinueHandler's list even // if ExceptionHandler returns EXCEPTION_CONTINUE_EXECUTION. // firstcontinuehandler will stop that search, // if exceptionhandler did the same earlier. uint32 runtime·firstcontinuehandler(ExceptionRecord *info, Context *r, G *gp) { USED(gp); if(!runtime·isgoexception(info, r)) return EXCEPTION_CONTINUE_SEARCH; return EXCEPTION_CONTINUE_EXECUTION; }