github.com/megatontech/mynoteforgo@v0.0.0-20200507084910-5d0c6ea6e890/源码/runtime/debugcall.go (about) 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. 4 5 // +build amd64 6 7 package runtime 8 9 import "unsafe" 10 11 const ( 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" 16 ) 17 18 func debugCallV1() 19 func debugCallPanicked(val interface{}) 20 21 // debugCallCheck checks whether it is safe to inject a debugger 22 // function call with return PC pc. If not, it returns a string 23 // explaining why. 24 // 25 //go:nosplit 26 func debugCallCheck(pc uintptr) string { 27 // No user calls from the system stack. 28 if getg() != getg().m.curg { 29 return debugCallSystemStack 30 } 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 35 // systemstack.) 36 return debugCallSystemStack 37 } 38 39 // Switch to the system stack to avoid overflowing the user 40 // stack. 41 var ret string 42 systemstack(func() { 43 f := findfunc(pc) 44 if !f.valid() { 45 ret = debugCallUnknownFunc 46 return 47 } 48 49 // Disallow calls from the runtime. We could 50 // potentially make this condition tighter (e.g., not 51 // when locks are held), but there are enough tightly 52 // coded sequences (e.g., defer handling) that it's 53 // better to play it safe. 54 if name, pfx := funcname(f), "runtime."; len(name) > len(pfx) && name[:len(pfx)] == pfx { 55 ret = debugCallRuntime 56 return 57 } 58 59 // Look up PC's register map. 60 pcdata := int32(-1) 61 if pc != f.entry { 62 pc-- 63 pcdata = pcdatavalue(f, _PCDATA_RegMapIndex, pc, nil) 64 } 65 if pcdata == -1 { 66 pcdata = 0 // in prologue 67 } 68 stkmap := (*stackmap)(funcdata(f, _FUNCDATA_RegPointerMaps)) 69 if pcdata == -2 || stkmap == nil { 70 // Not at a safe point. 71 ret = debugCallUnsafePoint 72 return 73 } 74 }) 75 return ret 76 } 77 78 // debugCallWrap pushes a defer to recover from panics in debug calls 79 // and then calls the dispatching function at PC dispatch. 80 func debugCallWrap(dispatch uintptr) { 81 var dispatchF func() 82 dispatchFV := funcval{dispatch} 83 *(*unsafe.Pointer)(unsafe.Pointer(&dispatchF)) = noescape(unsafe.Pointer(&dispatchFV)) 84 85 var ok bool 86 defer func() { 87 if !ok { 88 err := recover() 89 debugCallPanicked(err) 90 } 91 }() 92 dispatchF() 93 ok = true 94 }