/
threads.go
105 lines (90 loc) · 3.39 KB
/
threads.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
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))
}