diff options
Diffstat (limited to 'src/runtime/traceback_windows.go')
-rw-r--r-- | src/runtime/traceback_windows.go | 63 |
1 files changed, 63 insertions, 0 deletions
diff --git a/src/runtime/traceback_windows.go b/src/runtime/traceback_windows.go new file mode 100644 index 000000000..89dc1336e --- /dev/null +++ b/src/runtime/traceback_windows.go @@ -0,0 +1,63 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package runtime + +import "unsafe" + +// sigtrampPC is the PC at the beginning of the jmpdefer assembly function. +// The traceback needs to recognize it on link register architectures. +var sigtrampPC uintptr + +func sigtramp() + +func init() { + sigtrampPC = funcPC(sigtramp) + systraceback = traceback_windows +} + +func traceback_windows(f *_func, frame *stkframe, gp *g, printing bool, callback func(*stkframe, unsafe.Pointer) bool, v unsafe.Pointer) (changed, aborted bool) { + // The main traceback thinks it has found a function. Check this. + + // 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 == sigtrampPC && frame.pc > f.entry { + var r *context + // Invoke callback so that stack copier sees an uncopyable frame. + if callback != nil { + frame.continpc = frame.pc + frame.argp = 0 + frame.arglen = 0 + if !callback(frame, v) { + aborted = true + return + } + } + r = (*context)(unsafe.Pointer(frame.sp + ptrSize)) + frame.pc = contextPC(r) + frame.sp = contextSP(r) + frame.lr = 0 + frame.fp = 0 + frame.fn = nil + if printing && showframe(nil, gp) { + print("----- exception handler -----\n") + } + f = findfunc(frame.pc) + if f == nil { + print("runtime: unknown pc ", hex(frame.pc), " after exception handler\n") + if callback != nil { + gothrow("unknown pc") + } + } + frame.fn = f + changed = true + return + } + + return +} |