summaryrefslogtreecommitdiff
path: root/src/runtime/traceback_windows.go
diff options
context:
space:
mode:
Diffstat (limited to 'src/runtime/traceback_windows.go')
-rw-r--r--src/runtime/traceback_windows.go63
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
+}