delve/pkg/proc/interface.go

143 lines
4.4 KiB
Go
Raw Normal View History

package proc
2017-02-08 00:23:47 +00:00
import (
"go/ast"
)
// Process represents the target of the debugger. This
2017-02-08 00:23:47 +00:00
// 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 {
2017-02-08 00:23:47 +00:00
Info
ProcessManipulation
BreakpointManipulation
RecordingManipulation
}
// 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)
// 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.
Restart(pos string) error
// Direction changes execution direction.
Direction(Direction) error
// 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
}
// 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
2017-02-08 00:23:47 +00:00
}
// Info is an interface that provides general information on the target.
type Info interface {
Pid() int
// ResumeNotify specifies a channel that will be closed the next time
// ContinueOnce finishes resuming the target.
ResumeNotify(chan<- struct{})
// 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 ProcessDetachedError).
Valid() (bool, error)
BinInfo() *BinaryInfo
EntryPoint() (uint64, error)
// Common returns a struct with fields common to all backends
Common() *CommonProcess
2017-02-08 00:23:47 +00:00
ThreadInfo
GoroutineInfo
}
// ThreadInfo is an interface for getting information on active threads
// in the process.
type ThreadInfo interface {
FindThread(threadID int) (Thread, bool)
ThreadList() []Thread
CurrentThread() Thread
2017-02-08 00:23:47 +00:00
}
// GoroutineInfo is an interface for getting information on running goroutines.
type GoroutineInfo interface {
SelectedGoroutine() *G
SetSelectedGoroutine(*G)
2017-02-08 00:23:47 +00:00
}
// ProcessManipulation is an interface for changing the execution state of a process.
type ProcessManipulation interface {
ContinueOnce() (trapthread Thread, err error)
2017-02-08 00:23:47 +00:00
StepInstruction() error
SwitchThread(int) error
SwitchGoroutine(int) error
RequestManualStop() error
// CheckAndClearManualStopRequest returns true the first time it's called
// after a call to RequestManualStop.
CheckAndClearManualStopRequest() bool
2017-02-08 00:23:47 +00:00
Detach(bool) error
}
// BreakpointManipulation is an interface for managing breakpoints.
type BreakpointManipulation interface {
Breakpoints() *BreakpointMap
SetBreakpoint(addr uint64, kind BreakpointKind, cond ast.Expr) (*Breakpoint, error)
ClearBreakpoint(addr uint64) (*Breakpoint, error)
2017-02-08 00:23:47 +00:00
ClearInternalBreakpoints() error
}
// CommonProcess contains fields used by this package, common to all
// implementations of the Process interface.
type CommonProcess struct {
allGCache []*G
fncallEnabled bool
proc: allow function calls to appear inside an expression (#1503) The initial implementation of the 'call' command required the function call to be the root expression, i.e. something like: double(3) + 1 was not allowed, because the root expression was the binary operator '+', not the function call. With this change expressions like the one above and others are allowed. This is the first step necessary to implement nested function calls (where the result of a function call is used as argument to another function call). This is implemented by replacing proc.CallFunction with proc.EvalExpressionWithCalls. EvalExpressionWithCalls will run proc.(*EvalScope).EvalExpression in a different goroutine. This goroutine, the 'eval' goroutine, will communicate with the main goroutine of the debugger by means of two channels: continueRequest and continueCompleted. The eval goroutine evaluates the expression recursively, when a function call is encountered it takes care of setting up the function call on the target program and writes a request to the continueRequest channel, this causes the 'main' goroutine to restart the target program by calling proc.Continue. Whenever Continue encounters a breakpoint that belongs to the function call injection protocol (runtime.debugCallV1 and associated functions) it writes to continueCompleted which resumes the 'eval' goroutine. The 'eval' goroutine takes care of implementing the function call injection protocol. When the expression is fully evaluated the 'eval' goroutine will write a special message to 'continueRequest' signaling that the expression evaluation is terminated which will cause Continue to return to the user. Updates #119
2019-05-09 15:29:58 +00:00
// if continueCompleted is not nil it means we are in the process of
// executing an injected function call, see comments throughout
// pkg/proc/fncall.go for a description of how this works.
continueCompleted chan<- struct{}
continueRequest <-chan continueRequest
// callInProgress is true when a function call is being injected in the
// target process.
// This is only used to prevent nested function calls, it should be removed
// when we add support for them.
callInProgress bool
}
// NewCommonProcess returns a struct with fields common across
// all process implementations.
func NewCommonProcess(fncallEnabled bool) CommonProcess {
return CommonProcess{fncallEnabled: fncallEnabled}
}
// ClearAllGCache clears the cached contents of the cache for runtime.allgs.
func (p *CommonProcess) ClearAllGCache() {
p.allGCache = nil
}