| // 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 |
| } |