File: types.go

package info (click to toggle)
delve 1.26.0-1
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 15,084 kB
  • sloc: ansic: 111,947; sh: 194; asm: 147; makefile: 43; python: 23
file content (768 lines) | stat: -rw-r--r-- 26,403 bytes parent folder | download | duplicates (2)
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
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
package api

import (
	"bytes"
	"encoding/json"
	"errors"
	"fmt"
	"reflect"
	"strconv"
	"unicode"
	"unicode/utf8"

	"github.com/go-delve/delve/pkg/proc"
)

// ErrNotExecutable is an error returned when trying
// to debug a non-executable file.
var ErrNotExecutable = errors.New("not an executable file")

// DebuggerState represents the current context of the debugger.
type DebuggerState struct {
	// PID of the process we are debugging.
	Pid int
	// Command line of the process we are debugging.
	TargetCommandLine string
	// Running is true if the process is running and no other information can be collected.
	Running bool
	// Recording is true if the process is currently being recorded and no other
	// information can be collected. While the debugger is in this state
	// sending a StopRecording request will halt the recording, every other
	// request will block until the process has been recorded.
	Recording bool
	// Core dumping currently in progress.
	CoreDumping bool
	// CurrentThread is the currently selected debugger thread.
	CurrentThread *Thread `json:"currentThread,omitempty"`
	// SelectedGoroutine is the currently selected goroutine
	SelectedGoroutine *Goroutine `json:"currentGoroutine,omitempty"`
	// List of all the process threads
	Threads []*Thread
	// NextInProgress indicates that a next or step operation was interrupted by another breakpoint
	// or a manual stop and is waiting to complete.
	// While NextInProgress is set further requests for next or step may be rejected.
	// Either execute continue until NextInProgress is false or call CancelNext
	NextInProgress bool
	// WatchOutOfScope contains the list of watchpoints that went out of scope
	// during the last continue.
	WatchOutOfScope []*Breakpoint
	// Exited indicates whether the debugged process has exited.
	Exited     bool `json:"exited"`
	ExitStatus int  `json:"exitStatus"`
	// When contains a description of the current position in a recording
	When string
	// Filled by RPCClient.Continue, indicates an error
	Err error `json:"-"`
}

type TracepointResult struct {
	// Addr is the address of this tracepoint.
	Addr uint64 `json:"addr"`
	// File is the source file for the breakpoint.
	File string `json:"file"`
	// Line is a line in File for the breakpoint.
	Line  int  `json:"line"`
	IsRet bool `json:"is_ret"`
	// FunctionName is the name of the function at the current breakpoint, and
	// may not always be available.
	FunctionName string `json:"functionName,omitempty"`

	GoroutineID int `json:"goroutineID"`

	InputParams  []Variable `json:"inputParams,omitempty"`
	ReturnParams []Variable `json:"returnParams,omitempty"`
}

// Breakpoint addresses a set of locations at which process execution may be
// suspended.
type Breakpoint struct {
	// ID is a unique identifier for the breakpoint.
	ID int `json:"id"`
	// User defined name of the breakpoint.
	Name string `json:"name"`
	// Addr is deprecated, use Addrs.
	Addr uint64 `json:"addr"`
	// Addrs is the list of addresses for this breakpoint.
	Addrs []uint64 `json:"addrs"`
	// AddrPid[i] is the PID associated with by Addrs[i], when debugging a
	// single target process this is optional, otherwise it is mandatory.
	AddrPid []int `json:"addrpid"`
	// File is the source file for the breakpoint.
	File string `json:"file"`
	// Line is a line in File for the breakpoint.
	Line int `json:"line"`
	// FunctionName is the name of the function at the current breakpoint, and
	// may not always be available.
	FunctionName string `json:"functionName,omitempty"`
	// ExprString is the string that will be used to set a suspended breakpoint.
	ExprString string

	// Breakpoint condition
	Cond string
	// Breakpoint hit count condition.
	// Supported hit count conditions are "NUMBER" and "OP NUMBER".
	HitCond string
	// HitCondPerG use per goroutine hitcount as HitCond operand, instead of total hitcount
	HitCondPerG bool

	// Tracepoint flag, signifying this is a tracepoint.
	Tracepoint bool `json:"continue"`
	// TraceReturn flag signifying this is a breakpoint set at a return
	// statement in a traced function.
	TraceReturn bool `json:"traceReturn"`
	// retrieve goroutine information
	Goroutine bool `json:"goroutine"`
	// number of stack frames to retrieve
	Stacktrace int `json:"stacktrace"`
	// expressions to evaluate
	Variables []string `json:"variables,omitempty"`
	// LoadArgs requests loading function arguments when the breakpoint is hit
	LoadArgs *LoadConfig
	// LoadLocals requests loading function locals when the breakpoint is hit
	LoadLocals *LoadConfig
	// CustomCommands are custom starlark commands to execute when the breakpoint is hit
	CustomCommands []string `json:"customCommands,omitempty"`

	// WatchExpr is the expression used to create this watchpoint
	WatchExpr string
	WatchType WatchType

	VerboseDescr []string `json:"VerboseDescr,omitempty"`

	// number of times a breakpoint has been reached in a certain goroutine
	HitCount map[string]uint64 `json:"hitCount"`
	// number of times a breakpoint has been reached
	TotalHitCount uint64 `json:"totalHitCount"`
	// Disabled flag, signifying the state of the breakpoint
	Disabled bool `json:"disabled"`

	UserData any `json:"-"`

	// RootFuncName is the Root function from where tracing needs to be done
	RootFuncName string
	// TraceFollowCalls indicates the Depth of tracing
	TraceFollowCalls int
}

// ValidBreakpointName returns an error if
// the name to be chosen for a breakpoint is invalid.
// The name can not be just a number, and must contain a series
// of letters or numbers.
func ValidBreakpointName(name string) error {
	if _, err := strconv.Atoi(name); err == nil {
		return errors.New("breakpoint name can not be a number")
	}

	for _, ch := range name {
		if !(unicode.IsLetter(ch) || unicode.IsDigit(ch)) {
			return fmt.Errorf("invalid character in breakpoint name '%c'", ch)
		}
	}

	return nil
}

// WatchType is the watchpoint type
type WatchType uint8

const (
	WatchRead WatchType = 1 << iota
	WatchWrite
)

// Thread is a thread within the debugged process.
type Thread struct {
	// ID is a unique identifier for the thread.
	ID int `json:"id"`
	// PC is the current program counter for the thread.
	PC uint64 `json:"pc"`
	// File is the file for the program counter.
	File string `json:"file"`
	// Line is the line number for the program counter.
	Line int `json:"line"`
	// Function is function information at the program counter. May be nil.
	Function *Function `json:"function,omitempty"`

	// ID of the goroutine running on this thread
	GoroutineID int64 `json:"goroutineID"`

	// Breakpoint this thread is stopped at
	Breakpoint *Breakpoint `json:"breakPoint,omitempty"`
	// Information requested by the current breakpoint
	BreakpointInfo *BreakpointInfo `json:"breakPointInfo,omitempty"`

	// ReturnValues contains the return values of the function we just stepped out of
	ReturnValues []Variable
	// CallReturn is true if ReturnValues are the return values of an injected call.
	CallReturn bool
}

// Location holds program location information.
// In most cases a Location object will represent a physical location, with
// a single PC address held in the PC field.
// FindLocations however returns logical locations that can either have
// multiple PC addresses each (due to inlining) or no PC address at all.
type Location struct {
	PC       uint64    `json:"pc"`
	File     string    `json:"file"`
	Line     int       `json:"line"`
	Function *Function `json:"function,omitempty"`
	PCs      []uint64  `json:"pcs,omitempty"`
	PCPids   []int     `json:"pcpids,omitempty"`
}

// Stackframe describes one frame in a stack trace.
type Stackframe struct {
	Location
	Locals    []Variable
	Arguments []Variable

	FrameOffset        int64
	FramePointerOffset int64

	Defers []Defer

	Bottom bool `json:"Bottom,omitempty"` // Bottom is true if this is the bottom frame of the stack

	Err string
}

// Defer describes a deferred function.
type Defer struct {
	DeferredLoc Location // deferred function
	DeferLoc    Location // location of the defer statement
	SP          uint64   // value of SP when the function was deferred
	Unreadable  string
}

// Var will return the variable described by 'name' within
// this stack frame.
func (frame *Stackframe) Var(name string) *Variable {
	for i := range frame.Locals {
		if frame.Locals[i].Name == name {
			return &frame.Locals[i]
		}
	}
	for i := range frame.Arguments {
		if frame.Arguments[i].Name == name {
			return &frame.Arguments[i]
		}
	}
	return nil
}

// Function represents thread-scoped function information.
type Function struct {
	// Name is the function name.
	Name_  string `json:"name"`
	Value  uint64 `json:"value"`
	Type   byte   `json:"type"`
	GoType uint64 `json:"goType"`
	// Optimized is true if the function was optimized
	Optimized bool `json:"optimized"`
}

// Name will return the function name.
func (fn *Function) Name() string {
	if fn == nil {
		return "???"
	}
	return fn.Name_
}

// VariableFlags is the type of the Flags field of Variable.
type VariableFlags uint16

const (
	// VariableEscaped is set for local variables that escaped to the heap
	//
	// The compiler performs escape analysis on local variables, the variables
	// that may outlive the stack frame are allocated on the heap instead and
	// only the address is recorded on the stack. These variables will be
	// marked with this flag.
	VariableEscaped = 1 << iota

	// VariableShadowed is set for local variables that are shadowed by a
	// variable with the same name in another scope
	VariableShadowed

	// VariableConstant means this variable is a constant value
	VariableConstant

	// VariableArgument means this variable is a function argument
	VariableArgument

	// VariableReturnArgument means this variable is a function return value
	VariableReturnArgument

	// VariableFakeAddress means the address of this variable is either fake
	// (i.e. the variable is partially or completely stored in a CPU register
	// and doesn't have a real address) or possibly no longer available (because
	// the variable is the return value of a function call and allocated on a
	// frame that no longer exists)
	VariableFakeAddress

	// VariableCPtr means the variable is a C pointer
	VariableCPtr

	// VariableCPURegister means this variable is a CPU register.
	VariableCPURegister
)

// Variable describes a variable.
type Variable struct {
	// Name of the variable or struct member
	Name string `json:"name"`
	// Address of the variable or struct member
	Addr uint64 `json:"addr"`
	// Only the address field is filled (result of evaluating expressions like &<expr>)
	OnlyAddr bool `json:"onlyAddr"`
	// Go type of the variable
	Type string `json:"type"`
	// Type of the variable after resolving any typedefs
	RealType string `json:"realType"`

	Flags VariableFlags `json:"flags"`

	Kind reflect.Kind `json:"kind"`

	// Strings have their length capped at proc.maxArrayValues, use Len for the real length of a string
	// Function variables will store the name of the function in this field
	Value string `json:"value"`

	// StringValueBytes contains the Value for string variables that can not be
	// represented in unicode.
	// Specifically if v.Kind is reflect.String and v.Value is not a valid
	// unicode string the JSON marshaller will convert it to a valid unicode
	// string, altering its contents. This fields contains the unaltered string
	// contents.
	StringValueBytes []byte

	// Number of elements in an array or a slice, number of keys for a map, number of struct members for a struct, length of strings, number of captured variables for functions
	Len int64 `json:"len"`
	// Cap value for slices
	Cap int64 `json:"cap"`

	// Array and slice elements, member fields of structs, key/value pairs of maps, value of complex numbers, captured variables of functions.
	// The Name field in this slice will always be the empty string except for structs (when it will be the field name) and for complex numbers (when it will be "real" and "imaginary")
	// For maps each map entry will have to items in this slice, even numbered items will represent map keys and odd numbered items will represent their values
	// This field's length is capped at proc.maxArrayValues for slices and arrays and 2*proc.maxArrayValues for maps, in the circumstances where the cap takes effect len(Children) != Len
	// The other length cap applied to this field is related to maximum recursion depth, when the maximum recursion depth is reached this field is left empty, contrary to the previous one this cap also applies to structs (otherwise structs will always have all their member fields returned)
	Children []Variable `json:"children"`

	// Base address of arrays, Base address of the backing array for slices (0 for nil slices)
	// Base address of the backing byte array for strings
	// address of the struct backing chan and map variables
	// address of the function entry point for function variables (0 for nil function pointers)
	Base uint64 `json:"base"`

	// Unreadable addresses will have this field set
	Unreadable string `json:"unreadable"`

	// LocationExpr describes the location expression of this variable's address
	LocationExpr string
	// DeclLine is the line number of this variable's declaration
	DeclLine int64
}

type variableWithoutMarshaler Variable

func (v *Variable) MarshalJSON() (text []byte, err error) {
	var v2 *variableWithoutMarshaler = (*variableWithoutMarshaler)(v)
	if v2.Kind == reflect.String && !utf8.ValidString(v2.Value) {
		value := v2.Value
		// Should we blot out the value with something obviously wrong? Like:
		//
		// 	v2.Value = "<invalid-utf8-string>"
		// 	defer func() {
		// 		v2.Value = value
		// 	}()
		v2.StringValueBytes = []byte(value)
	}
	return json.Marshal(v2)
}

func (v *Variable) UnmarshalJSON(buf []byte) error {
	var v2 *variableWithoutMarshaler = (*variableWithoutMarshaler)(v)
	err := json.Unmarshal(buf, v2)
	if err != nil {
		return err
	}
	if v.Kind == reflect.String && len(v.StringValueBytes) > 0 {
		v.Value = string(v.StringValueBytes)
		v.StringValueBytes = nil
	}
	return nil
}

// LoadConfig describes how to load values from target's memory
type LoadConfig struct {
	// FollowPointers requests pointers to be automatically dereferenced.
	FollowPointers bool
	// MaxVariableRecurse is how far to recurse when evaluating nested types.
	MaxVariableRecurse int
	// MaxStringLen is the maximum number of bytes read from a string
	MaxStringLen int
	// MaxArrayValues is the maximum number of elements read from an array, a slice or a map.
	MaxArrayValues int
	// MaxStructFields is the maximum number of fields read from a struct, -1 will read all fields.
	MaxStructFields int
}

// Goroutine represents the information relevant to Delve from the runtime's
// internal G structure.
type Goroutine struct {
	// ID is a unique identifier for the goroutine.
	ID int64 `json:"id"`
	// Current location of the goroutine
	CurrentLoc Location `json:"currentLoc"`
	// Current location of the goroutine, excluding calls inside runtime
	UserCurrentLoc Location `json:"userCurrentLoc"`
	// Location of the go instruction that started this goroutine
	GoStatementLoc Location `json:"goStatementLoc"`
	// Location of the starting function
	StartLoc Location `json:"startLoc"`
	// ID of the associated thread for running goroutines
	ThreadID   int    `json:"threadID"`
	Status     uint64 `json:"status"`
	WaitSince  int64  `json:"waitSince"`
	WaitReason int64  `json:"waitReason"`
	Unreadable string `json:"unreadable"`
	// Goroutine's pprof labels
	Labels map[string]string `json:"labels,omitempty"`
}

const (
	GoroutineWaiting = proc.Gwaiting
	GoroutineSyscall = proc.Gsyscall
)

// DebuggerCommand is a command which changes the debugger's execution state.
type DebuggerCommand struct {
	// Name is the command to run.
	Name string `json:"name"`
	// ThreadID is used to specify which thread to use with the SwitchThread
	// command.
	ThreadID int `json:"threadID,omitempty"`
	// GoroutineID is used to specify which thread to use with the SwitchGoroutine
	// and Call commands.
	GoroutineID int64 `json:"goroutineID,omitempty"`
	// When ReturnInfoLoadConfig is not nil it will be used to load the value
	// of any return variables.
	ReturnInfoLoadConfig *LoadConfig
	// Expr is the expression argument for a Call command
	Expr string `json:"expr,omitempty"`

	// If WithEvents is set events are generated that should be read by calling
	// GetEvents.
	WithEvents bool

	// UnsafeCall disables parameter escape checking for function calls.
	// Go objects can be allocated on the stack or on the heap. Heap objects
	// can be used by any goroutine; stack objects can only be used by the
	// goroutine that owns the stack they are allocated on and can not survive
	// the stack frame of allocation.
	// The Go compiler will use escape analysis to determine whether to
	// allocate an object on the stack or the heap.
	// When injecting a function call Delve will check that no address of a
	// stack allocated object is passed to the called function: this ensures
	// the rules for stack objects will not be violated.
	// If you are absolutely sure that the function you are calling will not
	// violate the rules about stack objects you can disable this safety check
	// by setting UnsafeCall to true.
	UnsafeCall bool `json:"unsafeCall,omitempty"`
}

// BreakpointInfo contains information about the current breakpoint
type BreakpointInfo struct {
	Stacktrace []Stackframe `json:"stacktrace,omitempty"`
	Goroutine  *Goroutine   `json:"goroutine,omitempty"`
	Variables  []Variable   `json:"variables,omitempty"`
	Arguments  []Variable   `json:"arguments,omitempty"`
	Locals     []Variable   `json:"locals,omitempty"`
}

// EvalScope is the scope a command should
// be evaluated in. Describes the goroutine and frame number.
type EvalScope struct {
	GoroutineID  int64
	Frame        int
	DeferredCall int // when DeferredCall is n > 0 this eval scope is relative to the n-th deferred call in the current frame
}

const (
	// Continue resumes process execution.
	Continue = "continue"
	// Rewind resumes process execution backwards (target must be a recording).
	Rewind = "rewind"
	// DirectionCongruentContinue resumes process execution, if a reverse next, step or stepout operation is in progress it will resume execution backward.
	DirectionCongruentContinue = "directionCongruentContinue"
	// Step continues to next source line, entering function calls.
	Step = "step"
	// ReverseStep continues backward to the previous line of source code, entering function calls.
	ReverseStep = "reverseStep"
	// StepOut continues to the return address of the current function
	StepOut = "stepOut"
	// ReverseStepOut continues backward to the caller of the current function.
	ReverseStepOut = "reverseStepOut"
	// StepInstruction continues for exactly 1 cpu instruction.
	StepInstruction = "stepInstruction"
	// NextInstruction continues for 1 cpu instruction, skipping over CALL instructions.
	NextInstruction = "nextInstruction"
	// ReverseStepInstruction reverses execution for exactly 1 cpu instruction.
	ReverseStepInstruction = "reverseStepInstruction"
	// ReverseNextInstruction reverses execution for 1 cpu instruction, skipping over CALL instructions.
	ReverseNextInstruction = "reverseNextInstruction"
	// Next continues to the next source line, not entering function calls.
	Next = "next"
	// ReverseNext continues backward to the previous line of source code, not entering function calls.
	ReverseNext = "reverseNext"
	// SwitchThread switches the debugger's current thread context.
	SwitchThread = "switchThread"
	// SwitchGoroutine switches the debugger's current thread context to the thread running the specified goroutine
	SwitchGoroutine = "switchGoroutine"
	// Halt suspends the process.
	// The effect of Halt while the target process is stopped, or in the
	// process of stopping, is operating system and timing dependent. It will
	// either have no effect or cause the following resume to stop immediately.
	Halt = "halt"
	// Call resumes process execution injecting a function call.
	Call = "call"
)

// AssemblyFlavour describes the output
// of disassembled code.
type AssemblyFlavour int

const (
	// GNUFlavour will disassemble using GNU assembly syntax.
	GNUFlavour = AssemblyFlavour(proc.GNUFlavour)
	// IntelFlavour will disassemble using Intel assembly syntax.
	IntelFlavour = AssemblyFlavour(proc.IntelFlavour)
	// GoFlavour will disassemble using Go assembly syntax.
	GoFlavour = AssemblyFlavour(proc.GoFlavour)
)

// AsmInstruction represents one assembly instruction at some address
type AsmInstruction struct {
	// Loc is the location of this instruction
	Loc Location
	// Destination of CALL instructions
	DestLoc *Location
	// Text is the formatted representation of the instruction
	Text string
	// Bytes is the instruction as read from memory
	Bytes []byte
	// If Breakpoint is true a breakpoint is set at this instruction
	Breakpoint bool
	// In AtPC is true this is the instruction the current thread is stopped at
	AtPC bool
}

// AsmInstructions is a slice of single instructions.
type AsmInstructions []AsmInstruction

// GetVersionIn is the argument for GetVersion.
type GetVersionIn struct {
}

// GetVersionOut is the result of GetVersion.
type GetVersionOut struct {
	DelveVersion    string
	APIVersion      int
	Backend         string // backend currently in use
	TargetGoVersion string

	MinSupportedVersionOfGo string
	MaxSupportedVersionOfGo string
}

// SetAPIVersionIn is the input for SetAPIVersion.
type SetAPIVersionIn struct {
	APIVersion int
}

// SetAPIVersionOut is the output for SetAPIVersion.
type SetAPIVersionOut struct {
}

// Register holds information on a CPU register.
type Register struct {
	Name        string
	Value       string
	DwarfNumber int
}

// Registers is a list of CPU registers.
type Registers []Register

func (regs Registers) String() string {
	maxlen := 0
	for _, reg := range regs {
		if n := len(reg.Name); n > maxlen {
			maxlen = n
		}
	}

	var buf bytes.Buffer
	for _, reg := range regs {
		fmt.Fprintf(&buf, "%*s = %s\n", maxlen, reg.Name, reg.Value)
	}
	return buf.String()
}

// DiscardedBreakpoint is a breakpoint that is not
// reinstated during a restart.
type DiscardedBreakpoint struct {
	Breakpoint *Breakpoint
	Reason     string
}

// Checkpoint is a point in the program that
// can be returned to in certain execution modes.
type Checkpoint struct {
	ID    int
	When  string
	Where string
}

// Image represents a loaded shared object (go plugin or shared library)
type Image struct {
	Path      string
	Address   uint64
	LoadError string
}

// Ancestor represents a goroutine ancestor
type Ancestor struct {
	ID    int64
	Stack []Stackframe

	Unreadable string
}

// StacktraceOptions is the type of the Opts field of StacktraceIn that
// configures the stacktrace.
// Tracks proc.StacktraceOptions
type StacktraceOptions uint16

const (
	// StacktraceReadDefers requests a stacktrace decorated with deferred calls
	// for each frame.
	StacktraceReadDefers StacktraceOptions = 1 << iota

	// StacktraceSimple requests a stacktrace where no stack switches will be
	// attempted.
	StacktraceSimple

	// StacktraceG requests a stacktrace starting with the register
	// values saved in the runtime.g structure.
	StacktraceG
)

// PackageBuildInfo maps an import path to a directory path.
type PackageBuildInfo struct {
	ImportPath    string
	DirectoryPath string
	Files         []string
}

// DumpState describes the state of a core dump in progress
type DumpState struct {
	Dumping bool
	AllDone bool

	ThreadsDone, ThreadsTotal int
	MemDone, MemTotal         uint64

	Err string
}

// ListGoroutinesFilter describes a filtering condition for the
// ListGoroutines API call.
type ListGoroutinesFilter struct {
	Kind    GoroutineField
	Negated bool
	Arg     string
}

// GoroutineField allows referring to a field of a goroutine object.
type GoroutineField uint8

const (
	GoroutineFieldNone        GoroutineField = iota
	GoroutineCurrentLoc                      // the goroutine's CurrentLoc
	GoroutineUserLoc                         // the goroutine's UserLoc
	GoroutineGoLoc                           // the goroutine's GoStatementLoc
	GoroutineStartLoc                        // the goroutine's StartLoc
	GoroutineLabel                           // the goroutine's label
	GoroutineRunning                         // the goroutine is running
	GoroutineUser                            // the goroutine is a user goroutine
	GoroutineWaitingOnChannel                // the goroutine is waiting on the channel specified by the argument
)

// GoroutineGroup represents a group of goroutines in the return value of
// the ListGoroutines API call.
type GoroutineGroup struct {
	Name   string // name of this group
	Offset int    // start offset in the list of goroutines of this group
	Count  int    // number of goroutines that belong to this group in the list of goroutines
	Total  int    // total number of goroutines that belong to this group
}

type GoroutineGroupingOptions struct {
	GroupBy         GoroutineField
	GroupByKey      string
	MaxGroupMembers int
	MaxGroups       int
}

// Target represents a debugging target.
type Target struct {
	Pid           int
	CmdLine       string
	CurrentThread *Thread
}

// GuessSubstitutePathIn are the input parameters used to guess a substitute-path configuration automatically.
type GuessSubstitutePathIn struct {
	ImportPathOfMainPackage string
	ClientGOROOT            string
	ClientModuleDirectories map[string]string
}

// Event is an event that happened during execution of the debugged program.
type Event struct {
	Kind EventKind
	*BinaryInfoDownloadEventDetails
	*BreakpointMaterializedEventDetails
	*ProcessSpawnedEventDetails
}

type EventKind uint8

const (
	EventResumed EventKind = iota
	EventStopped
	EventBinaryInfoDownload
	EventBreakpointMaterialized
	EventProcessSpawned
)

// BinaryInfoDownloadEventDetails describes the details of a BinaryInfoDownloadEvent
type BinaryInfoDownloadEventDetails struct {
	ImagePath, Progress string
}

// BreakpointMaterializedEventDetails describes the details of a BreakpointMaterializedEvent
type BreakpointMaterializedEventDetails struct {
	Breakpoint *Breakpoint
}

// ProcessSpawnedEventDetails describes the details of a ProcessSpawnedEvent
type ProcessSpawnedEventDetails struct {
	PID        int
	ThreadID   int
	Cmdline    string
	WillFollow bool
}