mirror of
https://github.com/golang/go
synced 2024-09-24 23:20:12 -06:00
runtime: fix traceback on Windows
The exception handler runs on the ordinary g stack, and the stack copier is now trying to do a traceback across it. That's never been needed before, so it was unimplemented. Implement it, in all its ugliness. Fixes windows/amd64 build. TBR=khr CC=golang-codereviews https://golang.org/cl/71030043
This commit is contained in:
parent
871698136d
commit
0a3bd045f5
@ -8,9 +8,16 @@
|
||||
#include "arch_GOARCH.h"
|
||||
#include "malloc.h"
|
||||
#include "funcdata.h"
|
||||
#ifdef GOOS_windows
|
||||
#include "defs_GOOS_GOARCH.h"
|
||||
#endif
|
||||
|
||||
void runtime·sigpanic(void);
|
||||
|
||||
#ifdef GOOS_windows
|
||||
void runtime·sigtramp(void);
|
||||
#endif
|
||||
|
||||
// This code is also used for the 386 tracebacks.
|
||||
// Use uintptr for an appropriate word-sized integer.
|
||||
|
||||
@ -95,8 +102,50 @@ runtime·gentraceback(uintptr pc0, uintptr sp0, uintptr lr0, G *gp, int32 skip,
|
||||
frame.fn = f;
|
||||
continue;
|
||||
}
|
||||
|
||||
f = frame.fn;
|
||||
|
||||
#ifdef GOOS_windows
|
||||
// Windows exception handlers run on the actual g stack (there is room
|
||||
// dedicated to this below the usual "bottom of stack"), not on a separate
|
||||
// stack. As a result, we have to be able to unwind past the exception
|
||||
// handler when called to unwind during stack growth inside the handler.
|
||||
// Recognize the frame at the call to sighandler in sigtramp and unwind
|
||||
// using the context argument passed to the call. This is awful.
|
||||
if(f != nil && f->entry == (uintptr)runtime·sigtramp && frame.pc > f->entry) {
|
||||
Context *r;
|
||||
|
||||
// Invoke callback so that stack copier sees an uncopyable frame.
|
||||
if(callback != nil) {
|
||||
frame.argp = nil;
|
||||
frame.arglen = 0;
|
||||
if(!callback(&frame, v))
|
||||
return n;
|
||||
}
|
||||
r = (Context*)((uintptr*)frame.sp)[1];
|
||||
#ifdef GOARCH_amd64
|
||||
frame.pc = r->Rip;
|
||||
frame.sp = r->Rsp;
|
||||
#else
|
||||
frame.pc = r->Eip;
|
||||
frame.sp = r->Esp;
|
||||
#endif
|
||||
frame.lr = 0;
|
||||
frame.fp = 0;
|
||||
frame.fn = nil;
|
||||
if(printing && runtime·showframe(nil, gp))
|
||||
runtime·printf("----- exception handler -----\n");
|
||||
f = runtime·findfunc(frame.pc);
|
||||
if(f == nil) {
|
||||
runtime·printf("runtime: unknown pc %p after exception handler\n", frame.pc);
|
||||
if(callback != nil)
|
||||
runtime·throw("unknown pc");
|
||||
}
|
||||
frame.fn = f;
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Found an actual function.
|
||||
// Derive frame pointer and link register.
|
||||
if(frame.fp == 0) {
|
||||
|
Loading…
Reference in New Issue
Block a user