blob: 89dc1336e3d76eca4367e28dd685f70dbe54a19c [file] [log] [blame]
// 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
}