// 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 || arm64 || loong64 || ppc64le || ppc64

package runtime

import (
	"internal/abi"
	"internal/runtime/sys"
	"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 any)

// 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 := sys.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, abi.PCDATA_UnsafePoint, pc)
		if up != abi.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 lockedExt uint32
	callerpc := sys.GetCallerPC()
	gp := getg()

	// Lock ourselves to the OS thread.
	//
	// Debuggers rely on us running on the same thread until we get to
	// dispatch the function they asked as to.
	//
	// We're going to transfer this to the new G we just created.
	lockOSThread()

	// 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, false, waitReasonZero)
		args := &debugCallWrapArgs{
			dispatch: dispatch,
			callingG: gp,
		}
		newg.param = unsafe.Pointer(args)

		// Transfer locked-ness to the new goroutine.
		// Save lock state to restore later.
		mp := gp.m
		if mp != gp.lockedm.ptr() {
			throw("inconsistent lockedm")
		}
		// Save the external lock count and clear it so
		// that it can't be unlocked from the debug call.
		// Note: we already locked internally to the thread,
		// so if we were locked before we're still locked now.
		lockedExt = mp.lockedExt
		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.
		trace := traceAcquire()
		if trace.ok() {
			// Trace the event before the transition. It may take a
			// stack trace, but we won't own the stack after the
			// transition anymore.
			trace.GoPark(traceBlockDebugCall, 1)
		}
		casGToWaiting(gp, _Grunning, waitReasonDebugCall)
		if trace.ok() {
			traceRelease(trace)
		}
		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.
	mp := gp.m
	mp.lockedExt = lockedExt
	mp.lockedg.set(gp)
	gp.lockedm.set(mp)

	// Undo the lockOSThread we did earlier.
	unlockOSThread()

	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.
		trace := traceAcquire()
		if trace.ok() {
			// Trace the event before the transition. It may take a
			// stack trace, but we won't own the stack after the
			// transition anymore.
			trace.GoSched()
		}
		casgstatus(gp, _Grunning, _Grunnable)
		if trace.ok() {
			traceRelease(trace)
		}
		dropg()
		lock(&sched.lock)
		globrunqput(gp)
		unlock(&sched.lock)

		trace = traceAcquire()
		casgstatus(callingG, _Gwaiting, _Grunnable)
		if trace.ok() {
			trace.GoUnpark(callingG, 0)
			traceRelease(trace)
		}
		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
}
