mirror of
https://github.com/golang/go
synced 2024-11-12 06:20:22 -07: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 "arch_GOARCH.h"
|
||||||
#include "malloc.h"
|
#include "malloc.h"
|
||||||
#include "funcdata.h"
|
#include "funcdata.h"
|
||||||
|
#ifdef GOOS_windows
|
||||||
|
#include "defs_GOOS_GOARCH.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
void runtime·sigpanic(void);
|
void runtime·sigpanic(void);
|
||||||
|
|
||||||
|
#ifdef GOOS_windows
|
||||||
|
void runtime·sigtramp(void);
|
||||||
|
#endif
|
||||||
|
|
||||||
// This code is also used for the 386 tracebacks.
|
// This code is also used for the 386 tracebacks.
|
||||||
// Use uintptr for an appropriate word-sized integer.
|
// 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;
|
frame.fn = f;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
f = frame.fn;
|
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.
|
// Found an actual function.
|
||||||
// Derive frame pointer and link register.
|
// Derive frame pointer and link register.
|
||||||
if(frame.fp == 0) {
|
if(frame.fp == 0) {
|
||||||
|
Loading…
Reference in New Issue
Block a user