| // 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 local provides access to a local program. |
| package local // import "golang.org/x/debug/local" |
| |
| import ( |
| "golang.org/x/debug" |
| "golang.org/x/debug/server" |
| "golang.org/x/debug/server/protocol" |
| ) |
| |
| var _ debug.Program = (*Program)(nil) |
| var _ debug.File = (*File)(nil) |
| |
| // Program implements the debug.Program interface. |
| // Through that interface it provides access to a program being debugged. |
| type Program struct { |
| s *server.Server |
| } |
| |
| // New creates a new program from the specified file. |
| // The program can then be started by the Run method. |
| func New(textFile string) (*Program, error) { |
| s, err := server.New(textFile) |
| return &Program{s: s}, err |
| } |
| |
| func (p *Program) Open(name string, mode string) (debug.File, error) { |
| req := protocol.OpenRequest{ |
| Name: name, |
| Mode: mode, |
| } |
| var resp protocol.OpenResponse |
| err := p.s.Open(&req, &resp) |
| if err != nil { |
| return nil, err |
| } |
| f := &File{ |
| prog: p, |
| fd: resp.FD, |
| } |
| return f, nil |
| } |
| |
| func (p *Program) Run(args ...string) (debug.Status, error) { |
| req := protocol.RunRequest{args} |
| var resp protocol.RunResponse |
| err := p.s.Run(&req, &resp) |
| if err != nil { |
| return debug.Status{}, err |
| } |
| return resp.Status, nil |
| } |
| |
| func (p *Program) Stop() (debug.Status, error) { |
| panic("unimplemented") |
| } |
| |
| func (p *Program) Resume() (debug.Status, error) { |
| req := protocol.ResumeRequest{} |
| var resp protocol.ResumeResponse |
| err := p.s.Resume(&req, &resp) |
| if err != nil { |
| return debug.Status{}, err |
| } |
| return resp.Status, nil |
| } |
| |
| func (p *Program) Kill() (debug.Status, error) { |
| panic("unimplemented") |
| } |
| |
| func (p *Program) Breakpoint(address uint64) ([]uint64, error) { |
| req := protocol.BreakpointRequest{ |
| Address: address, |
| } |
| var resp protocol.BreakpointResponse |
| err := p.s.Breakpoint(&req, &resp) |
| return resp.PCs, err |
| } |
| |
| func (p *Program) BreakpointAtFunction(name string) ([]uint64, error) { |
| req := protocol.BreakpointAtFunctionRequest{ |
| Function: name, |
| } |
| var resp protocol.BreakpointResponse |
| err := p.s.BreakpointAtFunction(&req, &resp) |
| return resp.PCs, err |
| } |
| |
| func (p *Program) BreakpointAtLine(file string, line uint64) ([]uint64, error) { |
| req := protocol.BreakpointAtLineRequest{ |
| File: file, |
| Line: line, |
| } |
| var resp protocol.BreakpointResponse |
| err := p.s.BreakpointAtLine(&req, &resp) |
| return resp.PCs, err |
| } |
| |
| func (p *Program) DeleteBreakpoints(pcs []uint64) error { |
| req := protocol.DeleteBreakpointsRequest{PCs: pcs} |
| var resp protocol.DeleteBreakpointsResponse |
| return p.s.DeleteBreakpoints(&req, &resp) |
| } |
| |
| func (p *Program) Eval(expr string) ([]string, error) { |
| req := protocol.EvalRequest{ |
| Expr: expr, |
| } |
| var resp protocol.EvalResponse |
| err := p.s.Eval(&req, &resp) |
| return resp.Result, err |
| } |
| |
| func (p *Program) Evaluate(e string) (debug.Value, error) { |
| req := protocol.EvaluateRequest{ |
| Expression: e, |
| } |
| var resp protocol.EvaluateResponse |
| err := p.s.Evaluate(&req, &resp) |
| return resp.Result, err |
| } |
| |
| func (p *Program) Frames(count int) ([]debug.Frame, error) { |
| req := protocol.FramesRequest{ |
| Count: count, |
| } |
| var resp protocol.FramesResponse |
| err := p.s.Frames(&req, &resp) |
| return resp.Frames, err |
| } |
| |
| func (p *Program) Goroutines() ([]*debug.Goroutine, error) { |
| req := protocol.GoroutinesRequest{} |
| var resp protocol.GoroutinesResponse |
| err := p.s.Goroutines(&req, &resp) |
| return resp.Goroutines, err |
| } |
| |
| func (p *Program) VarByName(name string) (debug.Var, error) { |
| req := protocol.VarByNameRequest{Name: name} |
| var resp protocol.VarByNameResponse |
| err := p.s.VarByName(&req, &resp) |
| return resp.Var, err |
| } |
| |
| func (p *Program) Value(v debug.Var) (debug.Value, error) { |
| req := protocol.ValueRequest{Var: v} |
| var resp protocol.ValueResponse |
| err := p.s.Value(&req, &resp) |
| return resp.Value, err |
| } |
| |
| func (p *Program) MapElement(m debug.Map, index uint64) (debug.Var, debug.Var, error) { |
| req := protocol.MapElementRequest{Map: m, Index: index} |
| var resp protocol.MapElementResponse |
| err := p.s.MapElement(&req, &resp) |
| return resp.Key, resp.Value, err |
| } |
| |
| // File implements the debug.File interface, providing access |
| // to file-like resources associated with the target program. |
| type File struct { |
| prog *Program // The Program associated with the file. |
| fd int // File descriptor. |
| } |
| |
| func (f *File) ReadAt(p []byte, offset int64) (int, error) { |
| req := protocol.ReadAtRequest{ |
| FD: f.fd, |
| Len: len(p), |
| Offset: offset, |
| } |
| var resp protocol.ReadAtResponse |
| err := f.prog.s.ReadAt(&req, &resp) |
| return copy(p, resp.Data), err |
| } |
| |
| func (f *File) WriteAt(p []byte, offset int64) (int, error) { |
| panic("unimplemented") |
| } |
| |
| func (f *File) Close() error { |
| req := protocol.CloseRequest{ |
| FD: f.fd, |
| } |
| var resp protocol.CloseResponse |
| err := f.prog.s.Close(&req, &resp) |
| return err |
| } |