Copyright 2018 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.
+build amd64

package runtime

import 

const (
	debugCallSystemStack = "executing on Go runtime stack"
	debugCallUnknownFunc = "call from unknown function"
	debugCallRuntime     = "call from within the Go runtime"
	debugCallUnsafePoint = "call not at safe point"
)

func ()
func ( interface{})
debugCallCheck checks whether it is safe to inject a debugger function call with return PC pc. If not, it returns a string explaining why.go:nosplit
No user calls from the system stack.
	if getg() != getg().m.curg {
		return debugCallSystemStack
	}
Fast syscalls (nanotime) and racecall switch to the g0 stack without switching g. We can't safely make a call in this state. (We can't even safely systemstack.)
Switch to the system stack to avoid overflowing the user stack.
	var  string
	systemstack(func() {
		 := findfunc()
		if !.valid() {
			 = debugCallUnknownFunc
			return
		}

		 := funcname()

		switch  {
		case "debugCall32",
			"debugCall64",
			"debugCall128",
			"debugCall256",
			"debugCall512",
			"debugCall1024",
			"debugCall2048",
			"debugCall4096",
			"debugCall8192",
			"debugCall16384",
			"debugCall32768",
These functions are allowed so that the debugger can initiate multiple function calls. See: https://golang.org/cl/161137/
			return
		}
Disallow calls from the runtime. We could potentially make this condition tighter (e.g., not when locks are held), but there are enough tightly coded sequences (e.g., defer handling) that it's better to play it safe.
		if  := "runtime."; len() > len() && [:len()] ==  {
			 = debugCallRuntime
			return
		}
Check that this isn't an unsafe-point.
		if  != .entry {
			--
		}
		 := pcdatavalue(, _PCDATA_UnsafePoint, , nil)
Not at a safe point.
			 = debugCallUnsafePoint
		}
	})
	return 
}
debugCallWrap starts a new goroutine to run a debug call and blocks the calling goroutine. On the goroutine, it prepares to recover panics from the debug call, and then calls the call dispatching function at PC dispatch. This must be deeply nosplit because there are untyped values on the stack from debugCallV1.go:nosplit
func ( uintptr) {
	var  bool
	var  uint32
	 := getcallerpc()
	 := getg()
Create a new goroutine to execute the call on. Run this on the system stack to avoid growing our stack.
	systemstack(func() {
		var  struct {
			 uintptr
			 *g
		}
		. = 
		. = 
		 := debugCallWrap1
		 := newproc1(*(**funcval)(unsafe.Pointer(&)), unsafe.Pointer(&), int32(unsafe.Sizeof()), , )
If the current G is locked, then transfer that locked-ness to the new goroutine.
Save lock state to restore later.
			 := .m
			if  != .lockedm.ptr() {
				throw("inconsistent lockedm")
			}

			 = true
			 = .lockedExt
Transfer external lock count to internal so it can't be unlocked from the debug call.
			.lockedInt++
			.lockedExt = 0

			.lockedg.set()
			.lockedm.set()
			.lockedm = 0
		}
Mark the calling goroutine as being at an async safe-point, since it has a few conservative frames at the bottom of the stack. This also prevents stack shrinks.
Stash newg away so we can execute it below (mcall's closure can't capture anything).
		.schedlink.set()
	})
Switch to the new goroutine.
Get newg.
		 := .schedlink.ptr()
		.schedlink = 0
Directly execute the new goroutine. The debug protocol will continue on the new goroutine, so it's important we not just let the scheduler do this or it may resume a different goroutine.
		execute(, true)
	})
We'll resume here when the call returns.
Restore locked state.
	if  {
		 := .m
		.lockedExt = 
		.lockedInt--
		.lockedg.set()
		.lockedm.set()
	}

	.asyncSafePoint = false
}
debugCallWrap1 is the continuation of debugCallWrap on the callee goroutine.
Dispatch call and trap panics.
	debugCallWrap2()
Resume the caller goroutine.
	getg().schedlink.set()
	mcall(func( *g) {
		 := .schedlink.ptr()
		.schedlink = 0
Unlock this goroutine from the M if necessary. The calling G will relock.
		if .lockedm != 0 {
			.lockedm = 0
			.m.lockedg = 0
		}
Switch back to the calling goroutine. At some point the scheduler will schedule us again and we'll finish exiting.
Call the dispatch function and trap panics.
	var  func()
	 := funcval{}
	*(*unsafe.Pointer)(unsafe.Pointer(&)) = noescape(unsafe.Pointer(&))

	var  bool
	defer func() {
		if ! {
			 := recover()
			debugCallPanicked()
		}
	}()
	()
	 = true