1 // Copyright 2018 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
12 debugCallSystemStack = "executing on Go runtime stack"
13 debugCallUnknownFunc = "call from unknown function"
14 debugCallRuntime = "call from within the Go runtime"
15 debugCallUnsafePoint = "call not at safe point"
19 func debugCallPanicked(val interface{})
21 // debugCallCheck checks whether it is safe to inject a debugger
22 // function call with return PC pc. If not, it returns a string
26 func debugCallCheck(pc uintptr) string {
27 // No user calls from the system stack.
28 if getg() != getg().m.curg {
29 return debugCallSystemStack
31 if sp := getcallersp(); !(getg().stack.lo < sp && sp <= getg().stack.hi) {
32 // Fast syscalls (nanotime) and racecall switch to the
33 // g0 stack without switching g. We can't safely make
34 // a call in this state. (We can't even safely
36 return debugCallSystemStack
39 // Switch to the system stack to avoid overflowing the user
45 ret = debugCallUnknownFunc
64 // These functions are whitelisted so that the debugger can initiate multiple function calls.
65 // See: https://golang.org/cl/161137/
69 // Disallow calls from the runtime. We could
70 // potentially make this condition tighter (e.g., not
71 // when locks are held), but there are enough tightly
72 // coded sequences (e.g., defer handling) that it's
73 // better to play it safe.
74 if pfx := "runtime."; len(name) > len(pfx) && name[:len(pfx)] == pfx {
75 ret = debugCallRuntime
79 // Look up PC's register map.
83 pcdata = pcdatavalue(f, _PCDATA_RegMapIndex, pc, nil)
86 pcdata = 0 // in prologue
88 stkmap := (*stackmap)(funcdata(f, _FUNCDATA_RegPointerMaps))
89 if pcdata == -2 || stkmap == nil {
90 // Not at a safe point.
91 ret = debugCallUnsafePoint
98 // debugCallWrap pushes a defer to recover from panics in debug calls
99 // and then calls the dispatching function at PC dispatch.
100 func debugCallWrap(dispatch uintptr) {
102 dispatchFV := funcval{dispatch}
103 *(*unsafe.Pointer)(unsafe.Pointer(&dispatchF)) = noescape(unsafe.Pointer(&dispatchFV))
109 debugCallPanicked(err)