
* logflags,proc: flag to log stacktrace execution Add a log flag to write logs about what the stacktracer does. * proc: read context from sigtrampgo, fixes TestCgoStacktrace2 on 1.21 Changes stacktrace code to read the signal context from the arguments of sigtrampgo. Also changes the automatic fatalthrow breakpoint for go 1.21. In combination these two changes fix TestCgoStacktrace2 on Go 1.21 on various platforms.
107 lines
3.4 KiB
Go
107 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
|
|
StepInstruction() error
|
|
// 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))
|
|
}
|