// 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.

//go:build amd64

package runtime

import "unsafe"

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 debugCallV2()
func debugCallPanicked(val 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
func debugCallCheck(pc uintptr) string {
	// No user calls from the system stack.
	if getg() != getg().m.curg {
		return debugCallSystemStack
	}
	if sp := getcallersp(); !(getg().stack.lo < sp && sp <= getg().stack.hi) {
		// 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.)
		return debugCallSystemStack
	}

	// Switch to the system stack to avoid overflowing the user
	// stack.
	var ret string
	systemstack(func() {
		f := findfunc(pc)
		if !f.valid() {
			ret = debugCallUnknownFunc
			return
		}

		name := funcname(f)

		switch name {
		case "debugCall32",
			"debugCall64",
			"debugCall128",
			"debugCall256",
			"debugCall512",
			"debugCall1024",
			"debugCall2048",
			"debugCall4096",
			"debugCall8192",
			"debugCall16384",
			"debugCall32768",
			"debugCall65536":
			// 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 pfx := "runtime."; len(name) > len(pfx) && name[:len(pfx)] == pfx {
			ret = debugCallRuntime
			return
		}

		// Check that this isn't an unsafe-point.
		if pc != f.entry() {
			pc--
		}
		up := pcdatavalue(f, _PCDATA_UnsafePoint, pc, nil)
		if up != _PCDATA_UnsafePointSafe {
			// Not at a safe point.
			ret = debugCallUnsafePoint
		}
	})
	return ret
}

// 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 debugCallV2.
//
//go:nosplit
func debugCallWrap(dispatch uintptr) {
	var lockedm bool
	var lockedExt uint32
	callerpc := getcallerpc()
	gp := getg()

	// Create a new goroutine to execute the call on. Run this on
	// the system stack to avoid growing our stack.
	systemstack(func() {
		// TODO(mknyszek): It would be nice to wrap these arguments in an allocated
		// closure and start the goroutine with that closure, but the compiler disallows
		// implicit closure allocation in the runtime.
		fn := debugCallWrap1
		newg := newproc1(*(**funcval)(unsafe.Pointer(&fn)), gp, callerpc)
		args := &debugCallWrapArgs{
			dispatch: dispatch,
			callingG: gp,
		}
		newg.param = unsafe.Pointer(args)

		// If the current G is locked, then transfer that
		// locked-ness to the new goroutine.
		if gp.lockedm != 0 {
			// Save lock state to restore later.
			mp := gp.m
			if mp != gp.lockedm.ptr() {
				throw("inconsistent lockedm")
			}

			lockedm = true
			lockedExt = mp.lockedExt

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

			mp.lockedg.set(newg)
			newg.lockedm.set(mp)
			gp.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.
		gp.asyncSafePoint = true

		// Stash newg away so we can execute it below (mcall's
		// closure can't capture anything).
		gp.schedlink.set(newg)
	})

	// Switch to the new goroutine.
	mcall(func(gp *g) {
		// Get newg.
		newg := gp.schedlink.ptr()
		gp.schedlink = 0

		// Park the calling goroutine.
		gp.waitreason = waitReasonDebugCall
		if trace.enabled {
			traceGoPark(traceEvGoBlock, 1)
		}
		casgstatus(gp, _Grunning, _Gwaiting)
		dropg()

		// 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(newg, true)
	})

	// We'll resume here when the call returns.

	// Restore locked state.
	if lockedm {
		mp := gp.m
		mp.lockedExt = lockedExt
		mp.lockedInt--
		mp.lockedg.set(gp)
		gp.lockedm.set(mp)
	}

	gp.asyncSafePoint = false
}

type debugCallWrapArgs struct {
	dispatch uintptr
	callingG *g
}

// debugCallWrap1 is the continuation of debugCallWrap on the callee
// goroutine.
func debugCallWrap1() {
	gp := getg()
	args := (*debugCallWrapArgs)(gp.param)
	dispatch, callingG := args.dispatch, args.callingG
	gp.param = nil

	// Dispatch call and trap panics.
	debugCallWrap2(dispatch)

	// Resume the caller goroutine.
	getg().schedlink.set(callingG)
	mcall(func(gp *g) {
		callingG := gp.schedlink.ptr()
		gp.schedlink = 0

		// Unlock this goroutine from the M if necessary. The
		// calling G will relock.
		if gp.lockedm != 0 {
			gp.lockedm = 0
			gp.m.lockedg = 0
		}

		// Switch back to the calling goroutine. At some point
		// the scheduler will schedule us again and we'll
		// finish exiting.
		if trace.enabled {
			traceGoSched()
		}
		casgstatus(gp, _Grunning, _Grunnable)
		dropg()
		lock(&sched.lock)
		globrunqput(gp)
		unlock(&sched.lock)

		if trace.enabled {
			traceGoUnpark(callingG, 0)
		}
		casgstatus(callingG, _Gwaiting, _Grunnable)
		execute(callingG, true)
	})
}

func debugCallWrap2(dispatch uintptr) {
	// Call the dispatch function and trap panics.
	var dispatchF func()
	dispatchFV := funcval{dispatch}
	*(*unsafe.Pointer)(unsafe.Pointer(&dispatchF)) = noescape(unsafe.Pointer(&dispatchFV))

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