forked from golang/debug
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathprogram.go
317 lines (272 loc) · 9.63 KB
/
program.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
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
// Copyright 2014 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Package debug provides the portable interface to a program being debugged.
package debug // import "golang.org/x/debug"
import (
"fmt"
"io"
"strings"
)
// Program is the interface to a (possibly remote) program being debugged.
// The process (if any) and text file associated with it may change during
// the session, but many resources are associated with the Program rather
// than process or text file so they persist across debuggging runs.
type Program interface {
// Open opens a virtual file associated with the process.
// Names are things like "text", "mem", "fd/2".
// Mode is one of "r", "w", "rw".
// Return values are open File and error.
// When the target binary is re-run, open files are
// automatically updated to refer to the corresponding
// file in the new process.
Open(name string, mode string) (File, error)
// Run abandons the current running process, if any,
// and execs a new instance of the target binary file
// (which may have changed underfoot).
// Breakpoints and open files are re-established.
// The call hangs until the program stops executing,
// at which point it returns the program status.
// args contains the command-line arguments for the process.
Run(args ...string) (Status, error)
// Stop stops execution of the current process but
// does not kill it.
Stop() (Status, error)
// Resume resumes execution of a stopped process.
// The call hangs until the program stops executing,
// at which point it returns the program status.
Resume() (Status, error)
// TODO: Step(). Where does the granularity happen,
// on the proxy end or the debugging control end?
// Kill kills the current process.
Kill() (Status, error)
// Breakpoint sets a breakpoint at the specified address.
Breakpoint(address uint64) (PCs []uint64, err error)
// BreakpointAtFunction sets a breakpoint at the start of the specified function.
BreakpointAtFunction(name string) (PCs []uint64, err error)
// BreakpointAtLine sets a breakpoint at the specified source line.
BreakpointAtLine(file string, line uint64) (PCs []uint64, err error)
// DeleteBreakpoints removes the breakpoints at the specified addresses.
// Addresses where no breakpoint is set are ignored.
DeleteBreakpoints(pcs []uint64) error
// Eval evaluates the expression (typically an address) and returns
// its string representation(s). Multivalued expressions such as
// matches for regular expressions return multiple values.
// TODO: change this to multiple functions with more specific names.
// Syntax:
// re:regexp
// Returns a list of symbol names that match the expression
// addr:symbol
// Returns a one-element list holding the hexadecimal
// ("0x1234") value of the address of the symbol
// val:symbol
// Returns a one-element list holding the formatted
// value of the symbol
// 0x1234, 01234, 467
// Returns a one-element list holding the name of the
// symbol ("main.foo") at that address (hex, octal, decimal).
Eval(expr string) ([]string, error)
// Evaluate evaluates an expression. Accepts a subset of Go expression syntax:
// basic literals, identifiers, parenthesized expressions, and most operators.
// Only the len function call is available.
//
// The expression can refer to local variables and function parameters of the
// function where the program is stopped.
//
// On success, the type of the value returned will be one of:
// int8, int16, int32, int64, uint8, uint16, uint32, uint64, float32, float64,
// complex64, complex128, bool, Pointer, Array, Slice, String, Map, Struct,
// Channel, Func, or Interface.
Evaluate(e string) (Value, error)
// Frames returns up to count stack frames from where the program
// is currently stopped.
Frames(count int) ([]Frame, error)
// VarByName returns a Var referring to a global variable with the given name.
// TODO: local variables
VarByName(name string) (Var, error)
// Value gets the value of a variable by reading the program's memory.
Value(v Var) (Value, error)
// MapElement returns Vars for the key and value of a map element specified by
// a 0-based index.
MapElement(m Map, index uint64) (Var, Var, error)
// Goroutines gets the current goroutines.
Goroutines() ([]*Goroutine, error)
}
type Goroutine struct {
ID int64
Status GoroutineStatus
StatusString string // A human-readable string explaining the status in more detail.
Function string // Name of the goroutine function.
Caller string // Name of the function that created this goroutine.
StackFrames []Frame
}
type GoroutineStatus byte
const (
Running GoroutineStatus = iota
Queued
Blocked
)
func (g GoroutineStatus) String() string {
switch g {
case Running:
return "running"
case Queued:
return "queued"
case Blocked:
return "blocked"
}
return "invalid status"
}
func (g *Goroutine) String() string {
return fmt.Sprintf("goroutine %d [%s] %s -> %s", g.ID, g.StatusString, g.Caller, g.Function)
}
// A reference to a variable in a program.
// TODO: handle variables stored in registers
type Var struct {
TypeID uint64 // A type identifier, opaque to the user.
Address uint64 // The address of the variable.
}
// A value read from a remote program.
type Value interface{}
// Pointer is a Value representing a pointer.
// Note that the TypeID field will be the type of the variable being pointed to,
// not the type of this pointer.
type Pointer struct {
TypeID uint64 // A type identifier, opaque to the user.
Address uint64 // The address of the variable.
}
// Array is a Value representing an array.
type Array struct {
ElementTypeID uint64
Address uint64
Length uint64 // Number of elements in the array
StrideBits uint64 // Number of bits between array entries
}
// Len returns the number of elements in the array.
func (a Array) Len() uint64 {
return a.Length
}
// Element returns a Var referring to the given element of the array.
func (a Array) Element(index uint64) Var {
return Var{
TypeID: a.ElementTypeID,
Address: a.Address + index*(a.StrideBits/8),
}
}
// Slice is a Value representing a slice.
type Slice struct {
Array
Capacity uint64
}
// String is a Value representing a string.
// TODO: a method to access more of a truncated string.
type String struct {
// Length contains the length of the remote string, in bytes.
Length uint64
// String contains the string itself; it may be truncated to fewer bytes than the value of the Length field.
String string
}
// Map is a Value representing a map.
type Map struct {
TypeID uint64
Address uint64
Length uint64 // Number of elements in the map.
}
// Struct is a Value representing a struct.
type Struct struct {
Fields []StructField
}
// StructField represents a field in a struct object.
type StructField struct {
Name string
Var Var
}
// Channel is a Value representing a channel.
type Channel struct {
ElementTypeID uint64
Address uint64 // Location of the channel struct in memory.
Buffer uint64 // Location of the buffer; zero for nil channels.
Length uint64 // Number of elements stored in the channel buffer.
Capacity uint64 // Capacity of the buffer; zero for unbuffered channels.
Stride uint64 // Number of bytes between buffer entries.
BufferStart uint64 // Index in the buffer of the element at the head of the queue.
}
// Element returns a Var referring to the given element of the channel's queue.
// If the channel is unbuffered, nil, or if the index is too large, returns a Var with Address == 0.
func (m Channel) Element(index uint64) Var {
if index >= m.Length {
return Var{
TypeID: m.ElementTypeID,
Address: 0,
}
}
if index < m.Capacity-m.BufferStart {
// The element is in the part of the queue that occurs later in the buffer
// than the head of the queue.
return Var{
TypeID: m.ElementTypeID,
Address: m.Buffer + (m.BufferStart+index)*m.Stride,
}
}
// The element is in the part of the queue that has wrapped around to the
// start of the buffer.
return Var{
TypeID: m.ElementTypeID,
Address: m.Buffer + (m.BufferStart+index-m.Capacity)*m.Stride,
}
}
// Func is a Value representing a func.
type Func struct {
Address uint64
}
// Interface is a Value representing an interface.
type Interface struct{}
// The File interface provides access to file-like resources in the program.
// It implements only ReaderAt and WriterAt, not Reader and Writer, because
// random access is a far more common pattern for things like symbol tables,
// and because enormous address space of virtual memory makes routines
// like io.Copy dangerous.
type File interface {
io.ReaderAt
io.WriterAt
io.Closer
}
type Status struct {
PC, SP uint64
}
type Frame struct {
// PC is the hardware program counter.
PC uint64
// SP is the hardware stack pointer.
SP uint64
// File and Line are the source code location of the PC.
File string
Line uint64
// Function is the name of this frame's function.
Function string
// FunctionStart is the starting PC of the function.
FunctionStart uint64
// Params contains the function's parameters.
Params []Param
// Vars contains the function's local variables.
Vars []LocalVar
}
func (f Frame) String() string {
params := make([]string, len(f.Params))
for i, p := range f.Params {
params[i] = p.Name // TODO: more information
}
p := strings.Join(params, ", ")
off := f.PC - f.FunctionStart
return fmt.Sprintf("%s(%s)\n\t%s:%d +0x%x", f.Function, p, f.File, f.Line, off)
}
// Param is a parameter of a function.
type Param struct {
Name string
Var Var
}
// LocalVar is a local variable of a function.
type LocalVar struct {
Name string
Var Var
}