mirror of
				https://github.com/go-delve/delve.git
				synced 2025-11-04 14:36:47 +08:00 
			
		
		
		
	Moves handling of ResumeNotify and manualStopRequested to Target instead of the backends Updates #2551
		
			
				
	
	
		
			138 lines
		
	
	
		
			4.6 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			138 lines
		
	
	
		
			4.6 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
package proc
 | 
						|
 | 
						|
import (
 | 
						|
	"sync"
 | 
						|
 | 
						|
	"github.com/go-delve/delve/pkg/elfwriter"
 | 
						|
	"github.com/go-delve/delve/pkg/proc/internal/ebpf"
 | 
						|
)
 | 
						|
 | 
						|
// Process represents the target of the debugger. This
 | 
						|
// target could be a system process, core file, etc.
 | 
						|
//
 | 
						|
// Implementations of Process are not required to be thread safe and users
 | 
						|
// of Process should not assume they are.
 | 
						|
// There is one exception to this rule: it is safe to call RequestManualStop
 | 
						|
// concurrently with ContinueOnce.
 | 
						|
type Process interface {
 | 
						|
	BinInfo() *BinaryInfo
 | 
						|
	EntryPoint() (uint64, error)
 | 
						|
 | 
						|
	FindThread(threadID int) (Thread, bool)
 | 
						|
	ThreadList() []Thread
 | 
						|
 | 
						|
	Breakpoints() *BreakpointMap
 | 
						|
 | 
						|
	// Memory returns a memory read/writer for this process's memory.
 | 
						|
	Memory() MemoryReadWriter
 | 
						|
}
 | 
						|
 | 
						|
// ProcessInternal holds a set of methods that need to be implemented by a
 | 
						|
// Delve backend. Methods in the Process interface are safe to be called by
 | 
						|
// clients of the 'proc' library, while all other methods are only called
 | 
						|
// directly within 'proc'.
 | 
						|
type ProcessInternal interface {
 | 
						|
	Process
 | 
						|
	// Valid returns true if this Process can be used. When it returns false it
 | 
						|
	// also returns an error describing why the Process is invalid (either
 | 
						|
	// ErrProcessExited or ErrProcessDetached).
 | 
						|
	Valid() (bool, error)
 | 
						|
	Detach(bool) error
 | 
						|
	ContinueOnce(*ContinueOnceContext) (trapthread Thread, stopReason StopReason, err error)
 | 
						|
 | 
						|
	// RequestManualStop attempts to stop all the process' threads.
 | 
						|
	RequestManualStop(cctx *ContinueOnceContext) error
 | 
						|
 | 
						|
	WriteBreakpoint(*Breakpoint) error
 | 
						|
	EraseBreakpoint(*Breakpoint) error
 | 
						|
 | 
						|
	SupportsBPF() bool
 | 
						|
	SetUProbe(string, int64, []ebpf.UProbeArgMap) error
 | 
						|
	GetBufferedTracepoints() []ebpf.RawUProbeParams
 | 
						|
 | 
						|
	// DumpProcessNotes returns ELF core notes describing the process and its threads.
 | 
						|
	// Implementing this method is optional.
 | 
						|
	DumpProcessNotes(notes []elfwriter.Note, threadDone func()) (bool, []elfwriter.Note, error)
 | 
						|
	// MemoryMap returns the memory map of the target process. This method must be implemented if CanDump is true.
 | 
						|
	MemoryMap() ([]MemoryMapEntry, error)
 | 
						|
 | 
						|
	// StartCallInjection notifies the backend that we are about to inject a function call.
 | 
						|
	StartCallInjection() (func(), error)
 | 
						|
}
 | 
						|
 | 
						|
// RecordingManipulation is an interface for manipulating process recordings.
 | 
						|
type RecordingManipulation interface {
 | 
						|
	// Recorded returns true if the current process is a recording and the path
 | 
						|
	// to the trace directory.
 | 
						|
	Recorded() (recorded bool, tracedir string)
 | 
						|
	// Direction changes execution direction.
 | 
						|
	ChangeDirection(Direction) error
 | 
						|
	// GetDirection returns the current direction of execution.
 | 
						|
	GetDirection() Direction
 | 
						|
	// When returns current recording position.
 | 
						|
	When() (string, error)
 | 
						|
	// Checkpoint sets a checkpoint at the current position.
 | 
						|
	Checkpoint(where string) (id int, err error)
 | 
						|
	// Checkpoints returns the list of currently set checkpoint.
 | 
						|
	Checkpoints() ([]Checkpoint, error)
 | 
						|
	// ClearCheckpoint removes a checkpoint.
 | 
						|
	ClearCheckpoint(id int) error
 | 
						|
}
 | 
						|
 | 
						|
// RecordingManipulationInternal is an interface that a Delve backend can
 | 
						|
// implement if it is a recording.
 | 
						|
type RecordingManipulationInternal interface {
 | 
						|
	RecordingManipulation
 | 
						|
 | 
						|
	// Restart restarts the recording from the specified position, or from the
 | 
						|
	// last checkpoint if pos == "".
 | 
						|
	// If pos starts with 'c' it's a checkpoint ID, otherwise it's an event
 | 
						|
	// number.
 | 
						|
	// Returns the new current thread after the restart has completed.
 | 
						|
	Restart(cctx *ContinueOnceContext, pos string) (Thread, error)
 | 
						|
}
 | 
						|
 | 
						|
// Direction is the direction of execution for the target process.
 | 
						|
type Direction int8
 | 
						|
 | 
						|
const (
 | 
						|
	// Forward direction executes the target normally.
 | 
						|
	Forward Direction = 0
 | 
						|
	// Backward direction executes the target in reverse.
 | 
						|
	Backward Direction = 1
 | 
						|
)
 | 
						|
 | 
						|
// Checkpoint is a checkpoint
 | 
						|
type Checkpoint struct {
 | 
						|
	ID    int
 | 
						|
	When  string
 | 
						|
	Where string
 | 
						|
}
 | 
						|
 | 
						|
// ContinueOnceContext is an object passed to ContinueOnce that the backend
 | 
						|
// can use to communicate with the target layer.
 | 
						|
type ContinueOnceContext struct {
 | 
						|
	ResumeChan chan<- struct{}
 | 
						|
	StopMu     sync.Mutex
 | 
						|
	// manualStopRequested is set if all the threads in the process were
 | 
						|
	// signalled to stop as a result of a Halt API call. Used to disambiguate
 | 
						|
	// why a thread is found to have stopped.
 | 
						|
	manualStopRequested bool
 | 
						|
}
 | 
						|
 | 
						|
// CheckAndClearManualStopRequest will check for a manual
 | 
						|
// stop and then clear that state.
 | 
						|
func (cctx *ContinueOnceContext) CheckAndClearManualStopRequest() bool {
 | 
						|
	cctx.StopMu.Lock()
 | 
						|
	defer cctx.StopMu.Unlock()
 | 
						|
	msr := cctx.manualStopRequested
 | 
						|
	cctx.manualStopRequested = false
 | 
						|
	return msr
 | 
						|
}
 | 
						|
 | 
						|
func (cctx *ContinueOnceContext) GetManualStopRequested() bool {
 | 
						|
	cctx.StopMu.Lock()
 | 
						|
	defer cctx.StopMu.Unlock()
 | 
						|
	return cctx.manualStopRequested
 | 
						|
}
 |