2017-04-21 07:50:38 +00:00
|
|
|
package proc
|
2017-02-08 00:23:47 +00:00
|
|
|
|
2021-07-31 15:16:26 +00:00
|
|
|
import (
|
2022-03-21 19:42:37 +00:00
|
|
|
"sync"
|
2023-08-09 17:30:22 +00:00
|
|
|
"time"
|
2022-03-21 19:42:37 +00:00
|
|
|
|
2021-07-31 15:16:26 +00:00
|
|
|
"github.com/go-delve/delve/pkg/elfwriter"
|
|
|
|
"github.com/go-delve/delve/pkg/proc/internal/ebpf"
|
|
|
|
)
|
2021-01-29 21:39:33 +00:00
|
|
|
|
2023-02-22 17:26:28 +00:00
|
|
|
// ProcessGroup is a group of processes that are resumed at the same time.
|
|
|
|
type ProcessGroup interface {
|
|
|
|
ContinueOnce(*ContinueOnceContext) (Thread, StopReason, error)
|
2023-09-20 07:17:45 +00:00
|
|
|
StepInstruction(int) error
|
2023-08-28 19:46:19 +00:00
|
|
|
Detach(int, bool) error
|
2024-01-24 17:21:20 +00:00
|
|
|
Close() error
|
2023-02-22 17:26:28 +00:00
|
|
|
}
|
|
|
|
|
2017-04-21 07:50:38 +00:00
|
|
|
// 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.
|
2017-06-06 17:12:09 +00:00
|
|
|
//
|
|
|
|
// 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.
|
2017-04-21 07:50:38 +00:00
|
|
|
type Process interface {
|
2021-11-26 16:06:23 +00:00
|
|
|
BinInfo() *BinaryInfo
|
|
|
|
EntryPoint() (uint64, error)
|
|
|
|
|
|
|
|
FindThread(threadID int) (Thread, bool)
|
|
|
|
ThreadList() []Thread
|
2020-06-03 18:14:14 +00:00
|
|
|
|
|
|
|
Breakpoints() *BreakpointMap
|
2020-11-09 19:28:40 +00:00
|
|
|
|
|
|
|
// Memory returns a memory read/writer for this process's memory.
|
|
|
|
Memory() MemoryReadWriter
|
2017-05-05 22:17:52 +00:00
|
|
|
}
|
|
|
|
|
2021-11-26 16:06:23 +00:00
|
|
|
// 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'.
|
2020-03-10 19:27:38 +00:00
|
|
|
type ProcessInternal interface {
|
2021-11-26 16:06:23 +00:00
|
|
|
Process
|
2021-06-22 11:35:13 +00:00
|
|
|
// 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)
|
2022-03-21 19:42:37 +00:00
|
|
|
|
|
|
|
// RequestManualStop attempts to stop all the process' threads.
|
|
|
|
RequestManualStop(cctx *ContinueOnceContext) error
|
2020-06-03 18:14:14 +00:00
|
|
|
|
2021-01-27 15:27:54 +00:00
|
|
|
WriteBreakpoint(*Breakpoint) error
|
2020-06-03 18:14:14 +00:00
|
|
|
EraseBreakpoint(*Breakpoint) error
|
2021-01-29 21:39:33 +00:00
|
|
|
|
2021-07-31 15:16:26 +00:00
|
|
|
SupportsBPF() bool
|
2021-08-24 12:53:27 +00:00
|
|
|
SetUProbe(string, int64, []ebpf.UProbeArgMap) error
|
2021-11-26 16:06:23 +00:00
|
|
|
GetBufferedTracepoints() []ebpf.RawUProbeParams
|
2021-07-31 15:16:26 +00:00
|
|
|
|
2021-01-29 21:39:33 +00:00
|
|
|
// 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)
|
2021-07-31 15:16:26 +00:00
|
|
|
|
2021-10-14 18:06:14 +00:00
|
|
|
// StartCallInjection notifies the backend that we are about to inject a function call.
|
|
|
|
StartCallInjection() (func(), error)
|
2023-02-22 17:26:28 +00:00
|
|
|
|
|
|
|
// FollowExec enables (or disables) follow exec mode
|
|
|
|
FollowExec(bool) error
|
2020-03-10 19:27:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// 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)
|
2022-12-14 16:56:07 +00:00
|
|
|
// ChangeDirection changes execution direction.
|
proc,terminal: Implement reverse step, next and stepout (#1785)
* proc: move defer breakpoint code into a function
Moves the code that sets a breakpoint on the first deferred function,
used by both next and StepOut, to its function.
* proc: implement reverse step/next/stepout
When the direction of execution is reversed (on a recording) Step, Next and
StepOut will behave similarly to their forward version. However there are
some subtle interactions between their behavior, prologue skipping, deferred
calls and normal calls. Specifically:
- when stepping backwards we need to set a breakpoint on the first
instruction after each CALL instruction, once this breakpoint is reached we
need to execute a single StepInstruction operation to reverse step into the
CALL.
- to insure that the prologue is skipped reverse next needs to check if it
is on the first instruction after the prologue, and if it is behave like
reverse stepout.
- there is no reason to set breakpoints on deferred calls when reverse
nexting or reverse stepping out, they will never be hit.
- reverse step out should generally place its breakpoint on the CALL
instruction that created the current stack frame (which will be the CALL
instruction immediately preceding the instruction at the return address).
- reverse step out needs to treat panic calls and deferreturn calls
specially.
* service,terminal: implement reverse step, next, stepout
2020-03-11 22:40:41 +00:00
|
|
|
ChangeDirection(Direction) error
|
|
|
|
// GetDirection returns the current direction of execution.
|
|
|
|
GetDirection() Direction
|
2017-05-05 22:17:52 +00:00
|
|
|
// 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
|
|
|
|
}
|
|
|
|
|
2021-11-26 16:06:23 +00:00
|
|
|
// 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.
|
2022-03-21 19:42:37 +00:00
|
|
|
Restart(cctx *ContinueOnceContext, pos string) (Thread, error)
|
2021-11-26 16:06:23 +00:00
|
|
|
}
|
|
|
|
|
2018-08-31 18:08:18 +00:00
|
|
|
// Direction is the direction of execution for the target process.
|
2017-05-05 22:17:52 +00:00
|
|
|
type Direction int8
|
|
|
|
|
|
|
|
const (
|
2018-08-31 18:08:18 +00:00
|
|
|
// Forward direction executes the target normally.
|
|
|
|
Forward Direction = 0
|
|
|
|
// Backward direction executes the target in reverse.
|
2017-05-05 22:17:52 +00:00
|
|
|
Backward Direction = 1
|
|
|
|
)
|
|
|
|
|
|
|
|
// Checkpoint is a checkpoint
|
|
|
|
type Checkpoint struct {
|
|
|
|
ID int
|
|
|
|
When string
|
|
|
|
Where string
|
2017-02-08 00:23:47 +00:00
|
|
|
}
|
2022-03-21 19:42:37 +00:00
|
|
|
|
|
|
|
// 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
|
|
|
|
}
|
2023-08-09 17:30:22 +00:00
|
|
|
|
|
|
|
// WaitFor is passed to native.Attach and gdbserver.LLDBAttach to wait for a
|
|
|
|
// process to start before attaching.
|
|
|
|
type WaitFor struct {
|
|
|
|
Name string
|
|
|
|
Interval, Duration time.Duration
|
|
|
|
}
|