| // 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/ogle/program/local" |
| |
| import ( |
| "golang.org/x/debug/ogle/program" |
| "golang.org/x/debug/ogle/program/proxyrpc" |
| "golang.org/x/debug/ogle/program/server" |
| ) |
| |
| var _ program.Program = (*Local)(nil) |
| var _ program.File = (*File)(nil) |
| |
| // Local implements the interface program.Program. |
| // Through that interface it provides access to a program being debugged. |
| type Local 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) (*Local, error) { |
| s, err := server.New(textFile) |
| return &Local{s: s}, err |
| } |
| |
| func (l *Local) Open(name string, mode string) (program.File, error) { |
| req := proxyrpc.OpenRequest{ |
| Name: name, |
| Mode: mode, |
| } |
| var resp proxyrpc.OpenResponse |
| err := l.s.Open(&req, &resp) |
| if err != nil { |
| return nil, err |
| } |
| f := &File{ |
| prog: l, |
| fd: resp.FD, |
| } |
| return f, nil |
| } |
| |
| func (l *Local) Run(args ...string) (program.Status, error) { |
| req := proxyrpc.RunRequest{args} |
| var resp proxyrpc.RunResponse |
| err := l.s.Run(&req, &resp) |
| if err != nil { |
| return program.Status{}, err |
| } |
| return resp.Status, nil |
| } |
| |
| func (l *Local) Stop() (program.Status, error) { |
| panic("unimplemented") |
| } |
| |
| func (l *Local) Resume() (program.Status, error) { |
| req := proxyrpc.ResumeRequest{} |
| var resp proxyrpc.ResumeResponse |
| err := l.s.Resume(&req, &resp) |
| if err != nil { |
| return program.Status{}, err |
| } |
| return resp.Status, nil |
| } |
| |
| func (l *Local) Kill() (program.Status, error) { |
| panic("unimplemented") |
| } |
| |
| func (l *Local) Breakpoint(address uint64) ([]uint64, error) { |
| req := proxyrpc.BreakpointRequest{address} |
| var resp proxyrpc.BreakpointResponse |
| err := l.s.Breakpoint(&req, &resp) |
| return resp.PCs, err |
| } |
| |
| func (l *Local) BreakpointAtFunction(name string) ([]uint64, error) { |
| req := proxyrpc.BreakpointAtFunctionRequest{name} |
| var resp proxyrpc.BreakpointResponse |
| err := l.s.BreakpointAtFunction(&req, &resp) |
| return resp.PCs, err |
| } |
| |
| func (l *Local) BreakpointAtLine(file string, line uint64) ([]uint64, error) { |
| req := proxyrpc.BreakpointAtLineRequest{file, line} |
| var resp proxyrpc.BreakpointResponse |
| err := l.s.BreakpointAtLine(&req, &resp) |
| return resp.PCs, err |
| } |
| |
| func (l *Local) DeleteBreakpoints(pcs []uint64) error { |
| req := proxyrpc.DeleteBreakpointsRequest{PCs: pcs} |
| var resp proxyrpc.DeleteBreakpointsResponse |
| return l.s.DeleteBreakpoints(&req, &resp) |
| } |
| |
| func (l *Local) Eval(expr string) ([]string, error) { |
| req := proxyrpc.EvalRequest{ |
| Expr: expr, |
| } |
| var resp proxyrpc.EvalResponse |
| err := l.s.Eval(&req, &resp) |
| return resp.Result, err |
| } |
| |
| func (l *Local) Frames(count int) ([]program.Frame, error) { |
| req := proxyrpc.FramesRequest{ |
| Count: count, |
| } |
| var resp proxyrpc.FramesResponse |
| err := l.s.Frames(&req, &resp) |
| return resp.Frames, err |
| } |
| |
| func (l *Local) VarByName(name string) (program.Var, error) { |
| req := proxyrpc.VarByNameRequest{Name: name} |
| var resp proxyrpc.VarByNameResponse |
| err := l.s.VarByName(&req, &resp) |
| return resp.Var, err |
| } |
| |
| func (l *Local) Value(v program.Var) (program.Value, error) { |
| req := proxyrpc.ValueRequest{Var: v} |
| var resp proxyrpc.ValueResponse |
| err := l.s.Value(&req, &resp) |
| return resp.Value, err |
| } |
| |
| // File implements the program.File interface, providing access |
| // to file-like resources associated with the target program. |
| type File struct { |
| prog *Local // The Program associated with the file. |
| fd int // File descriptor. |
| } |
| |
| func (f *File) ReadAt(p []byte, offset int64) (int, error) { |
| req := proxyrpc.ReadAtRequest{ |
| FD: f.fd, |
| Len: len(p), |
| Offset: offset, |
| } |
| var resp proxyrpc.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 := proxyrpc.CloseRequest{ |
| FD: f.fd, |
| } |
| var resp proxyrpc.CloseResponse |
| err := f.prog.s.Close(&req, &resp) |
| return err |
| } |