
Move StepInstruction method to TargetGroup since it will need access to the process group on Windows to call WaitForDebugEvent.
106 lines
3.4 KiB
Go
106 lines
3.4 KiB
Go
package proc
|
|
|
|
import (
|
|
"errors"
|
|
|
|
"github.com/go-delve/delve/pkg/dwarf/op"
|
|
)
|
|
|
|
// Thread represents a thread.
|
|
type Thread interface {
|
|
Location() (*Location, error)
|
|
// Breakpoint will return the breakpoint that this thread is stopped at or
|
|
// nil if the thread is not stopped at any breakpoint.
|
|
Breakpoint() *BreakpointState
|
|
ThreadID() int
|
|
|
|
// Registers returns the CPU registers of this thread. The contents of the
|
|
// variable returned may or may not change to reflect the new CPU status
|
|
// when the thread is resumed or the registers are changed by calling
|
|
// SetPC/SetSP/etc.
|
|
// To insure that the returned variable won't change call the Copy
|
|
// method of Registers.
|
|
Registers() (Registers, error)
|
|
|
|
// RestoreRegisters restores saved registers
|
|
RestoreRegisters(Registers) error
|
|
BinInfo() *BinaryInfo
|
|
// ProcessMemory returns the process memory.
|
|
ProcessMemory() MemoryReadWriter
|
|
// SetCurrentBreakpoint updates the current breakpoint of this thread, if adjustPC is true also checks for breakpoints that were just hit (this should only be passed true after a thread resume)
|
|
SetCurrentBreakpoint(adjustPC bool) error
|
|
// SoftExc returns true if this thread received a software exception during the last resume.
|
|
SoftExc() bool
|
|
// Common returns the CommonThread structure for this thread
|
|
Common() *CommonThread
|
|
|
|
// SetReg changes the value of the specified register. A minimal
|
|
// implementation of this interface can support just setting the PC
|
|
// register.
|
|
SetReg(uint64, *op.DwarfRegister) error
|
|
}
|
|
|
|
// Location represents the location of a thread.
|
|
// Holds information on the current instruction
|
|
// address, the source file:line, and the function.
|
|
type Location struct {
|
|
PC uint64
|
|
File string
|
|
Line int
|
|
Fn *Function
|
|
}
|
|
|
|
// CommonThread contains fields used by this package, common to all
|
|
// implementations of the Thread interface.
|
|
type CommonThread struct {
|
|
CallReturn bool // returnValues are the return values of a call injection
|
|
returnValues []*Variable
|
|
g *G // cached g for this thread
|
|
}
|
|
|
|
// ReturnValues reads the return values from the function executing on
|
|
// this thread using the provided LoadConfig.
|
|
func (t *CommonThread) ReturnValues(cfg LoadConfig) []*Variable {
|
|
loadValues(t.returnValues, cfg)
|
|
return t.returnValues
|
|
}
|
|
|
|
// topframe returns the two topmost frames of g, or thread if g is nil.
|
|
func topframe(tgt *Target, g *G, thread Thread) (Stackframe, Stackframe, error) {
|
|
var frames []Stackframe
|
|
var err error
|
|
|
|
if g == nil {
|
|
frames, err = ThreadStacktrace(tgt, thread, 1)
|
|
} else {
|
|
frames, err = GoroutineStacktrace(tgt, g, 1, StacktraceReadDefers)
|
|
}
|
|
if err != nil {
|
|
return Stackframe{}, Stackframe{}, err
|
|
}
|
|
switch len(frames) {
|
|
case 0:
|
|
return Stackframe{}, Stackframe{}, errors.New("empty stack trace")
|
|
case 1:
|
|
return frames[0], Stackframe{}, nil
|
|
default:
|
|
return frames[0], frames[1], nil
|
|
}
|
|
}
|
|
|
|
func setPC(thread Thread, newPC uint64) error {
|
|
return thread.SetReg(thread.BinInfo().Arch.PCRegNum, op.DwarfRegisterFromUint64(newPC))
|
|
}
|
|
|
|
func setSP(thread Thread, newSP uint64) error {
|
|
return thread.SetReg(thread.BinInfo().Arch.SPRegNum, op.DwarfRegisterFromUint64(newSP))
|
|
}
|
|
|
|
func setClosureReg(thread Thread, newClosureReg uint64) error {
|
|
return thread.SetReg(thread.BinInfo().Arch.ContextRegNum, op.DwarfRegisterFromUint64(newClosureReg))
|
|
}
|
|
|
|
func setLR(thread Thread, newLR uint64) error {
|
|
return thread.SetReg(thread.BinInfo().Arch.LRRegNum, op.DwarfRegisterFromUint64(newLR))
|
|
}
|