x/debug: reorganize directory structure.
Fundamental types like Program, Var, Value, Frame are now in x/debug.
Deletes some unreferenced prototype code.
Change-Id: I618c6ee8327ef7f76f31a7cc98673cd3f38f2461
Reviewed-on: https://go-review.googlesource.com/19876
Reviewed-by: Rob Pike <r@golang.org>
Reviewed-by: Dave Day <djd@golang.org>
diff --git a/ogle/arch/arch.go b/arch/arch.go
similarity index 98%
rename from ogle/arch/arch.go
rename to arch/arch.go
index 4c76dc0..acd2ee9 100644
--- a/ogle/arch/arch.go
+++ b/arch/arch.go
@@ -3,7 +3,7 @@
// license that can be found in the LICENSE file.
// Package arch contains architecture-specific definitions.
-package arch // import "golang.org/x/debug/ogle/arch"
+package arch // import "golang.org/x/debug/arch"
import (
"encoding/binary"
diff --git a/ogle/cmd/ogleproxy/main.go b/cmd/debugproxy/main.go
similarity index 72%
rename from ogle/cmd/ogleproxy/main.go
rename to cmd/debugproxy/main.go
index 5459118..942790b 100644
--- a/ogle/cmd/ogleproxy/main.go
+++ b/cmd/debugproxy/main.go
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// The ogleproxy connects to the target binary and serves an RPC
-// interface to access and control it.
+// debugproxy connects to the target binary, and serves an RPC interface using
+// the types in server/protocol to access and control it.
package main
import (
@@ -13,7 +13,7 @@
"net/rpc"
"os"
- "golang.org/x/debug/ogle/program/server"
+ "golang.org/x/debug/server"
)
var (
@@ -22,31 +22,29 @@
func main() {
log.SetFlags(0)
- log.SetPrefix("ogleproxy: ")
+ log.SetPrefix("debugproxy: ")
flag.Parse()
if *textFlag == "" {
- fmt.Printf("OGLE BAD\n")
flag.Usage()
os.Exit(2)
}
s, err := server.New(*textFlag)
if err != nil {
- fmt.Printf("OGLE BAD\n%s\n", err)
+ fmt.Printf("server.New: %v\n", err)
os.Exit(2)
}
err = rpc.Register(s)
if err != nil {
- fmt.Printf("OGLE BAD\n%s\n", err)
+ fmt.Printf("rpc.Register: %v\n", err)
os.Exit(2)
}
- fmt.Println("OGLE OK")
- log.Print("start server")
- // TODO: Usually done in a go.
+ fmt.Println("OK")
+ log.Print("starting server")
rpc.ServeConn(&rwc{
os.Stdin,
os.Stdout,
})
- log.Print("finish server")
+ log.Print("server finished")
}
// rwc creates a single io.ReadWriteCloser from a read side and a write side.
diff --git a/ogle/doc/ptrace-nptl.txt b/doc/ptrace-nptl.txt
similarity index 100%
rename from ogle/doc/ptrace-nptl.txt
rename to doc/ptrace-nptl.txt
diff --git a/local/local.go b/local/local.go
new file mode 100644
index 0000000..e054249
--- /dev/null
+++ b/local/local.go
@@ -0,0 +1,193 @@
+// 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
+}
diff --git a/ogle/demo/ptrace-linux-amd64/main.go b/ogle/demo/ptrace-linux-amd64/main.go
deleted file mode 100644
index c90c534..0000000
--- a/ogle/demo/ptrace-linux-amd64/main.go
+++ /dev/null
@@ -1,270 +0,0 @@
-// 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.
-
-// This program is a standalone demo that demonstrates a Go tracer program
-// (this program) forking, executing and inserting breakpoints into a (multi-
-// threaded) Go tracee program. It logs all syscall.Wait4 results, and reading
-// those logs, as well as ../../doc/ptrace-nptl.txt, should help understand how
-// the (more complicated) golang.org/x/debug/ogle/program/server package works.
-//
-// Only tested on linux/amd64.
-package main
-
-// TODO: other threads are not stopped when one tracee thread hits a breakpoint.
-// Thus, other threads could racily miss a breakpoint when they concurrently
-// execute code where the trap should be, in between lifting and re-setting the
-// trap.
-//
-// One option is to simply accept this behavior as is. Another option, "all-
-// stop", is to stop all other threads when one traps. A third option, "non-
-// stop", is to not lift the trap and not stop other threads, but to simulate
-// the original instruction when single-stepping: the "Non-stop Multi-Threaded
-// Debugging in GDB" paper calls this "displaced stepping". "Non-stop" is less
-// intrusive than "all-stop" (e.g. network I/O can still happen while at a
-// breakpoint), but it involves complicated, architecture-specific code.
-
-import (
- "fmt"
- "log"
- "os"
- "runtime"
- "syscall"
- "time"
-
- "golang.org/x/debug/dwarf"
- "golang.org/x/debug/elf"
- "golang.org/x/debug/macho"
-)
-
-const (
- exeFilename = "tracee/tracee"
-
- // TODO: don't be amd64-specific.
- breakpointInstr = 0xcc
- breakpointInstrLen = 1
-)
-
-type breakpoint struct {
- pc uint64
- origInstr byte // TODO: don't be amd64-specific.
-}
-
-func main() {
- go run()
- time.Sleep(2 * time.Second)
-}
-
-func run() {
- // If the debugger itself is multi-threaded, ptrace calls must come from
- // the same thread that originally attached to the remote thread.
- runtime.LockOSThread()
-
- f, err := os.Open(exeFilename)
- if err != nil {
- log.Printf(`%q not found. Did you run "go build ." in that directory?`, exeFilename)
- log.Fatalf("Open: %v", err)
- }
- defer f.Close()
- dwarfData, err := loadDwarfData(f)
- if err != nil {
- log.Fatalf("loadDwarfData: %v", err)
- }
-
- proc, err := os.StartProcess(exeFilename, []string{exeFilename}, &os.ProcAttr{
- Files: []*os.File{
- os.Stdin,
- os.Stdout,
- os.Stderr,
- },
- Sys: &syscall.SysProcAttr{
- Ptrace: true,
- Pdeathsig: syscall.SIGKILL,
- },
- })
- if err != nil {
- log.Fatalf("StartProcess: %v", err)
- }
-
- fmt.Printf("\tproc.Pid=%d\n", proc.Pid)
-
- _, status, err := wait(proc.Pid)
- if err != nil {
- log.Fatalf("wait: %v", err)
- }
- if status != 0x00057f { // 0x05=SIGTRAP, 0x7f=stopped.
- log.Fatalf("status: got %#x, want %#x", status, 0x57f)
- }
- err = syscall.PtraceSetOptions(proc.Pid, syscall.PTRACE_O_TRACECLONE|syscall.PTRACE_O_TRACEEXIT)
- if err != nil {
- log.Fatalf("PtraceSetOptions: %v", err)
- }
-
- addr, err := lookupSym(dwarfData, "fmt.Printf")
- if err != nil {
- log.Fatalf("lookupSym: %v", err)
- }
- fmt.Printf("\tfmt.Printf=%#x\n", addr)
-
- var buf [1]byte
- if err := peek(proc.Pid, addr, buf[:1]); err != nil {
- log.Fatalf("peek: %v", err)
- }
- breakpoints := map[uint64]breakpoint{
- addr: {pc: addr, origInstr: buf[0]},
- }
- buf[0] = breakpointInstr
- if err := poke(proc.Pid, addr, buf[:1]); err != nil {
- log.Fatalf("poke: %v", err)
- }
-
- err = syscall.PtraceCont(proc.Pid, 0)
- if err != nil {
- log.Fatalf("PtraceCont: %v", err)
- }
-
- for {
- pid, status, err := wait(-1)
- if err != nil {
- log.Fatalf("wait: %v", err)
- }
-
- switch status {
- case 0x00057f: // 0x05=SIGTRAP, 0x7f=stopped.
- regs := syscall.PtraceRegs{}
- if err := syscall.PtraceGetRegs(pid, ®s); err != nil {
- log.Fatalf("PtraceGetRegs: %v", err)
- }
- regs.Rip -= breakpointInstrLen
- if err := syscall.PtraceSetRegs(pid, ®s); err != nil {
- log.Fatalf("PtraceSetRegs: %v", err)
- }
- bp, ok := breakpoints[regs.Rip]
- if !ok {
- log.Fatalf("no breakpoint for address %#x\n", regs.Rip)
- }
- buf[0] = bp.origInstr
- if err := poke(pid, addr, buf[:1]); err != nil {
- log.Fatalf("poke: %v", err)
- }
- fmt.Printf("\thit breakpoint at %#x, pid=%5d\n", regs.Rip, pid)
- if err := syscall.PtraceSingleStep(pid); err != nil {
- log.Fatalf("PtraceSingleStep: %v", err)
- }
- _, status, err := wait(pid)
- if err != nil {
- log.Fatalf("wait: %v", err)
- }
- if status != 0x00057f {
- log.Fatalf("PtraceSingleStep: unexpected status %#x\n", status)
- }
- buf[0] = breakpointInstr
- if err := poke(pid, addr, buf[:1]); err != nil {
- log.Fatalf("poke: %v", err)
- }
-
- case 0x00137f: // 0x13=SIGSTOP, 0x7f=stopped.
- // No-op.
-
- case 0x03057f: // 0x05=SIGTRAP, 0x7f=stopped, 0x03=PTRACE_EVENT_CLONE.
- msg, err := syscall.PtraceGetEventMsg(pid)
- if err != nil {
- log.Fatalf("PtraceGetEventMsg: %v", err)
- }
- fmt.Printf("\tclone: new pid=%d\n", msg)
-
- default:
- log.Fatalf("unexpected status %#x\n", status)
- }
-
- err = syscall.PtraceCont(pid, 0)
- if err != nil {
- log.Fatalf("PtraceCont: %v", err)
- }
- }
-}
-
-func wait(pid int) (wpid int, status syscall.WaitStatus, err error) {
- wpid, err = syscall.Wait4(pid, &status, syscall.WALL, nil)
- if err != nil {
- return 0, 0, err
- }
- fmt.Printf("\t\twait: wpid=%5d, status=0x%06x\n", wpid, status)
- return wpid, status, nil
-}
-
-func peek(pid int, addr uint64, data []byte) error {
- n, err := syscall.PtracePeekText(pid, uintptr(addr), data)
- if err != nil {
- return err
- }
- if n != len(data) {
- return fmt.Errorf("peek: got %d bytes, want %d", len(data))
- }
- return nil
-}
-
-func poke(pid int, addr uint64, data []byte) error {
- n, err := syscall.PtracePokeText(pid, uintptr(addr), data)
- if err != nil {
- return err
- }
- if n != len(data) {
- return fmt.Errorf("poke: got %d bytes, want %d", len(data))
- }
- return nil
-}
-
-func lookupSym(dwarfData *dwarf.Data, name string) (uint64, error) {
- r := dwarfData.Reader()
- for {
- entry, err := r.Next()
- if err != nil {
- return 0, err
- }
- if entry == nil {
- // TODO: why don't we get an error here.
- break
- }
- if entry.Tag != dwarf.TagSubprogram {
- continue
- }
- nameAttr := lookupAttr(entry, dwarf.AttrName)
- if nameAttr == nil {
- // TODO: this shouldn't be possible.
- continue
- }
- if nameAttr.(string) != name {
- continue
- }
- addrAttr := lookupAttr(entry, dwarf.AttrLowpc)
- if addrAttr == nil {
- return 0, fmt.Errorf("symbol %q has no LowPC attribute", name)
- }
- addr, ok := addrAttr.(uint64)
- if !ok {
- return 0, fmt.Errorf("symbol %q has non-uint64 LowPC attribute", name)
- }
- return addr, nil
- }
- return 0, fmt.Errorf("symbol %q not found", name)
-}
-
-func lookupAttr(e *dwarf.Entry, a dwarf.Attr) interface{} {
- for _, f := range e.Field {
- if f.Attr == a {
- return f.Val
- }
- }
- return nil
-}
-
-func loadDwarfData(f *os.File) (*dwarf.Data, error) {
- if obj, err := elf.NewFile(f); err == nil {
- return obj.DWARF()
- }
- if obj, err := macho.NewFile(f); err == nil {
- return obj.DWARF()
- }
- return nil, fmt.Errorf("unrecognized binary format")
-}
diff --git a/ogle/demo/ptrace-linux-amd64/tracee/main.go b/ogle/demo/ptrace-linux-amd64/tracee/main.go
deleted file mode 100644
index 042e4f7..0000000
--- a/ogle/demo/ptrace-linux-amd64/tracee/main.go
+++ /dev/null
@@ -1,42 +0,0 @@
-// 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.
-
-// This program prints to stdout from multiple goroutines multiplexed onto
-// multiple threads. It is used as the tracee program by the debugger (tracer)
-// program in the parent directory.
-package main
-
-import (
- "fmt"
- "runtime"
- "syscall"
- "time"
-)
-
-// ansiColor is whether to display ANSI color codes in the program's output.
-// This distinguishes this program's output (the tracee's) from the debugger
-// program's output (the tracer's).
-const ansiColor = false
-
-var prefix, suffix string
-
-func run(base int, sleep time.Duration, lockOSThread bool) {
- if lockOSThread {
- runtime.LockOSThread()
- }
- for i := 0; ; i++ {
- fmt.Printf("%sx=%5d tid=%d%s\n", prefix, base+i, syscall.Gettid(), suffix)
- time.Sleep(sleep)
- }
-}
-
-func main() {
- if ansiColor {
- prefix, suffix = "\x1b[36m", "\x1b[0m"
- }
- go run(0, 300*time.Millisecond, false)
- go run(100, 500*time.Millisecond, false)
- go run(10000, 700*time.Millisecond, true)
- time.Sleep(5 * time.Second)
-}
diff --git a/ogle/probe/addr_test.go b/ogle/probe/addr_test.go
deleted file mode 100644
index 48ff2ac..0000000
--- a/ogle/probe/addr_test.go
+++ /dev/null
@@ -1,85 +0,0 @@
-// 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 probe
-
-import (
- "reflect"
- "testing"
-)
-
-// Defined in assembler.
-func base() uintptr
-func etext() uintptr
-func edata() uintptr
-func end() uintptr
-
-var dataItem = 3
-var bssItem [100]int
-
-// addr turns an arbitrary address into a uintptr.
-func addr(p interface{}) uintptr {
- v := reflect.ValueOf(p)
- switch v.Kind() {
- case reflect.Ptr:
- return v.Elem().UnsafeAddr()
- default:
- // TODO: how do we find the address of a text symbol?
- panic("unknown type " + v.Type().String())
- }
-}
-
-func TestGoodReadAddresses(t *testing.T) {
- addrs := []uintptr{
- base(),
- addr(&t), // On the stack.
- addr(&dataItem), // In data.
- addr(&bssItem), // In bss.
- }
- for _, a := range addrs {
- if !validRead(a, 1) {
- t.Errorf("%#x is invalid; should be valid", a)
- }
- }
-}
-
-func TestBadReadAddresses(t *testing.T) {
- addrs := []uintptr{
- 0,
- base()/2 - 1, // Pull well down below; the Mac only unmaps up to 0x1000.
- ^uintptr(0),
- }
- for _, a := range addrs {
- if validRead(a, 1) {
- t.Errorf("%#x is valid; should be invalid", a)
- }
- }
-}
-
-func TestGoodWriteAddresses(t *testing.T) {
- addrs := []uintptr{
- addr(&t), // On the stack.
- addr(&dataItem), // In data.
- addr(&bssItem), // In bss.
- }
- for _, a := range addrs {
- if !validWrite(a, 1) {
- t.Errorf("%#x is invalid; should be valid", a)
- }
- }
-}
-
-func TestBadWriteAddresses(t *testing.T) {
- addrs := []uintptr{
- 0,
- base(), // In the text segment.
- base() - 1,
- ^uintptr(0),
- }
- for _, a := range addrs {
- if validWrite(a, 1) {
- t.Errorf("%#x is valid; should be invalid", a)
- }
- }
-}
diff --git a/ogle/probe/net.go b/ogle/probe/net.go
deleted file mode 100644
index 87ebe98..0000000
--- a/ogle/probe/net.go
+++ /dev/null
@@ -1,286 +0,0 @@
-// 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.
-
-// TODO: Document the protocol once it settles.
-
-package probe
-
-import (
- "errors"
- "io" // Used only for the definitions of the various interfaces and errors.
- "net"
-
- "golang.org/x/debug/ogle/socket"
-)
-
-var (
- tracing = false
- listening = make(chan struct{})
-)
-
-// init starts a listener and leaves it in the background waiting for connections.
-func init() {
- go demon()
-}
-
-// demon answers consecutive connection requests and starts a server to manage each one.
-// The server runs in the same goroutine as the demon, so a new connection cannot be
-// established until the previous one is completed.
-func demon() {
- listener, err := socket.Listen()
- close(listening)
- if err != nil {
- trace("listen:", err)
- return
- }
- trace("listening")
- for {
- conn, err := listener.Accept()
- if err != nil {
- trace("accept", err)
- continue
- }
- trace("accepted a connection")
- serve(conn)
- conn.Close()
- }
-}
-
-// stringer is the same as fmt.Stringer. We redefine it here to avoid pulling in fmt.
-type stringer interface {
- String() string
-}
-
-func printHex(b byte) {
- const hex = "0123456789ABCDEF"
- b1, b0 := b>>4&0xF, b&0xF
- print(hex[b1:b1+1], hex[b0:b0+1])
-}
-
-// trace is a simple version of println that is enabled by the tracing boolean.
-func trace(args ...interface{}) {
- if !tracing {
- return
- }
- print("ogle demon: ")
- for i, arg := range args {
- if i > 0 {
- print(" ")
- }
- // A little help. Built-in print isn't very capable.
- switch arg := arg.(type) {
- case stringer:
- print(arg.String())
- case error:
- print(arg.Error())
- case []byte:
- print("[")
- for i := range arg {
- if i > 0 {
- print(" ")
- }
- printHex(arg[i])
- }
- print("]")
- case int:
- print(arg)
- case string:
- print(arg)
- case uintptr:
- print("0x")
- for i := ptrSize - 1; i >= 0; i-- {
- printHex(byte(arg >> uint(8*i)))
- }
- default:
- print(arg)
- }
- }
- print("\n")
-}
-
-func serve(conn net.Conn) {
- const (
- bufSize = 1 << 16
- )
- var buf [bufSize]byte
- network := &pipe{
- rw: conn,
- }
- for {
- // One message per loop.
- n, err := network.Read(buf[:1])
- if n != 1 || err != nil {
- return
- }
- switch buf[0] {
- case 'r':
- // Read: ['r', address, size] => [0, size, size bytes]
- u, err := network.readUintptr()
- if err != nil {
- return
- }
- n, err := network.readInt()
- if err != nil {
- return
- }
- if !validRead(u, n) {
- trace("read", err)
- network.error("invalid read address")
- continue
- }
- network.sendReadResponse(u, n)
- default:
- // TODO: shut down connection?
- trace("unknown message type:", buf[0])
- }
- }
-}
-
-// pipe is a buffered network connection (actually just a reader/writer) that
-// implements Read and ReadByte as well as readFull.
-// It also has support routines to make it easier to read and write
-// network messages.
-type pipe struct {
- rw io.ReadWriter
- pos int
- end int
- oneByte [1]byte
- buf [4096]byte
-}
-
-// readFull fills the argument slice with data from the wire. If it cannot fill the
-// slice, it returns an error.
-// TODO: unused for now; write will need it.
-func (p *pipe) readFull(buf []byte) error {
- for len(buf) > 0 {
- n, err := p.rw.Read(buf)
- if n == len(buf) {
- return nil
- }
- if err != nil {
- if err == io.EOF {
- err = io.ErrUnexpectedEOF
- }
- return err
- }
- if n == 0 {
- return io.EOF
- }
- buf = buf[n:]
- }
- return nil
-}
-
-// Read satisfies io.Reader.
-func (p *pipe) Read(buf []byte) (int, error) {
- n := len(buf)
- if p.end == p.pos {
- p.pos = 0
- // Read from network
- var err error
- p.end, err = p.rw.Read(p.buf[:])
- if err != nil {
- trace("read:", err)
- return p.end, err
- }
- if p.end == 0 {
- trace("read: eof")
- return p.end, io.EOF
- }
- }
- if n > p.end-p.pos {
- n = p.end - p.pos
- }
- copy(buf, p.buf[p.pos:p.pos+n])
- p.pos += n
- return n, nil
-}
-
-// ReadByte satisfies io.ByteReader.
-func (p *pipe) ReadByte() (byte, error) {
- _, err := p.Read(p.oneByte[:])
- return p.oneByte[0], err
-}
-
-// readUintptr reads a varint-encoded uinptr value from the connection.
-func (p *pipe) readUintptr() (uintptr, error) {
- u, err := readUvarint(p)
- if err != nil {
- trace("read uintptr:", err)
- return 0, err
- }
- if u > uint64(^uintptr(0)) {
- trace("read uintptr: overflow")
- return 0, err
- }
- return uintptr(u), nil
-}
-
-var intOverflow = errors.New("ogle probe: varint overflows int")
-
-// readInt reads an varint-encoded int value from the connection.
-// The transported value is always a uint64; this routine
-// verifies that it fits in an int.
-func (p *pipe) readInt() (int, error) {
- u, err := readUvarint(p)
- if err != nil {
- trace("read int:", err)
- return 0, err
- }
- // Does it fit in an int?
- if u > maxInt {
- trace("int overflow")
- return 0, intOverflow
- }
- return int(u), nil
-}
-
-// error writes an error message to the connection.
-// The format is [size, size bytes].
-func (p *pipe) error(msg string) {
- // A zero-length message is problematic. It should never arise, but be safe.
- if len(msg) == 0 {
- msg = "undefined error"
- }
- // Truncate if necessary. Extremely unlikely.
- if len(msg) > len(p.buf)-maxVarintLen64 {
- msg = msg[:len(p.buf)-maxVarintLen64]
- }
- n := putUvarint(p.buf[:], uint64(len(msg)))
- n += copy(p.buf[n:], msg)
- _, err := p.rw.Write(p.buf[:n])
- if err != nil {
- trace("write:", err)
- // TODO: shut down connection?
- }
-}
-
-// sendReadResponse sends a read response to the connection.
-// The format is [0, size, size bytes].
-func (p *pipe) sendReadResponse(addr uintptr, size int) {
- trace("sendRead:", addr, size)
- m := 0
- m += putUvarint(p.buf[m:], 0) // No error.
- m += putUvarint(p.buf[m:], uint64(size)) // Number of bytes to follow.
- for m > 0 || size > 0 {
- n := len(p.buf) - m
- if n > size {
- n = size
- }
- if !read(addr, p.buf[m:m+n]) {
- trace("copy error")
- // TODO: shut down connection?
- // TODO: for now, continue delivering data. We said we would.
- }
- _, err := p.rw.Write(p.buf[:m+n])
- if err != nil {
- trace("write:", err)
- // TODO: shut down connection?
- }
- addr += uintptr(n)
- size -= n
- // Next time we can use the whole buffer.
- m = 0
- }
-}
diff --git a/ogle/probe/net_test.go b/ogle/probe/net_test.go
deleted file mode 100644
index c9d599d..0000000
--- a/ogle/probe/net_test.go
+++ /dev/null
@@ -1,233 +0,0 @@
-// 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 probe
-
-import (
- "bufio"
- "io"
- "net"
- "os"
- "testing"
- "unsafe"
-
- "golang.org/x/debug/ogle/socket"
-)
-
-// traceThisFunction turns on tracing and returns a function to turn it off.
-// It is intended for use as "defer traceThisFunction()()".
-func traceThisFunction() func() {
- // TODO: This should be done atomically to guarantee the probe can see the update.
- tracing = true
- return func() {
- tracing = false
- }
-}
-
-type Conn struct {
- conn net.Conn
- input *bufio.Reader
- output *bufio.Writer
-}
-
-func (c *Conn) close() {
- c.output.Flush()
- c.conn.Close()
-}
-
-// newConn makes a connection.
-func newConn(t *testing.T) *Conn {
- // defer traceThisFunction()()
- <-listening
- conn, err := socket.Dial(os.Getuid(), os.Getpid())
- if err != nil {
- t.Fatal(err)
- }
- return &Conn{
- conn: conn,
- input: bufio.NewReader(conn),
- output: bufio.NewWriter(conn),
- }
-}
-
-// bytesToUint64 returns the uint64 stored in the 8 bytes of buf.
-func bytesToUint64(buf []byte) uint64 {
- // We're using same machine here, so byte order is the same.
- // We can just fetch it, but on some architectures it
- // must be aligned so copy first.
- var tmp [8]byte
- copy(tmp[:], buf)
- return *(*uint64)(unsafe.Pointer(&tmp[0]))
-}
-
-// Test that we get an error back for a request to read an illegal address.
-func TestReadBadAddress(t *testing.T) {
- //defer traceThisFunction()()
-
- conn := newConn(t)
- defer conn.close()
-
- // Read the elements in pseudo-random order.
- var tmp [100]byte
- // Request a read of a bad address.
- conn.output.WriteByte('r')
- // Address.
- n := putUvarint(tmp[:], 0)
- conn.output.Write(tmp[:n])
- // Length. Any length will do.
- n = putUvarint(tmp[:], 8)
- conn.output.Write(tmp[:n])
- // Send it.
- err := conn.output.Flush()
- if err != nil {
- t.Fatal(err)
- }
- // Read result.
- // We expect an initial non-zero value, the number of bytes of the error message.
- u, err := readUvarint(conn.input)
- if err != nil {
- t.Fatal(err)
- }
- if u == 0 {
- t.Fatalf("expected error return; got none")
- }
- // We expect a particular error.
- const expect = "invalid read address"
- if u != uint64(len(expect)) {
- t.Fatalf("got %d bytes; expected %d", u, len(expect))
- }
- _, err = io.ReadFull(conn.input, tmp[:u])
- if err != nil {
- t.Fatal(err)
- }
- msg := string(tmp[:u])
- if msg != expect {
- t.Fatalf("got %q; expected %q", msg, expect)
- }
-}
-
-// Test that we can read some data from the address space on the other side of the connection.
-func TestReadUint64(t *testing.T) {
- //defer traceThisFunction()()
-
- conn := newConn(t)
- defer conn.close()
-
- // Some data to send over the wire.
- data := make([]uint64, 10)
- for i := range data {
- data[i] = 0x1234567887654321 + 12345*uint64(i)
- }
- // TODO: To be righteous we should put a memory barrier here.
-
- // Read the elements in pseudo-random order.
- var tmp [100]byte
- which := 0
- for i := 0; i < 100; i++ {
- which = (which + 7) % len(data)
- // Request a read of data[which].
- conn.output.WriteByte('r')
- // Address.
- n := putUvarint(tmp[:], uint64(addr(&data[which])))
- conn.output.Write(tmp[:n])
- // Length
- n = putUvarint(tmp[:], 8)
- conn.output.Write(tmp[:n])
- // Send it.
- err := conn.output.Flush()
- if err != nil {
- t.Fatal(err)
- }
- // Read result.
- // We expect 10 bytes: the initial zero, followed by 8 (the count), followed by 8 bytes of data.
- u, err := readUvarint(conn.input)
- if err != nil {
- t.Fatal(err)
- }
- if u != 0 {
- t.Fatalf("expected leading zero byte; got %#x\n", u)
- }
- // N bytes of data.
- u, err = readUvarint(conn.input)
- if err != nil {
- t.Fatal(err)
- }
- if u != 8 {
- t.Fatalf("got %d bytes of data; expected 8", u)
- }
- _, err = io.ReadFull(conn.input, tmp[:u])
- if err != nil {
- t.Fatal(err)
- }
- u = bytesToUint64(tmp[:u])
- if u != data[which] {
- t.Fatalf("got %#x; expected %#x", u, data[which])
- }
- }
-}
-
-// Test that we can read an array bigger than the pipe's buffer size.
-func TestBigRead(t *testing.T) {
- // defer traceThisFunction()()
-
- conn := newConn(t)
- defer conn.close()
-
- // A big slice.
- data := make([]byte, 3*len(pipe{}.buf))
- noise := 17
- for i := range data {
- data[i] = byte(noise)
- noise += 23
- }
- // TODO: To be righteous we should put a memory barrier here.
-
- // Read the elements in one big call.
- tmp := make([]byte, len(data))
- conn.output.WriteByte('r')
- // Address.
- n := putUvarint(tmp[:], uint64(addr(&data[0])))
- conn.output.Write(tmp[:n])
- // Length.
- n = putUvarint(tmp[:], uint64(len(data)))
- conn.output.Write(tmp[:n])
- // Send it.
- err := conn.output.Flush()
- if err != nil {
- t.Fatal(err)
- }
- // Read result.
- // We expect the full data back.
- u, err := readUvarint(conn.input)
- if err != nil {
- t.Fatal(err)
- }
- if u != 0 {
- t.Fatalf("expected leading zero byte; got %#x\n", u)
- }
- // N bytes of data.
- u, err = readUvarint(conn.input)
- if err != nil {
- t.Fatal(err)
- }
- if u != uint64(len(data)) {
- t.Fatalf("got %d bytes of data; expected 8", u)
- }
- _, err = io.ReadFull(conn.input, tmp)
- if err != nil {
- t.Fatal(err)
- }
- for i, c := range data {
- if tmp[i] != c {
- t.Fatalf("at offset %d expected %#x; got %#x", i, c, tmp[i])
- }
- }
-}
-
-// TestCollectGarbage doesn't actually test anything, but it does collect any
-// garbage sockets that are no longer used. It is a courtesy for computers that
-// run this test suite often.
-func TestCollectGarbage(t *testing.T) {
- socket.CollectGarbage()
-}
diff --git a/ogle/probe/probe.go b/ogle/probe/probe.go
deleted file mode 100644
index 9db1f81..0000000
--- a/ogle/probe/probe.go
+++ /dev/null
@@ -1,79 +0,0 @@
-// 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 probe is imported by programs to provide (possibly remote)
-// access to a separate debugger program.
-package probe // import "golang.org/x/debug/ogle/probe"
-
-import (
- "runtime/debug"
- "unsafe"
-)
-
-// catchFault is used by the read and write routines to turn a panic into an error return.
-func catchFault(ok *bool) {
- if e := recover(); e != nil {
- *ok = false
- }
-}
-
-// validRead reports whether a read of the specified size can be done at address p.
-// TODO: It does this by actually doing the read and seeing if it succeeds. Do better.
-func validRead(p uintptr, size int) (ok bool) {
- // Check for negative size and for (p + size) overflow.
- if size < 0 || uint64(^uintptr(0)-p) < uint64(size) {
- return false
- }
- defer catchFault(&ok)
- defer debug.SetPanicOnFault(debug.SetPanicOnFault(true))
- ep := p + uintptr(size)
- var b byte
- for p < ep {
- b = *(*byte)(unsafe.Pointer(p))
- _ = b
- p++
- }
- return true
-}
-
-// validWrite reports whether a write of the specified size can be done at address p.
-// TODO: It does this by actually doing a write and seeing if it succeeds. Do better.
-func validWrite(p uintptr, size int) (ok bool) {
- // Check for negative size and for (p + size) overflow.
- if size < 0 || uint64(^uintptr(0)-p) < uint64(size) {
- return false
- }
- defer catchFault(&ok)
- defer debug.SetPanicOnFault(debug.SetPanicOnFault(true))
- ep := p + uintptr(size)
- for p < ep {
- *(*byte)(unsafe.Pointer(p)) = *(*byte)(unsafe.Pointer(p))
- p++
- }
- return true
-}
-
-// read copies into the argument buffer the contents of memory starting at address p.
-// Its boolean return tells whether it succeeded. If it fails, no bytes were copied.
-func read(p uintptr, buf []byte) (ok bool) {
- defer catchFault(&ok)
- defer debug.SetPanicOnFault(debug.SetPanicOnFault(true))
- for i := range buf {
- buf[i] = *(*byte)(unsafe.Pointer(p))
- p++
- }
- return true
-}
-
-// write copies the argument buffer to memory starting at address p.
-// Its boolean return tells whether it succeeded. If it fails, no bytes were copied.
-func write(p uintptr, buf []byte) (ok bool) {
- defer catchFault(&ok)
- defer debug.SetPanicOnFault(debug.SetPanicOnFault(true))
- for i := range buf {
- *(*byte)(unsafe.Pointer(p)) = buf[i]
- p++
- }
- return true
-}
diff --git a/ogle/probe/probe_darwin_amd64.s b/ogle/probe/probe_darwin_amd64.s
deleted file mode 100644
index 90ec8cc..0000000
--- a/ogle/probe/probe_darwin_amd64.s
+++ /dev/null
@@ -1,38 +0,0 @@
-// 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.
-
-// TODO #include "../../cmd/ld/textflag.h"
-
-#define NOSPLIT 4
-
-// Functions that return details about our address space.
-// They use the C-defined symbols like edata and also know
-// a little about the heap and memory layout.
-
-// From the linker. Well-known but might change.
-// TODO: Is there a better way to know this?
-#define INITTEXT 0x2000
-
-// base of the address space.
-TEXT ·base(SB), NOSPLIT, $0
- MOVQ $INITTEXT, ret+0(FP)
- RET
-
-// end of the text segment.
-TEXT ·etext(SB), NOSPLIT, $0
- LEAQ etext+0(SB), BX
- MOVQ BX, ret+0(FP)
- RET
-
-// end of the data segment.
-TEXT ·edata(SB), NOSPLIT, $0
- LEAQ edata+0(SB), BX
- MOVQ BX, ret+0(FP)
- RET
-
-// end of the pre-defined address space.
-TEXT ·end(SB), NOSPLIT, $0
- LEAQ end+0(SB), BX
- MOVQ BX, ret+0(FP)
- RET
diff --git a/ogle/probe/probe_linux_amd64.s b/ogle/probe/probe_linux_amd64.s
deleted file mode 100644
index 37999a2..0000000
--- a/ogle/probe/probe_linux_amd64.s
+++ /dev/null
@@ -1,39 +0,0 @@
-// 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.
-
-// TODO #include "../../cmd/ld/textflag.h"
-
-#define NOSPLIT 4
-
-// Functions that return details about our address space.
-// They use the C-defined symbols like edata and also know
-// a little about the heap and memory layout.
-
-// From the linker. Well-known but might change.
-// TODO: Is there a better way to know this?
-#define ELFRESERVE 3072
-#define INITTEXT ((1<<22)+ELFRESERVE)
-
-// base of the address space.
-TEXT ·base(SB), NOSPLIT, $0
- MOVQ $INITTEXT, ret+0(FP)
- RET
-
-// end of the text segment.
-TEXT ·etext(SB), NOSPLIT, $0
- LEAQ etext+0(SB), BX
- MOVQ BX, ret+0(FP)
- RET
-
-// end of the data segment.
-TEXT ·edata(SB), NOSPLIT, $0
- LEAQ edata+0(SB), BX
- MOVQ BX, ret+0(FP)
- RET
-
-// end of the pre-defined address space.
-TEXT ·end(SB), NOSPLIT, $0
- LEAQ end+0(SB), BX
- MOVQ BX, ret+0(FP)
- RET
diff --git a/ogle/probe/size_amd64.go b/ogle/probe/size_amd64.go
deleted file mode 100644
index 08783a5..0000000
--- a/ogle/probe/size_amd64.go
+++ /dev/null
@@ -1,12 +0,0 @@
-// 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 probe
-
-// Sizes of values for the AMD64 architecture.
-
-const (
- ptrSize = 8
- maxInt = 1<<63 - 1
-)
diff --git a/ogle/probe/varint.go b/ogle/probe/varint.go
deleted file mode 100644
index 2d4f1b3..0000000
--- a/ogle/probe/varint.go
+++ /dev/null
@@ -1,82 +0,0 @@
-// 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 probe
-
-// This file contains an implementation of "varint" encoding and decoding.
-// Code is adapted from encoding/binary/varint.go, copied here to avoid dependencies,
-// simplified somewhat, and made local to the package.
-// It handles unsigned integers only.
-
-import (
- "errors"
- "io"
-)
-
-// maxVarintLenN is the maximum length of a varint-encoded N-bit integer.
-const (
- maxVarintLen16 = 3
- maxVarintLen32 = 5
- maxVarintLen64 = 10
-)
-
-// putUvarint encodes a uint64 into buf and returns the number of bytes written.
-// If the buffer is too small, putUvarint will panic.
-func putUvarint(buf []byte, x uint64) int {
- i := 0
- for x >= 0x80 {
- buf[i] = byte(x) | 0x80
- x >>= 7
- i++
- }
- buf[i] = byte(x)
- return i + 1
-}
-
-// getUvarint decodes a uint64 from buf and returns that value and the
-// number of bytes read (> 0). If an error occurred, the value is 0
-// and the number of bytes n is <= 0 meaning:
-//
-// n == 0: buf too small
-// n < 0: value larger than 64 bits (overflow)
-// and -n is the number of bytes read
-//
-// TODO: Unused. Delete if it doesn't get used.
-func getUvarint(buf []byte) (uint64, int) {
- var x uint64
- var s uint
- for i, b := range buf {
- if b < 0x80 {
- if i > 9 || i == 9 && b > 1 {
- return 0, -(i + 1) // overflow
- }
- return x | uint64(b)<<s, i + 1
- }
- x |= uint64(b&0x7f) << s
- s += 7
- }
- return 0, 0
-}
-
-var overflow = errors.New("ogle probe: varint overflows a 64-bit integer")
-
-// readUvarint reads an encoded unsigned integer from r and returns it as a uint64.
-func readUvarint(r io.ByteReader) (uint64, error) {
- var x uint64
- var s uint
- for i := 0; ; i++ {
- b, err := r.ReadByte()
- if err != nil {
- return x, err
- }
- if b < 0x80 {
- if i > 9 || i == 9 && b > 1 {
- return x, overflow
- }
- return x | uint64(b)<<s, nil
- }
- x |= uint64(b&0x7f) << s
- s += 7
- }
-}
diff --git a/ogle/program/local/local.go b/ogle/program/local/local.go
deleted file mode 100644
index ed9bdc8..0000000
--- a/ogle/program/local/local.go
+++ /dev/null
@@ -1,186 +0,0 @@
-// 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) Evaluate(e string) (program.Value, error) {
- req := proxyrpc.EvaluateRequest{
- Expression: e,
- }
- var resp proxyrpc.EvaluateResponse
- err := l.s.Evaluate(&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) Goroutines() ([]*program.Goroutine, error) {
- req := proxyrpc.GoroutinesRequest{}
- var resp proxyrpc.GoroutinesResponse
- err := l.s.Goroutines(&req, &resp)
- return resp.Goroutines, 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
-}
-
-func (l *Local) MapElement(m program.Map, index uint64) (program.Var, program.Var, error) {
- req := proxyrpc.MapElementRequest{Map: m, Index: index}
- var resp proxyrpc.MapElementResponse
- err := l.s.MapElement(&req, &resp)
- return resp.Key, 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
-}
diff --git a/ogle/socket/socket.go b/ogle/socket/socket.go
deleted file mode 100644
index 4745dc2..0000000
--- a/ogle/socket/socket.go
+++ /dev/null
@@ -1,107 +0,0 @@
-// 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 socket provides a way for multiple processes from the same user to
-// communicate over a Unix domain socket.
-package socket // import "golang.org/x/debug/ogle/socket"
-
-// TODO: euid instead of uid?
-// TODO: Windows support.
-
-import (
- "net"
- "os"
- "syscall"
-)
-
-// atoi is like strconv.Atoi but we aim to minimize this package's dependencies.
-func atoi(s string) (i int, ok bool) {
- for _, c := range s {
- if c < '0' || '9' < c {
- return 0, false
- }
- i = 10*i + int(c-'0')
- }
- return i, true
-}
-
-// itoa is like strconv.Itoa but we aim to minimize this package's dependencies.
-func itoa(i int) string {
- var buf [30]byte
- n := len(buf)
- neg := false
- if i < 0 {
- i = -i
- neg = true
- }
- ui := uint(i)
- for ui > 0 || n == len(buf) {
- n--
- buf[n] = byte('0' + ui%10)
- ui /= 10
- }
- if neg {
- n--
- buf[n] = '-'
- }
- return string(buf[n:])
-}
-
-func names(uid, pid int) (dirName, socketName string) {
- dirName = "/tmp/ogle-socket-uid" + itoa(uid)
- socketName = dirName + "/pid" + itoa(pid)
- return
-}
-
-// Listen creates a PID-specific socket under a UID-specific sub-directory of
-// /tmp. That sub-directory is created with 0700 permission bits (before
-// umasking), so that only processes with the same UID can dial that socket.
-func Listen() (net.Listener, error) {
- dirName, socketName := names(os.Getuid(), os.Getpid())
- if err := os.MkdirAll(dirName, 0700); err != nil {
- return nil, err
- }
- if err := os.Remove(socketName); err != nil && !os.IsNotExist(err) {
- return nil, err
- }
- return net.Listen("unix", socketName)
-}
-
-// Dial dials the Unix domain socket created by the process with the given UID
-// and PID.
-func Dial(uid, pid int) (net.Conn, error) {
- _, socketName := names(uid, pid)
- return net.Dial("unix", socketName)
-}
-
-// CollectGarbage deletes any no-longer-used sockets in the UID-specific sub-
-// directory of /tmp.
-func CollectGarbage() {
- dirName, _ := names(os.Getuid(), os.Getpid())
- dir, err := os.Open(dirName)
- if err != nil {
- return
- }
- defer dir.Close()
- fileNames, err := dir.Readdirnames(-1)
- if err != nil {
- return
- }
- for _, fileName := range fileNames {
- if len(fileName) < 3 || fileName[:3] != "pid" {
- continue
- }
- pid, ok := atoi(fileName[3:])
- if !ok {
- continue
- }
- // See if there is a process with the given PID. The os.FindProcess function
- // looks relevant, but on Unix that always succeeds even if there is no such
- // process. Instead, we send signal 0 and look for ESRCH.
- if syscall.Kill(pid, 0) != syscall.ESRCH {
- continue
- }
- os.Remove(dirName + "/" + fileName)
- }
-}
diff --git a/ogle/socket/socket_test.go b/ogle/socket/socket_test.go
deleted file mode 100644
index b07a732..0000000
--- a/ogle/socket/socket_test.go
+++ /dev/null
@@ -1,79 +0,0 @@
-// 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 socket
-
-import (
- "fmt"
- "io/ioutil"
- "os"
- "testing"
- "time"
-)
-
-func TestSocket(t *testing.T) {
- const msg = "Zoich!"
-
- l, err := Listen()
- if err != nil {
- t.Fatalf("listen: %v", err)
- }
- defer l.Close()
-
- wc := make(chan string, 1)
- go func(c chan string) {
- w, err := Dial(os.Getuid(), os.Getpid())
- if err != nil {
- c <- fmt.Sprintf("dial: %v", err)
- return
- }
- defer w.Close()
- _, err = w.Write([]byte(msg))
- if err != nil {
- c <- fmt.Sprintf("write: %v", err)
- return
- }
- c <- ""
- }(wc)
-
- rc := make(chan string, 1)
- go func(c chan string) {
- r, err := l.Accept()
- if err != nil {
- c <- fmt.Sprintf("accept: %v", err)
- return
- }
- defer r.Close()
- s, err := ioutil.ReadAll(r)
- if err != nil {
- c <- fmt.Sprintf("readAll: %v", err)
- return
- }
- c <- string(s)
- }(rc)
-
- for wc != nil || rc != nil {
- select {
- case <-time.After(100 * time.Millisecond):
- t.Fatal("timed out")
- case errStr := <-wc:
- if errStr != "" {
- t.Fatal(errStr)
- }
- wc = nil
- case got := <-rc:
- if got != msg {
- t.Fatalf("got %q, want %q", got, msg)
- }
- rc = nil
- }
- }
-}
-
-// TestCollectGarbage doesn't actually test anything, but it does collect any
-// garbage sockets that are no longer used. It is a courtesy for computers that
-// run this test suite often.
-func TestCollectGarbage(t *testing.T) {
- CollectGarbage()
-}
diff --git a/ogle/program/program.go b/program.go
similarity index 98%
rename from ogle/program/program.go
rename to program.go
index 72c0389..b988d83 100644
--- a/ogle/program/program.go
+++ b/program.go
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// Package program provides the portable interface to a program being debugged.
-package program // import "golang.org/x/debug/ogle/program"
+// Package debug provides the portable interface to a program being debugged.
+package debug // import "golang.org/x/debug"
import (
"fmt"
diff --git a/ogle/program/client/client.go b/remote/remote.go
similarity index 60%
rename from ogle/program/client/client.go
rename to remote/remote.go
index 51bf1a5..66080c0 100644
--- a/ogle/program/client/client.go
+++ b/remote/remote.go
@@ -2,34 +2,41 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// Package client provides remote access to an ogle proxy.
-package client // import "golang.org/x/debug/ogle/program/client"
+// Package remote provides remote access to a debugproxy server.
+package remote // import "golang.org/x/debug/remote"
import (
- "errors"
"fmt"
"io"
"net/rpc"
"os"
"os/exec"
- "golang.org/x/debug/ogle/program"
- "golang.org/x/debug/ogle/program/proxyrpc"
+ "golang.org/x/debug"
+ "golang.org/x/debug/server/protocol"
)
-var _ program.Program = (*Program)(nil)
-var _ program.File = (*File)(nil)
+var _ debug.Program = (*Program)(nil)
+var _ debug.File = (*File)(nil)
-// OgleproxyCmd is the path to the ogleproxy command. It is a variable in case
-// the default value, "ogleproxy", is not in the $PATH.
-var OgleproxyCmd = "ogleproxy"
+// Program implements the debug.Program interface.
+// Through that interface it provides access to a program being
+// debugged on a possibly remote machine by communicating
+// with a debugproxy adjacent to the target program.
+type Program struct {
+ client *rpc.Client
+}
-// New connects to the specified host using SSH, starts an ogle proxy
+// DebugproxyCmd is the path to the debugproxy command. It is a variable in case
+// the default value, "debugproxy", is not in the $PATH.
+var DebugproxyCmd = "debugproxy"
+
+// New connects to the specified host using SSH, starts DebugproxyCmd
// there, and creates a new program from the specified file.
// The program can then be started by the Run method.
func New(host string, textFile string) (*Program, error) {
// TODO: add args.
- cmdStrs := []string{"/usr/bin/ssh", host, OgleproxyCmd, "-text", textFile}
+ cmdStrs := []string{"/usr/bin/ssh", host, DebugproxyCmd, "-text", textFile}
if host == "localhost" {
cmdStrs = cmdStrs[2:]
}
@@ -50,21 +57,9 @@
return nil, err
}
stdout.Close()
- // Read back one line. It must start "OGLE" and we hope says "OK".
- msg, err := readLine(fromStdout)
- if err != nil {
+ if msg, err := readLine(fromStdout); err != nil {
return nil, err
- }
- switch msg {
- case "OGLE BAD":
- // Error is on next line.
- msg, err = readLine(fromStdout)
- if err == nil {
- err = errors.New(msg)
- }
- return nil, err
- case "OGLE OK":
- default:
+ } else if msg != "OK" {
// Communication error.
return nil, fmt.Errorf("unrecognized message %q", msg)
}
@@ -127,20 +122,12 @@
return werr
}
-// Program implements the similarly named ogle interface.
-// Through that interface it provides access to a program being
-// debugged on a possibly remote machine by communicating
-// with an ogle proxy adjacent to the target program.
-type Program struct {
- client *rpc.Client
-}
-
-func (p *Program) Open(name string, mode string) (program.File, error) {
- req := proxyrpc.OpenRequest{
+func (p *Program) Open(name string, mode string) (debug.File, error) {
+ req := protocol.OpenRequest{
Name: name,
Mode: mode,
}
- var resp proxyrpc.OpenResponse
+ var resp protocol.OpenResponse
err := p.client.Call("Server.Open", &req, &resp)
if err != nil {
return nil, err
@@ -152,124 +139,124 @@
return f, nil
}
-func (p *Program) Run(args ...string) (program.Status, error) {
- req := proxyrpc.RunRequest{args}
- var resp proxyrpc.RunResponse
+func (p *Program) Run(args ...string) (debug.Status, error) {
+ req := protocol.RunRequest{args}
+ var resp protocol.RunResponse
err := p.client.Call("Server.Run", &req, &resp)
if err != nil {
- return program.Status{}, err
+ return debug.Status{}, err
}
return resp.Status, nil
}
-func (p *Program) Stop() (program.Status, error) {
+func (p *Program) Stop() (debug.Status, error) {
panic("unimplemented")
}
-func (p *Program) Resume() (program.Status, error) {
- req := proxyrpc.ResumeRequest{}
- var resp proxyrpc.ResumeResponse
+func (p *Program) Resume() (debug.Status, error) {
+ req := protocol.ResumeRequest{}
+ var resp protocol.ResumeResponse
err := p.client.Call("Server.Resume", &req, &resp)
if err != nil {
- return program.Status{}, err
+ return debug.Status{}, err
}
return resp.Status, nil
}
-func (p *Program) Kill() (program.Status, error) {
+func (p *Program) Kill() (debug.Status, error) {
panic("unimplemented")
}
func (p *Program) Breakpoint(address uint64) ([]uint64, error) {
- req := proxyrpc.BreakpointRequest{
+ req := protocol.BreakpointRequest{
Address: address,
}
- var resp proxyrpc.BreakpointResponse
+ var resp protocol.BreakpointResponse
err := p.client.Call("Server.Breakpoint", &req, &resp)
return resp.PCs, err
}
func (p *Program) BreakpointAtFunction(name string) ([]uint64, error) {
- req := proxyrpc.BreakpointAtFunctionRequest{
+ req := protocol.BreakpointAtFunctionRequest{
Function: name,
}
- var resp proxyrpc.BreakpointResponse
+ var resp protocol.BreakpointResponse
err := p.client.Call("Server.BreakpointAtFunction", &req, &resp)
return resp.PCs, err
}
func (p *Program) BreakpointAtLine(file string, line uint64) ([]uint64, error) {
- req := proxyrpc.BreakpointAtLineRequest{
+ req := protocol.BreakpointAtLineRequest{
File: file,
Line: line,
}
- var resp proxyrpc.BreakpointResponse
+ var resp protocol.BreakpointResponse
err := p.client.Call("Server.BreakpointAtLine", &req, &resp)
return resp.PCs, err
}
func (p *Program) DeleteBreakpoints(pcs []uint64) error {
- req := proxyrpc.DeleteBreakpointsRequest{PCs: pcs}
- var resp proxyrpc.DeleteBreakpointsResponse
+ req := protocol.DeleteBreakpointsRequest{PCs: pcs}
+ var resp protocol.DeleteBreakpointsResponse
return p.client.Call("Server.DeleteBreakpoints", &req, &resp)
}
func (p *Program) Eval(expr string) ([]string, error) {
- req := proxyrpc.EvalRequest{
+ req := protocol.EvalRequest{
Expr: expr,
}
- var resp proxyrpc.EvalResponse
+ var resp protocol.EvalResponse
err := p.client.Call("Server.Eval", &req, &resp)
return resp.Result, err
}
-func (p *Program) Evaluate(e string) (program.Value, error) {
- req := proxyrpc.EvaluateRequest{
+func (p *Program) Evaluate(e string) (debug.Value, error) {
+ req := protocol.EvaluateRequest{
Expression: e,
}
- var resp proxyrpc.EvaluateResponse
+ var resp protocol.EvaluateResponse
err := p.client.Call("Server.Evaluate", &req, &resp)
return resp.Result, err
}
-func (p *Program) Frames(count int) ([]program.Frame, error) {
- req := proxyrpc.FramesRequest{
+func (p *Program) Frames(count int) ([]debug.Frame, error) {
+ req := protocol.FramesRequest{
Count: count,
}
- var resp proxyrpc.FramesResponse
+ var resp protocol.FramesResponse
err := p.client.Call("Server.Frames", &req, &resp)
return resp.Frames, err
}
-func (p *Program) Goroutines() ([]*program.Goroutine, error) {
- req := proxyrpc.GoroutinesRequest{}
- var resp proxyrpc.GoroutinesResponse
+func (p *Program) Goroutines() ([]*debug.Goroutine, error) {
+ req := protocol.GoroutinesRequest{}
+ var resp protocol.GoroutinesResponse
err := p.client.Call("Server.Goroutines", &req, &resp)
return resp.Goroutines, err
}
-func (p *Program) VarByName(name string) (program.Var, error) {
- req := proxyrpc.VarByNameRequest{Name: name}
- var resp proxyrpc.VarByNameResponse
+func (p *Program) VarByName(name string) (debug.Var, error) {
+ req := protocol.VarByNameRequest{Name: name}
+ var resp protocol.VarByNameResponse
err := p.client.Call("Server.VarByName", &req, &resp)
return resp.Var, err
}
-func (p *Program) Value(v program.Var) (program.Value, error) {
- req := proxyrpc.ValueRequest{Var: v}
- var resp proxyrpc.ValueResponse
+func (p *Program) Value(v debug.Var) (debug.Value, error) {
+ req := protocol.ValueRequest{Var: v}
+ var resp protocol.ValueResponse
err := p.client.Call("Server.Value", &req, &resp)
return resp.Value, err
}
-func (p *Program) MapElement(m program.Map, index uint64) (program.Var, program.Var, error) {
- req := proxyrpc.MapElementRequest{Map: m, Index: index}
- var resp proxyrpc.MapElementResponse
+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.client.Call("Server.MapElement", &req, &resp)
return resp.Key, resp.Value, err
}
-// File implements the program.File interface, providing access
+// 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.
@@ -277,32 +264,32 @@
}
func (f *File) ReadAt(p []byte, offset int64) (int, error) {
- req := proxyrpc.ReadAtRequest{
+ req := protocol.ReadAtRequest{
FD: f.fd,
Len: len(p),
Offset: offset,
}
- var resp proxyrpc.ReadAtResponse
+ var resp protocol.ReadAtResponse
err := f.prog.client.Call("Server.ReadAt", &req, &resp)
return copy(p, resp.Data), err
}
func (f *File) WriteAt(p []byte, offset int64) (int, error) {
- req := proxyrpc.WriteAtRequest{
+ req := protocol.WriteAtRequest{
FD: f.fd,
Data: p,
Offset: offset,
}
- var resp proxyrpc.WriteAtResponse
+ var resp protocol.WriteAtResponse
err := f.prog.client.Call("Server.WriteAt", &req, &resp)
return resp.Len, err
}
func (f *File) Close() error {
- req := proxyrpc.CloseRequest{
+ req := protocol.CloseRequest{
FD: f.fd,
}
- var resp proxyrpc.CloseResponse
+ var resp protocol.CloseResponse
err := f.prog.client.Call("Server.Close", &req, &resp)
return err
}
diff --git a/ogle/program/server/dwarf.go b/server/dwarf.go
similarity index 100%
rename from ogle/program/server/dwarf.go
rename to server/dwarf.go
diff --git a/ogle/program/server/eval.go b/server/eval.go
similarity index 96%
rename from ogle/program/server/eval.go
rename to server/eval.go
index 51e8a28..b7a1b68 100644
--- a/ogle/program/server/eval.go
+++ b/server/eval.go
@@ -21,8 +21,8 @@
"math"
"math/big"
+ "golang.org/x/debug"
"golang.org/x/debug/dwarf"
- "golang.org/x/debug/ogle/program"
)
const prec = 256 // precision for untyped float and complex constants.
@@ -50,7 +50,7 @@
// For address operations, v will have type pointerToValue.
// For the operands of address operations, v will have type addressableValue.
// Other types are represented using the corresponding implementation of
-// program.Value in program.go.
+// debug.Value in program.go.
//
// If an evaluation results in an error, the zero value of result is used.
type result struct {
@@ -84,7 +84,7 @@
// pointerToValue is a pointer to a value in memory.
// The evaluator constructs these as the result of address operations like "&x".
-// Unlike program.Pointer, the DWARF type stored alongside values of this type
+// Unlike debug.Pointer, the DWARF type stored alongside values of this type
// is the type of the variable, not the type of the pointer.
type pointerToValue struct {
a uint64
@@ -98,9 +98,9 @@
}
// A sliceOf is a slice created by slicing an array.
-// Unlike program.Slice, the DWARF type stored alongside a value of this type is
+// Unlike debug.Slice, the DWARF type stored alongside a value of this type is
// the type of the slice's elements, not the type of the slice.
-type sliceOf program.Slice
+type sliceOf debug.Slice
// ident is a value for representing a special identifier.
type ident string
@@ -112,7 +112,7 @@
// evalExpression evaluates a Go expression.
// If the program counter and stack pointer are nonzero, they are used to determine
// what local variables are available and where in memory they are.
-func (s *Server) evalExpression(expression string, pc, sp uint64) (program.Value, error) {
+func (s *Server) evalExpression(expression string, pc, sp uint64) (debug.Value, error) {
e := evaluator{server: s, expression: expression, pc: pc, sp: sp}
node, err := parser.ParseExpr(expression)
if err != nil {
@@ -155,11 +155,11 @@
}
return complex(r, i), nil
case untString:
- return program.String{Length: uint64(len(v)), String: string(v)}, nil
+ return debug.String{Length: uint64(len(v)), String: string(v)}, nil
case pointerToValue:
- return program.Pointer{TypeID: uint64(val.d.Common().Offset), Address: v.a}, nil
+ return debug.Pointer{TypeID: uint64(val.d.Common().Offset), Address: v.a}, nil
case sliceOf:
- return program.Slice(v), nil
+ return debug.Slice(v), nil
case nil, addressableValue:
// This case should not be reachable.
return nil, errors.New("unknown error")
@@ -286,7 +286,7 @@
case *ast.StarExpr:
x := e.evalNode(n.X, false)
switch v := x.v.(type) {
- case program.Pointer:
+ case debug.Pointer:
// x.d may be a typedef pointing to a pointer type (or a typedef pointing
// to a typedef pointing to a pointer type, etc.), so remove typedefs
// until we get the underlying pointer type.
@@ -307,7 +307,7 @@
x := e.evalNode(n.X, false)
sel := n.Sel.Name
switch v := x.v.(type) {
- case program.Struct:
+ case debug.Struct:
for _, f := range v.Fields {
if f.Name == sel {
t, err := e.server.dwarfData.Type(dwarf.Offset(f.Var.TypeID))
@@ -318,7 +318,7 @@
}
}
return e.err("struct field not found")
- case program.Pointer:
+ case debug.Pointer:
pt, ok := followTypedefs(x.d).(*dwarf.PtrType) // x.d should be a pointer to struct.
if !ok {
return e.err("invalid DWARF information for pointer")
@@ -353,7 +353,7 @@
return result{}
}
// The expression is x[index]
- if m, ok := x.v.(program.Map); ok {
+ if m, ok := x.v.(debug.Map); ok {
if getAddress {
return e.err("can't take address of map value")
}
@@ -406,7 +406,7 @@
return e.err("invalid index: " + err.Error())
}
switch v := x.v.(type) {
- case program.Array:
+ case debug.Array:
if u >= v.Length {
return e.err("array index out of bounds")
}
@@ -415,7 +415,7 @@
return e.err(err.Error())
}
return e.resultFrom(v.Element(u).Address, elemType, getAddress)
- case program.Slice:
+ case debug.Slice:
if u >= v.Length {
return e.err("slice index out of bounds")
}
@@ -429,7 +429,7 @@
return e.err("slice index out of bounds")
}
return e.resultFrom(v.Element(u).Address, x.d, getAddress)
- case program.String:
+ case debug.String:
if getAddress {
return e.err("can't take address of string element")
}
@@ -482,19 +482,19 @@
}
x := e.evalNode(n.X, false)
switch v := x.v.(type) {
- case program.Array, program.Pointer, pointerToValue:
+ case debug.Array, debug.Pointer, pointerToValue:
// This case handles the slicing of arrays and pointers to arrays.
- var arr program.Array
+ var arr debug.Array
switch v := x.v.(type) {
- case program.Array:
+ case debug.Array:
arr = v
- case program.Pointer:
+ case debug.Pointer:
pt, ok := followTypedefs(x.d).(*dwarf.PtrType)
if !ok {
return e.err("invalid DWARF type for pointer")
}
a := e.resultFrom(v.Address, pt.Type, false)
- arr, ok = a.v.(program.Array)
+ arr, ok = a.v.(debug.Array)
if !ok {
// v is a pointer to something other than an array.
return e.err("cannot slice pointer")
@@ -502,7 +502,7 @@
case pointerToValue:
a := e.resultFrom(v.a, x.d, false)
var ok bool
- arr, ok = a.v.(program.Array)
+ arr, ok = a.v.(debug.Array)
if !ok {
// v is a pointer to something other than an array.
return e.err("cannot slice pointer")
@@ -528,7 +528,7 @@
return result{
d: elemType,
v: sliceOf{
- Array: program.Array{
+ Array: debug.Array{
ElementTypeID: arr.ElementTypeID,
Address: arr.Element(low).Address,
Length: high - low,
@@ -537,7 +537,7 @@
Capacity: max - low,
},
}
- case program.Slice:
+ case debug.Slice:
if n.High == nil {
high = v.Length
} else if high > v.Capacity {
@@ -573,7 +573,7 @@
v.Length = high - low
v.Capacity = max - low
return result{x.d, v}
- case program.String:
+ case debug.String:
if n.Max != nil {
return e.err("full slice of string")
}
@@ -1331,12 +1331,12 @@
}
return result{x.d, c}
- case program.String:
- b, ok := y.v.(program.String)
+ case debug.String:
+ b, ok := y.v.(debug.String)
if !ok {
return e.err("type mismatch")
}
- var c program.String
+ var c debug.String
switch op {
// TODO: these comparison operators only use the part of the string that
// was read. Very large strings do not have their entire contents read by
@@ -1690,7 +1690,7 @@
if !ok {
e.err("couldn't construct string")
}
- return result{t, program.String{Length: uint64(len(s)), String: s}}
+ return result{t, debug.String{Length: uint64(len(s)), String: s}}
}
// getBaseType returns the *dwarf.Type with a given name.
@@ -1777,24 +1777,24 @@
case *dwarf.BoolType:
v = false
case *dwarf.PtrType:
- v = program.Pointer{TypeID: uint64(t.Common().Offset)}
+ v = debug.Pointer{TypeID: uint64(t.Common().Offset)}
case *dwarf.SliceType:
- v = program.Slice{
- Array: program.Array{
+ v = debug.Slice{
+ Array: debug.Array{
ElementTypeID: uint64(typ.ElemType.Common().Offset),
StrideBits: uint64(typ.ElemType.Common().ByteSize) * 8,
},
}
case *dwarf.StringType:
- v = program.String{}
+ v = debug.String{}
case *dwarf.InterfaceType:
- v = program.Interface{}
+ v = debug.Interface{}
case *dwarf.FuncType:
- v = program.Func{}
+ v = debug.Func{}
case *dwarf.MapType:
- v = program.Map{TypeID: uint64(t.Common().Offset)}
+ v = debug.Map{TypeID: uint64(t.Common().Offset)}
case *dwarf.ChanType:
- v = program.Channel{
+ v = debug.Channel{
ElementTypeID: uint64(typ.ElemType.Common().Offset),
Stride: uint64(typ.ElemType.Common().ByteSize),
}
@@ -1984,8 +1984,8 @@
}
case untString:
switch y.v.(type) {
- case program.String:
- return result{y.d, program.String{Length: uint64(len(a)), String: string(a)}}
+ case debug.String:
+ return result{y.d, debug.String{Length: uint64(len(a)), String: string(a)}}
}
}
return x
diff --git a/ogle/program/server/eval.m4 b/server/eval.m4
similarity index 96%
rename from ogle/program/server/eval.m4
rename to server/eval.m4
index ec48880..0e0def3 100644
--- a/ogle/program/server/eval.m4
+++ b/server/eval.m4
@@ -21,8 +21,8 @@
"math"
"math/big"
+ "golang.org/x/debug"
"golang.org/x/debug/dwarf"
- "golang.org/x/debug/ogle/program"
)
const prec = 256 // precision for untyped float and complex constants.
@@ -50,7 +50,7 @@
// For address operations, v will have type pointerToValue.
// For the operands of address operations, v will have type addressableValue.
// Other types are represented using the corresponding implementation of
-// program.Value in program.go.
+// debug.Value in program.go.
//
// If an evaluation results in an error, the zero value of result is used.
type result struct {
@@ -84,7 +84,7 @@
// pointerToValue is a pointer to a value in memory.
// The evaluator constructs these as the result of address operations like "&x".
-// Unlike program.Pointer, the DWARF type stored alongside values of this type
+// Unlike debug.Pointer, the DWARF type stored alongside values of this type
// is the type of the variable, not the type of the pointer.
type pointerToValue struct {
a uint64
@@ -98,9 +98,9 @@
}
// A sliceOf is a slice created by slicing an array.
-// Unlike program.Slice, the DWARF type stored alongside a value of this type is
+// Unlike debug.Slice, the DWARF type stored alongside a value of this type is
// the type of the slice's elements, not the type of the slice.
-type sliceOf program.Slice
+type sliceOf debug.Slice
// ident is a value for representing a special identifier.
type ident string
@@ -112,7 +112,7 @@
// evalExpression evaluates a Go expression.
// If the program counter and stack pointer are nonzero, they are used to determine
// what local variables are available and where in memory they are.
-func (s *Server) evalExpression(expression string, pc, sp uint64) (program.Value, error) {
+func (s *Server) evalExpression(expression string, pc, sp uint64) (debug.Value, error) {
e := evaluator{server: s, expression: expression, pc: pc, sp: sp}
node, err := parser.ParseExpr(expression)
if err != nil {
@@ -155,11 +155,11 @@
}
return complex(r, i), nil
case untString:
- return program.String{Length: uint64(len(v)), String: string(v)}, nil
+ return debug.String{Length: uint64(len(v)), String: string(v)}, nil
case pointerToValue:
- return program.Pointer{TypeID: uint64(val.d.Common().Offset), Address: v.a}, nil
+ return debug.Pointer{TypeID: uint64(val.d.Common().Offset), Address: v.a}, nil
case sliceOf:
- return program.Slice(v), nil
+ return debug.Slice(v), nil
case nil, addressableValue:
// This case should not be reachable.
return nil, errors.New("unknown error")
@@ -286,7 +286,7 @@
case *ast.StarExpr:
x := e.evalNode(n.X, false)
switch v := x.v.(type) {
- case program.Pointer:
+ case debug.Pointer:
// x.d may be a typedef pointing to a pointer type (or a typedef pointing
// to a typedef pointing to a pointer type, etc.), so remove typedefs
// until we get the underlying pointer type.
@@ -307,7 +307,7 @@
x := e.evalNode(n.X, false)
sel := n.Sel.Name
switch v := x.v.(type) {
- case program.Struct:
+ case debug.Struct:
for _, f := range v.Fields {
if f.Name == sel {
t, err := e.server.dwarfData.Type(dwarf.Offset(f.Var.TypeID))
@@ -318,7 +318,7 @@
}
}
return e.err("struct field not found")
- case program.Pointer:
+ case debug.Pointer:
pt, ok := followTypedefs(x.d).(*dwarf.PtrType) // x.d should be a pointer to struct.
if !ok {
return e.err("invalid DWARF information for pointer")
@@ -353,7 +353,7 @@
return result{}
}
// The expression is x[index]
- if m, ok := x.v.(program.Map); ok {
+ if m, ok := x.v.(debug.Map); ok {
if getAddress {
return e.err("can't take address of map value")
}
@@ -406,7 +406,7 @@
return e.err("invalid index: " + err.Error())
}
switch v := x.v.(type) {
- case program.Array:
+ case debug.Array:
if u >= v.Length {
return e.err("array index out of bounds")
}
@@ -415,7 +415,7 @@
return e.err(err.Error())
}
return e.resultFrom(v.Element(u).Address, elemType, getAddress)
- case program.Slice:
+ case debug.Slice:
if u >= v.Length {
return e.err("slice index out of bounds")
}
@@ -429,7 +429,7 @@
return e.err("slice index out of bounds")
}
return e.resultFrom(v.Element(u).Address, x.d, getAddress)
- case program.String:
+ case debug.String:
if getAddress {
return e.err("can't take address of string element")
}
@@ -482,19 +482,19 @@
}
x := e.evalNode(n.X, false)
switch v := x.v.(type) {
- case program.Array, program.Pointer, pointerToValue:
+ case debug.Array, debug.Pointer, pointerToValue:
// This case handles the slicing of arrays and pointers to arrays.
- var arr program.Array
+ var arr debug.Array
switch v := x.v.(type) {
- case program.Array:
+ case debug.Array:
arr = v
- case program.Pointer:
+ case debug.Pointer:
pt, ok := followTypedefs(x.d).(*dwarf.PtrType)
if !ok {
return e.err("invalid DWARF type for pointer")
}
a := e.resultFrom(v.Address, pt.Type, false)
- arr, ok = a.v.(program.Array)
+ arr, ok = a.v.(debug.Array)
if !ok {
// v is a pointer to something other than an array.
return e.err("cannot slice pointer")
@@ -502,7 +502,7 @@
case pointerToValue:
a := e.resultFrom(v.a, x.d, false)
var ok bool
- arr, ok = a.v.(program.Array)
+ arr, ok = a.v.(debug.Array)
if !ok {
// v is a pointer to something other than an array.
return e.err("cannot slice pointer")
@@ -528,7 +528,7 @@
return result{
d: elemType,
v: sliceOf{
- Array: program.Array{
+ Array: debug.Array{
ElementTypeID: arr.ElementTypeID,
Address: arr.Element(low).Address,
Length: high - low,
@@ -537,7 +537,7 @@
Capacity: max - low,
},
}
- case program.Slice:
+ case debug.Slice:
if n.High == nil {
high = v.Length
} else if high > v.Capacity {
@@ -573,7 +573,7 @@
v.Length = high - low
v.Capacity = max - low
return result{x.d, v}
- case program.String:
+ case debug.String:
if n.Max != nil {
return e.err("full slice of string")
}
@@ -939,12 +939,12 @@
}
return result{x.d, c}
- case program.String:
- b, ok := y.v.(program.String)
+ case debug.String:
+ b, ok := y.v.(debug.String)
if !ok {
return e.err("type mismatch")
}
- var c program.String
+ var c debug.String
switch op {
// TODO: these comparison operators only use the part of the string that
// was read. Very large strings do not have their entire contents read by
@@ -1298,7 +1298,7 @@
if !ok {
e.err("couldn't construct string")
}
- return result{t, program.String{Length: uint64(len(s)), String: s}}
+ return result{t, debug.String{Length: uint64(len(s)), String: s}}
}
// getBaseType returns the *dwarf.Type with a given name.
@@ -1385,24 +1385,24 @@
case *dwarf.BoolType:
v = false
case *dwarf.PtrType:
- v = program.Pointer{TypeID: uint64(t.Common().Offset)}
+ v = debug.Pointer{TypeID: uint64(t.Common().Offset)}
case *dwarf.SliceType:
- v = program.Slice{
- Array: program.Array{
+ v = debug.Slice{
+ Array: debug.Array{
ElementTypeID: uint64(typ.ElemType.Common().Offset),
StrideBits: uint64(typ.ElemType.Common().ByteSize) * 8,
},
}
case *dwarf.StringType:
- v = program.String{}
+ v = debug.String{}
case *dwarf.InterfaceType:
- v = program.Interface{}
+ v = debug.Interface{}
case *dwarf.FuncType:
- v = program.Func{}
+ v = debug.Func{}
case *dwarf.MapType:
- v = program.Map{TypeID: uint64(t.Common().Offset)}
+ v = debug.Map{TypeID: uint64(t.Common().Offset)}
case *dwarf.ChanType:
- v = program.Channel{
+ v = debug.Channel{
ElementTypeID: uint64(typ.ElemType.Common().Offset),
Stride: uint64(typ.ElemType.Common().ByteSize),
}
@@ -1592,8 +1592,8 @@
}
case untString:
switch y.v.(type) {
- case program.String:
- return result{y.d, program.String{Length: uint64(len(a)), String: string(a)}}
+ case debug.String:
+ return result{y.d, debug.String{Length: uint64(len(a)), String: string(a)}}
}
}
return x
diff --git a/ogle/program/server/peek.go b/server/peek.go
similarity index 100%
rename from ogle/program/server/peek.go
rename to server/peek.go
diff --git a/ogle/program/server/print.go b/server/print.go
similarity index 99%
rename from ogle/program/server/print.go
rename to server/print.go
index 0ec0e5c..927988a 100644
--- a/ogle/program/server/print.go
+++ b/server/print.go
@@ -8,8 +8,8 @@
"bytes"
"fmt"
+ "golang.org/x/debug/arch"
"golang.org/x/debug/dwarf"
- "golang.org/x/debug/ogle/arch"
)
// typeAndAddress associates an address in the target with a DWARF type.
diff --git a/ogle/program/proxyrpc/proxyrpc.go b/server/protocol/protocol.go
similarity index 69%
rename from ogle/program/proxyrpc/proxyrpc.go
rename to server/protocol/protocol.go
index b6636f8..c08b895 100644
--- a/ogle/program/proxyrpc/proxyrpc.go
+++ b/server/protocol/protocol.go
@@ -2,27 +2,26 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// Package proxyrpc defines the types used to represent the RPC calls
-// used to the ogleproxy.
-package proxyrpc // import "golang.org/x/debug/ogle/program/proxyrpc"
+// Package protocol defines the types used to represent calls to the debug server.
+package protocol // import "golang.org/x/debug/server/protocol"
import (
"encoding/gob"
- "golang.org/x/debug/ogle/program"
+ "golang.org/x/debug"
)
func init() {
- // Register implementations of program.Value with gob.
- gob.Register(program.Pointer{})
- gob.Register(program.Array{})
- gob.Register(program.Struct{})
- gob.Register(program.Slice{})
- gob.Register(program.Map{})
- gob.Register(program.String{})
- gob.Register(program.Channel{})
- gob.Register(program.Func{})
- gob.Register(program.Interface{})
+ // Register implementations of debug.Value with gob.
+ gob.Register(debug.Pointer{})
+ gob.Register(debug.Array{})
+ gob.Register(debug.Struct{})
+ gob.Register(debug.Slice{})
+ gob.Register(debug.Map{})
+ gob.Register(debug.String{})
+ gob.Register(debug.Channel{})
+ gob.Register(debug.Func{})
+ gob.Register(debug.Interface{})
}
// For regularity, each method has a unique Request and a Response type even
@@ -73,14 +72,14 @@
}
type RunResponse struct {
- Status program.Status
+ Status debug.Status
}
type ResumeRequest struct {
}
type ResumeResponse struct {
- Status program.Status
+ Status debug.Status
}
type BreakpointRequest struct {
@@ -120,7 +119,7 @@
}
type EvaluateResponse struct {
- Result program.Value
+ Result debug.Value
}
type FramesRequest struct {
@@ -128,7 +127,7 @@
}
type FramesResponse struct {
- Frames []program.Frame
+ Frames []debug.Frame
}
type VarByNameRequest struct {
@@ -136,30 +135,30 @@
}
type VarByNameResponse struct {
- Var program.Var
+ Var debug.Var
}
type ValueRequest struct {
- Var program.Var
+ Var debug.Var
}
type ValueResponse struct {
- Value program.Value
+ Value debug.Value
}
type MapElementRequest struct {
- Map program.Map
+ Map debug.Map
Index uint64
}
type MapElementResponse struct {
- Key program.Var
- Value program.Var
+ Key debug.Var
+ Value debug.Var
}
type GoroutinesRequest struct {
}
type GoroutinesResponse struct {
- Goroutines []*program.Goroutine
+ Goroutines []*debug.Goroutine
}
diff --git a/ogle/program/server/ptrace.go b/server/ptrace.go
similarity index 100%
rename from ogle/program/server/ptrace.go
rename to server/ptrace.go
diff --git a/ogle/program/server/server.go b/server/server.go
similarity index 78%
rename from ogle/program/server/server.go
rename to server/server.go
index 2d86704..584ed5b 100644
--- a/ogle/program/server/server.go
+++ b/server/server.go
@@ -4,7 +4,7 @@
// Package server provides RPC access to a local program being debugged.
// It is the remote end of the client implementation of the Program interface.
-package server // import "golang.org/x/debug/ogle/program/server"
+package server // import "golang.org/x/debug/server"
//go:generate sh -c "m4 -P eval.m4 > eval.go"
@@ -19,12 +19,12 @@
"sync"
"syscall"
+ "golang.org/x/debug"
+ "golang.org/x/debug/arch"
"golang.org/x/debug/dwarf"
"golang.org/x/debug/elf"
"golang.org/x/debug/macho"
- "golang.org/x/debug/ogle/arch"
- "golang.org/x/debug/ogle/program"
- "golang.org/x/debug/ogle/program/proxyrpc"
+ "golang.org/x/debug/server/protocol"
)
type breakpoint struct {
@@ -58,7 +58,7 @@
printer *Printer
// goroutineStack reads the stack of a (non-running) goroutine.
- goroutineStack func(uint64) ([]program.Frame, error)
+ goroutineStack func(uint64) ([]debug.Frame, error)
goroutineStackOnce sync.Once
}
@@ -154,38 +154,38 @@
func (s *Server) dispatch(c call) {
switch req := c.req.(type) {
- case *proxyrpc.BreakpointRequest:
- c.errc <- s.handleBreakpoint(req, c.resp.(*proxyrpc.BreakpointResponse))
- case *proxyrpc.BreakpointAtFunctionRequest:
- c.errc <- s.handleBreakpointAtFunction(req, c.resp.(*proxyrpc.BreakpointResponse))
- case *proxyrpc.BreakpointAtLineRequest:
- c.errc <- s.handleBreakpointAtLine(req, c.resp.(*proxyrpc.BreakpointResponse))
- case *proxyrpc.DeleteBreakpointsRequest:
- c.errc <- s.handleDeleteBreakpoints(req, c.resp.(*proxyrpc.DeleteBreakpointsResponse))
- case *proxyrpc.CloseRequest:
- c.errc <- s.handleClose(req, c.resp.(*proxyrpc.CloseResponse))
- case *proxyrpc.EvalRequest:
- c.errc <- s.handleEval(req, c.resp.(*proxyrpc.EvalResponse))
- case *proxyrpc.EvaluateRequest:
- c.errc <- s.handleEvaluate(req, c.resp.(*proxyrpc.EvaluateResponse))
- case *proxyrpc.FramesRequest:
- c.errc <- s.handleFrames(req, c.resp.(*proxyrpc.FramesResponse))
- case *proxyrpc.OpenRequest:
- c.errc <- s.handleOpen(req, c.resp.(*proxyrpc.OpenResponse))
- case *proxyrpc.ReadAtRequest:
- c.errc <- s.handleReadAt(req, c.resp.(*proxyrpc.ReadAtResponse))
- case *proxyrpc.ResumeRequest:
- c.errc <- s.handleResume(req, c.resp.(*proxyrpc.ResumeResponse))
- case *proxyrpc.RunRequest:
- c.errc <- s.handleRun(req, c.resp.(*proxyrpc.RunResponse))
- case *proxyrpc.VarByNameRequest:
- c.errc <- s.handleVarByName(req, c.resp.(*proxyrpc.VarByNameResponse))
- case *proxyrpc.ValueRequest:
- c.errc <- s.handleValue(req, c.resp.(*proxyrpc.ValueResponse))
- case *proxyrpc.MapElementRequest:
- c.errc <- s.handleMapElement(req, c.resp.(*proxyrpc.MapElementResponse))
- case *proxyrpc.GoroutinesRequest:
- c.errc <- s.handleGoroutines(req, c.resp.(*proxyrpc.GoroutinesResponse))
+ case *protocol.BreakpointRequest:
+ c.errc <- s.handleBreakpoint(req, c.resp.(*protocol.BreakpointResponse))
+ case *protocol.BreakpointAtFunctionRequest:
+ c.errc <- s.handleBreakpointAtFunction(req, c.resp.(*protocol.BreakpointResponse))
+ case *protocol.BreakpointAtLineRequest:
+ c.errc <- s.handleBreakpointAtLine(req, c.resp.(*protocol.BreakpointResponse))
+ case *protocol.DeleteBreakpointsRequest:
+ c.errc <- s.handleDeleteBreakpoints(req, c.resp.(*protocol.DeleteBreakpointsResponse))
+ case *protocol.CloseRequest:
+ c.errc <- s.handleClose(req, c.resp.(*protocol.CloseResponse))
+ case *protocol.EvalRequest:
+ c.errc <- s.handleEval(req, c.resp.(*protocol.EvalResponse))
+ case *protocol.EvaluateRequest:
+ c.errc <- s.handleEvaluate(req, c.resp.(*protocol.EvaluateResponse))
+ case *protocol.FramesRequest:
+ c.errc <- s.handleFrames(req, c.resp.(*protocol.FramesResponse))
+ case *protocol.OpenRequest:
+ c.errc <- s.handleOpen(req, c.resp.(*protocol.OpenResponse))
+ case *protocol.ReadAtRequest:
+ c.errc <- s.handleReadAt(req, c.resp.(*protocol.ReadAtResponse))
+ case *protocol.ResumeRequest:
+ c.errc <- s.handleResume(req, c.resp.(*protocol.ResumeResponse))
+ case *protocol.RunRequest:
+ c.errc <- s.handleRun(req, c.resp.(*protocol.RunResponse))
+ case *protocol.VarByNameRequest:
+ c.errc <- s.handleVarByName(req, c.resp.(*protocol.VarByNameResponse))
+ case *protocol.ValueRequest:
+ c.errc <- s.handleValue(req, c.resp.(*protocol.ValueResponse))
+ case *protocol.MapElementRequest:
+ c.errc <- s.handleMapElement(req, c.resp.(*protocol.MapElementResponse))
+ case *protocol.GoroutinesRequest:
+ c.errc <- s.handleGoroutines(req, c.resp.(*protocol.GoroutinesResponse))
default:
panic(fmt.Sprintf("unexpected call request type %T", c.req))
}
@@ -200,14 +200,14 @@
type file struct {
mode string
index int
- f program.File
+ f debug.File
}
-func (s *Server) Open(req *proxyrpc.OpenRequest, resp *proxyrpc.OpenResponse) error {
+func (s *Server) Open(req *protocol.OpenRequest, resp *protocol.OpenResponse) error {
return s.call(s.otherc, req, resp)
}
-func (s *Server) handleOpen(req *proxyrpc.OpenRequest, resp *proxyrpc.OpenResponse) error {
+func (s *Server) handleOpen(req *protocol.OpenRequest, resp *protocol.OpenResponse) error {
// TODO: Better simulation. For now we just open the named OS file.
var flag int
switch req.Mode {
@@ -241,11 +241,11 @@
return nil
}
-func (s *Server) ReadAt(req *proxyrpc.ReadAtRequest, resp *proxyrpc.ReadAtResponse) error {
+func (s *Server) ReadAt(req *protocol.ReadAtRequest, resp *protocol.ReadAtResponse) error {
return s.call(s.otherc, req, resp)
}
-func (s *Server) handleReadAt(req *proxyrpc.ReadAtRequest, resp *proxyrpc.ReadAtResponse) error {
+func (s *Server) handleReadAt(req *protocol.ReadAtRequest, resp *protocol.ReadAtResponse) error {
fd := req.FD
if fd < 0 || len(s.files) <= fd || s.files[fd] == nil {
return fmt.Errorf("ReadAt: bad file descriptor %d", fd)
@@ -257,11 +257,11 @@
return err
}
-func (s *Server) Close(req *proxyrpc.CloseRequest, resp *proxyrpc.CloseResponse) error {
+func (s *Server) Close(req *protocol.CloseRequest, resp *protocol.CloseResponse) error {
return s.call(s.otherc, req, resp)
}
-func (s *Server) handleClose(req *proxyrpc.CloseRequest, resp *proxyrpc.CloseResponse) error {
+func (s *Server) handleClose(req *protocol.CloseRequest, resp *protocol.CloseResponse) error {
fd := req.FD
if fd < 0 || fd >= len(s.files) || s.files[fd] == nil {
return fmt.Errorf("Close: bad file descriptor %d", fd)
@@ -272,11 +272,11 @@
return err
}
-func (s *Server) Run(req *proxyrpc.RunRequest, resp *proxyrpc.RunResponse) error {
+func (s *Server) Run(req *protocol.RunRequest, resp *protocol.RunResponse) error {
return s.call(s.otherc, req, resp)
}
-func (s *Server) handleRun(req *proxyrpc.RunRequest, resp *proxyrpc.RunResponse) error {
+func (s *Server) handleRun(req *protocol.RunRequest, resp *protocol.RunResponse) error {
if s.proc != nil {
s.proc.Kill()
s.proc = nil
@@ -305,11 +305,11 @@
return nil
}
-func (s *Server) Resume(req *proxyrpc.ResumeRequest, resp *proxyrpc.ResumeResponse) error {
+func (s *Server) Resume(req *protocol.ResumeRequest, resp *protocol.ResumeResponse) error {
return s.call(s.otherc, req, resp)
}
-func (s *Server) handleResume(req *proxyrpc.ResumeRequest, resp *proxyrpc.ResumeResponse) error {
+func (s *Server) handleResume(req *protocol.ResumeRequest, resp *protocol.ResumeResponse) error {
if s.proc == nil {
return fmt.Errorf("Resume: Run did not successfully start a process")
}
@@ -412,19 +412,19 @@
}
}
-func (s *Server) Breakpoint(req *proxyrpc.BreakpointRequest, resp *proxyrpc.BreakpointResponse) error {
+func (s *Server) Breakpoint(req *protocol.BreakpointRequest, resp *protocol.BreakpointResponse) error {
return s.call(s.breakpointc, req, resp)
}
-func (s *Server) handleBreakpoint(req *proxyrpc.BreakpointRequest, resp *proxyrpc.BreakpointResponse) error {
+func (s *Server) handleBreakpoint(req *protocol.BreakpointRequest, resp *protocol.BreakpointResponse) error {
return s.addBreakpoints([]uint64{req.Address}, resp)
}
-func (s *Server) BreakpointAtFunction(req *proxyrpc.BreakpointAtFunctionRequest, resp *proxyrpc.BreakpointResponse) error {
+func (s *Server) BreakpointAtFunction(req *protocol.BreakpointAtFunctionRequest, resp *protocol.BreakpointResponse) error {
return s.call(s.breakpointc, req, resp)
}
-func (s *Server) handleBreakpointAtFunction(req *proxyrpc.BreakpointAtFunctionRequest, resp *proxyrpc.BreakpointResponse) error {
+func (s *Server) handleBreakpointAtFunction(req *protocol.BreakpointAtFunctionRequest, resp *protocol.BreakpointResponse) error {
pc, err := s.lookupFunction(req.Function)
if err != nil {
return err
@@ -432,11 +432,11 @@
return s.addBreakpoints([]uint64{pc}, resp)
}
-func (s *Server) BreakpointAtLine(req *proxyrpc.BreakpointAtLineRequest, resp *proxyrpc.BreakpointResponse) error {
+func (s *Server) BreakpointAtLine(req *protocol.BreakpointAtLineRequest, resp *protocol.BreakpointResponse) error {
return s.call(s.breakpointc, req, resp)
}
-func (s *Server) handleBreakpointAtLine(req *proxyrpc.BreakpointAtLineRequest, resp *proxyrpc.BreakpointResponse) error {
+func (s *Server) handleBreakpointAtLine(req *protocol.BreakpointAtLineRequest, resp *protocol.BreakpointResponse) error {
if s.dwarfData == nil {
return fmt.Errorf("no DWARF data")
}
@@ -448,7 +448,7 @@
}
// addBreakpoints adds breakpoints at the addresses in pcs, then stores pcs in the response.
-func (s *Server) addBreakpoints(pcs []uint64, resp *proxyrpc.BreakpointResponse) error {
+func (s *Server) addBreakpoints(pcs []uint64, resp *protocol.BreakpointResponse) error {
// Get the original code at each address with ptracePeek.
bps := make([]breakpoint, 0, len(pcs))
for _, pc := range pcs {
@@ -470,11 +470,11 @@
return nil
}
-func (s *Server) DeleteBreakpoints(req *proxyrpc.DeleteBreakpointsRequest, resp *proxyrpc.DeleteBreakpointsResponse) error {
+func (s *Server) DeleteBreakpoints(req *protocol.DeleteBreakpointsRequest, resp *protocol.DeleteBreakpointsResponse) error {
return s.call(s.breakpointc, req, resp)
}
-func (s *Server) handleDeleteBreakpoints(req *proxyrpc.DeleteBreakpointsRequest, resp *proxyrpc.DeleteBreakpointsResponse) error {
+func (s *Server) handleDeleteBreakpoints(req *protocol.DeleteBreakpointsRequest, resp *protocol.DeleteBreakpointsResponse) error {
for _, pc := range req.PCs {
delete(s.breakpoints, pc)
}
@@ -501,11 +501,11 @@
return nil
}
-func (s *Server) Eval(req *proxyrpc.EvalRequest, resp *proxyrpc.EvalResponse) error {
+func (s *Server) Eval(req *protocol.EvalRequest, resp *protocol.EvalResponse) error {
return s.call(s.otherc, req, resp)
}
-func (s *Server) handleEval(req *proxyrpc.EvalRequest, resp *proxyrpc.EvalResponse) (err error) {
+func (s *Server) handleEval(req *protocol.EvalRequest, resp *protocol.EvalResponse) (err error) {
resp.Result, err = s.eval(req.Expr)
return err
}
@@ -566,11 +566,11 @@
return nil, fmt.Errorf("bad expression syntax: %q", expr)
}
-func (s *Server) Evaluate(req *proxyrpc.EvaluateRequest, resp *proxyrpc.EvaluateResponse) error {
+func (s *Server) Evaluate(req *protocol.EvaluateRequest, resp *protocol.EvaluateResponse) error {
return s.call(s.otherc, req, resp)
}
-func (s *Server) handleEvaluate(req *proxyrpc.EvaluateRequest, resp *proxyrpc.EvaluateResponse) (err error) {
+func (s *Server) handleEvaluate(req *protocol.EvaluateRequest, resp *protocol.EvaluateResponse) (err error) {
resp.Result, err = s.evalExpression(req.Expression, s.stoppedRegs.Rip, s.stoppedRegs.Rsp)
return err
}
@@ -602,11 +602,11 @@
return addr, nil
}
-func (s *Server) Frames(req *proxyrpc.FramesRequest, resp *proxyrpc.FramesResponse) error {
+func (s *Server) Frames(req *protocol.FramesRequest, resp *protocol.FramesResponse) error {
return s.call(s.otherc, req, resp)
}
-func (s *Server) handleFrames(req *proxyrpc.FramesRequest, resp *proxyrpc.FramesResponse) error {
+func (s *Server) handleFrames(req *protocol.FramesRequest, resp *protocol.FramesResponse) error {
// TODO: verify that we're stopped.
if s.topOfStackAddrs == nil {
if err := s.evaluateTopOfStackAddrs(); err != nil {
@@ -624,8 +624,8 @@
}
// walkStack returns up to the requested number of stack frames.
-func (s *Server) walkStack(pc, sp uint64, count int) ([]program.Frame, error) {
- var frames []program.Frame
+func (s *Server) walkStack(pc, sp uint64, count int) ([]debug.Frame, error) {
+ var frames []debug.Frame
var buf [8]byte
b := new(bytes.Buffer)
@@ -647,7 +647,7 @@
if err != nil {
return frames, err
}
- frame := program.Frame{
+ frame := debug.Frame{
PC: pc,
SP: sp,
File: file,
@@ -667,7 +667,7 @@
// TODO: report variables we couldn't parse?
if entry.Tag == dwarf.TagFormalParameter {
if v, err := s.parseParameterOrLocal(entry, fp); err == nil {
- frame.Params = append(frame.Params, program.Param(v))
+ frame.Params = append(frame.Params, debug.Param(v))
}
}
if entry.Tag == dwarf.TagVariable {
@@ -694,8 +694,8 @@
// parseParameterOrLocal parses the entry for a function parameter or local
// variable, which are both specified the same way. fp contains the frame
// pointer, which is used to calculate the variable location.
-func (s *Server) parseParameterOrLocal(entry *dwarf.Entry, fp uint64) (program.LocalVar, error) {
- var v program.LocalVar
+func (s *Server) parseParameterOrLocal(entry *dwarf.Entry, fp uint64) (debug.LocalVar, error) {
+ var v debug.LocalVar
v.Name, _ = entry.Val(dwarf.AttrName).(string)
if off, err := s.dwarfData.EntryTypeOffset(entry); err != nil {
return v, err
@@ -775,11 +775,11 @@
return false
}
-func (s *Server) VarByName(req *proxyrpc.VarByNameRequest, resp *proxyrpc.VarByNameResponse) error {
+func (s *Server) VarByName(req *protocol.VarByNameRequest, resp *protocol.VarByNameResponse) error {
return s.call(s.otherc, req, resp)
}
-func (s *Server) handleVarByName(req *proxyrpc.VarByNameRequest, resp *proxyrpc.VarByNameResponse) error {
+func (s *Server) handleVarByName(req *protocol.VarByNameRequest, resp *protocol.VarByNameResponse) error {
entry, err := s.dwarfData.LookupEntry(req.Name)
if err != nil {
return fmt.Errorf("variable %s: %s", req.Name, err)
@@ -800,11 +800,11 @@
return nil
}
-func (s *Server) Value(req *proxyrpc.ValueRequest, resp *proxyrpc.ValueResponse) error {
+func (s *Server) Value(req *protocol.ValueRequest, resp *protocol.ValueResponse) error {
return s.call(s.otherc, req, resp)
}
-func (s *Server) handleValue(req *proxyrpc.ValueRequest, resp *proxyrpc.ValueResponse) error {
+func (s *Server) handleValue(req *protocol.ValueRequest, resp *protocol.ValueResponse) error {
t, err := s.dwarfData.Type(dwarf.Offset(req.Var.TypeID))
if err != nil {
return err
@@ -813,11 +813,11 @@
return err
}
-func (s *Server) MapElement(req *proxyrpc.MapElementRequest, resp *proxyrpc.MapElementResponse) error {
+func (s *Server) MapElement(req *protocol.MapElementRequest, resp *protocol.MapElementResponse) error {
return s.call(s.otherc, req, resp)
}
-func (s *Server) handleMapElement(req *proxyrpc.MapElementRequest, resp *proxyrpc.MapElementResponse) error {
+func (s *Server) handleMapElement(req *protocol.MapElementRequest, resp *protocol.MapElementResponse) error {
t, err := s.dwarfData.Type(dwarf.Offset(req.Map.TypeID))
if err != nil {
return err
@@ -833,8 +833,8 @@
fn := func(keyAddr, valAddr uint64, keyType, valType dwarf.Type) bool {
count++
if count == req.Index+1 {
- resp.Key = program.Var{TypeID: uint64(keyType.Common().Offset), Address: keyAddr}
- resp.Value = program.Var{TypeID: uint64(valType.Common().Offset), Address: valAddr}
+ resp.Key = debug.Var{TypeID: uint64(keyType.Common().Offset), Address: keyAddr}
+ resp.Value = debug.Var{TypeID: uint64(valType.Common().Offset), Address: valAddr}
return false
}
return true
@@ -849,33 +849,33 @@
return nil
}
-func (s *Server) Goroutines(req *proxyrpc.GoroutinesRequest, resp *proxyrpc.GoroutinesResponse) error {
+func (s *Server) Goroutines(req *protocol.GoroutinesRequest, resp *protocol.GoroutinesResponse) error {
return s.call(s.otherc, req, resp)
}
-const invalidStatus program.GoroutineStatus = 99
+const invalidStatus debug.GoroutineStatus = 99
var (
- gStatus = [...]program.GoroutineStatus{
- 0: program.Queued, // _Gidle
- 1: program.Queued, // _Grunnable
- 2: program.Running, // _Grunning
- 3: program.Blocked, // _Gsyscall
- 4: program.Blocked, // _Gwaiting
- 5: invalidStatus, // _Gmoribund_unused
- 6: invalidStatus, // _Gdead
- 7: invalidStatus, // _Genqueue
- 8: program.Running, // _Gcopystack
+ gStatus = [...]debug.GoroutineStatus{
+ 0: debug.Queued, // _Gidle
+ 1: debug.Queued, // _Grunnable
+ 2: debug.Running, // _Grunning
+ 3: debug.Blocked, // _Gsyscall
+ 4: debug.Blocked, // _Gwaiting
+ 5: invalidStatus, // _Gmoribund_unused
+ 6: invalidStatus, // _Gdead
+ 7: invalidStatus, // _Genqueue
+ 8: debug.Running, // _Gcopystack
}
- gScanStatus = [...]program.GoroutineStatus{
- 0: invalidStatus, // _Gscan + _Gidle
- 1: program.Queued, // _Gscanrunnable
- 2: program.Running, // _Gscanrunning
- 3: program.Blocked, // _Gscansyscall
- 4: program.Blocked, // _Gscanwaiting
- 5: invalidStatus, // _Gscan + _Gmoribund_unused
- 6: invalidStatus, // _Gscan + _Gdead
- 7: program.Queued, // _Gscanenqueue
+ gScanStatus = [...]debug.GoroutineStatus{
+ 0: invalidStatus, // _Gscan + _Gidle
+ 1: debug.Queued, // _Gscanrunnable
+ 2: debug.Running, // _Gscanrunning
+ 3: debug.Blocked, // _Gscansyscall
+ 4: debug.Blocked, // _Gscanwaiting
+ 5: invalidStatus, // _Gscan + _Gmoribund_unused
+ 6: invalidStatus, // _Gscan + _Gdead
+ 7: debug.Queued, // _Gscanenqueue
}
gStatusString = [...]string{
0: "idle",
@@ -894,7 +894,7 @@
}
)
-func (s *Server) handleGoroutines(req *proxyrpc.GoroutinesRequest, resp *proxyrpc.GoroutinesResponse) error {
+func (s *Server) handleGoroutines(req *protocol.GoroutinesRequest, resp *protocol.GoroutinesResponse) error {
// Get DWARF type information for runtime.g.
ge, err := s.dwarfData.LookupEntry("runtime.g")
if err != nil {
@@ -972,7 +972,7 @@
if err != nil {
return err
}
- gr := program.Goroutine{}
+ gr := debug.Goroutine{}
// Read status from the field named "atomicstatus" or "status".
status, err := s.peekUintStructField(gType, g, "atomicstatus")
@@ -1034,7 +1034,7 @@
if gopc, err := s.peekUintStructField(gType, g, "gopc"); err == nil {
gr.Caller = functionName(gopc)
}
- if gr.Status != program.Running {
+ if gr.Status != debug.Running {
// TODO: running goroutines too.
gr.StackFrames, _ = s.goroutineStack(g)
}
@@ -1054,7 +1054,7 @@
// If we fail to read the DWARF data needed for s.goroutineStack, calling it
// will always return the error that occurred during initialization.
var err error // err is captured by the func below.
- s.goroutineStack = func(gAddr uint64) ([]program.Frame, error) {
+ s.goroutineStack = func(gAddr uint64) ([]debug.Frame, error) {
return nil, err
}
@@ -1099,7 +1099,7 @@
}
}
- s.goroutineStack = func(gAddr uint64) ([]program.Frame, error) {
+ s.goroutineStack = func(gAddr uint64) ([]debug.Frame, error) {
schedPC, err := s.peekUint(gAddr+schedPCOffset, schedPCByteSize)
if err != nil {
return nil, err
diff --git a/ogle/program/server/value.go b/server/value.go
similarity index 91%
rename from ogle/program/server/value.go
rename to server/value.go
index 2b5c1c6..0fef7fe 100644
--- a/ogle/program/server/value.go
+++ b/server/value.go
@@ -6,12 +6,13 @@
import (
"fmt"
+
+ "golang.org/x/debug"
"golang.org/x/debug/dwarf"
- "golang.org/x/debug/ogle/program"
)
// value peeks the program's memory at the given address, parsing it as a value of type t.
-func (s *Server) value(t dwarf.Type, addr uint64) (program.Value, error) {
+func (s *Server) value(t dwarf.Type, addr uint64) (debug.Value, error) {
// readBasic reads the memory for a basic type of size n bytes.
readBasic := func(n int64) ([]byte, error) {
switch n {
@@ -114,7 +115,7 @@
if err != nil {
return nil, fmt.Errorf("reading pointer: %s", err)
}
- return program.Pointer{
+ return debug.Pointer{
TypeID: uint64(t.Type.Common().Offset),
Address: uint64(s.arch.Uintptr(buf)),
}, nil
@@ -135,8 +136,8 @@
return nil, fmt.Errorf("slice's capacity %d is less than its length %d", capacity, length)
}
- return program.Slice{
- program.Array{
+ return debug.Slice{
+ debug.Array{
ElementTypeID: uint64(t.ElemType.Common().Offset),
Address: uint64(ptr),
Length: length,
@@ -150,24 +151,24 @@
if stride%8 != 0 {
return nil, fmt.Errorf("array is not byte-aligned")
}
- return program.Array{
+ return debug.Array{
ElementTypeID: uint64(t.Type.Common().Offset),
Address: uint64(addr),
Length: uint64(length),
StrideBits: uint64(stride),
}, nil
case *dwarf.StructType:
- fields := make([]program.StructField, len(t.Field))
+ fields := make([]debug.StructField, len(t.Field))
for i, field := range t.Field {
- fields[i] = program.StructField{
+ fields[i] = debug.StructField{
Name: field.Name,
- Var: program.Var{
+ Var: debug.Var{
TypeID: uint64(field.Type.Common().Offset),
Address: uint64(addr) + uint64(field.ByteOffset),
},
}
}
- return program.Struct{fields}, nil
+ return debug.Struct{fields}, nil
case *dwarf.TypedefType:
return s.value(t.Type, addr)
case *dwarf.MapType:
@@ -175,7 +176,7 @@
if err != nil {
return nil, err
}
- return program.Map{
+ return debug.Map{
TypeID: uint64(t.Common().Offset),
Address: addr,
Length: length,
@@ -200,7 +201,7 @@
if err := s.peekBytes(ptr, tmp); err != nil {
return nil, fmt.Errorf("reading string contents: %s", err)
}
- return program.String{Length: length, String: string(tmp)}, nil
+ return debug.String{Length: length, String: string(tmp)}, nil
case *dwarf.ChanType:
pt, ok := t.TypedefType.Type.(*dwarf.PtrType)
if !ok {
@@ -217,7 +218,7 @@
}
if a == 0 {
// This channel is nil.
- return program.Channel{
+ return debug.Channel{
ElementTypeID: uint64(t.ElemType.Common().Offset),
Address: 0,
Buffer: 0,
@@ -244,7 +245,7 @@
if err != nil {
return nil, fmt.Errorf("reading channel buffer index: %s", err)
}
- return program.Channel{
+ return debug.Channel{
ElementTypeID: uint64(t.ElemType.Common().Offset),
Address: a,
Buffer: buf,
@@ -258,9 +259,9 @@
if err != nil {
return nil, fmt.Errorf("reading func: %s", err)
}
- return program.Func{Address: a}, nil
+ return debug.Func{Address: a}, nil
case *dwarf.InterfaceType:
- return program.Interface{}, nil
+ return debug.Interface{}, nil
// TODO: more types
}
return nil, fmt.Errorf("Unsupported type %T", t)
diff --git a/ogle/demo/ogler/ogler_test.go b/tests/peek/peek_test.go
similarity index 73%
rename from ogle/demo/ogler/ogler_test.go
rename to tests/peek/peek_test.go
index 729fa75..8d00a93 100644
--- a/ogle/demo/ogler/ogler_test.go
+++ b/tests/peek/peek_test.go
@@ -2,10 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// Demo program that starts another program and calls Ogle library functions
-// to debug it.
-
-package ogler
+package peek_test
import (
"fmt"
@@ -15,9 +12,9 @@
"reflect"
"testing"
- "golang.org/x/debug/ogle/program"
- "golang.org/x/debug/ogle/program/client"
- "golang.org/x/debug/ogle/program/local"
+ "golang.org/x/debug"
+ "golang.org/x/debug/local"
+ "golang.org/x/debug/remote"
)
var expectedVarValues = map[string]interface{}{
@@ -87,53 +84,53 @@
`main.Z_unsafe_pointer_nil`: `0x0`,
}
-// expectedEvaluate contains expected results of the program.Evaluate function.
+// expectedEvaluate contains expected results of the debug.Evaluate function.
// A nil value indicates that an error is expected.
-var expectedEvaluate = map[string]program.Value{
+var expectedEvaluate = map[string]debug.Value{
`x`: int16(42),
- `local_array`: program.Array{42, 42, 5, 8},
+ `local_array`: debug.Array{42, 42, 5, 8},
`local_bool_false`: false,
`local_bool_true`: true,
- `local_channel`: program.Channel{42, 42, 42, 0, 0, 2, 0},
- `local_channel_buffered`: program.Channel{42, 42, 42, 6, 10, 2, 8},
- `local_channel_nil`: program.Channel{42, 0, 0, 0, 0, 2, 0},
+ `local_channel`: debug.Channel{42, 42, 42, 0, 0, 2, 0},
+ `local_channel_buffered`: debug.Channel{42, 42, 42, 6, 10, 2, 8},
+ `local_channel_nil`: debug.Channel{42, 0, 0, 0, 0, 2, 0},
`local_complex128`: complex128(1.987654321 - 2.987654321i),
`local_complex64`: complex64(1.54321 + 2.54321i),
`local_float32`: float32(1.54321),
`local_float64`: float64(1.987654321),
- `local_func_int8_r_int8`: program.Func{42},
- `local_func_int8_r_pint8`: program.Func{42},
- `local_func_bar`: program.Func{42},
- `local_func_nil`: program.Func{0},
+ `local_func_int8_r_int8`: debug.Func{42},
+ `local_func_int8_r_pint8`: debug.Func{42},
+ `local_func_bar`: debug.Func{42},
+ `local_func_nil`: debug.Func{0},
`local_int`: -21,
`local_int16`: int16(-32321),
`local_int32`: int32(-1987654321),
`local_int64`: int64(-9012345678987654321),
`local_int8`: int8(-121),
`local_int_typedef`: int16(88),
- `local_interface`: program.Interface{},
- `local_interface_nil`: program.Interface{},
- `local_interface_typed_nil`: program.Interface{},
- `local_map`: program.Map{42, 42, 1},
- `local_map_2`: program.Map{42, 42, 1},
- `local_map_3`: program.Map{42, 42, 2},
- `local_map_empty`: program.Map{42, 42, 0},
- `local_map_nil`: program.Map{42, 42, 0},
- `local_pointer`: program.Pointer{42, 42},
- `local_pointer_nil`: program.Pointer{42, 0},
- `local_slice`: program.Slice{program.Array{42, 42, 5, 8}, 5},
- `local_slice_2`: program.Slice{program.Array{42, 42, 2, 8}, 5},
- `local_slice_nil`: program.Slice{program.Array{42, 0, 0, 8}, 0},
- `local_string`: program.String{12, `I'm a string`},
- `local_struct`: program.Struct{[]program.StructField{{"a", program.Var{}}, {"b", program.Var{}}}},
+ `local_interface`: debug.Interface{},
+ `local_interface_nil`: debug.Interface{},
+ `local_interface_typed_nil`: debug.Interface{},
+ `local_map`: debug.Map{42, 42, 1},
+ `local_map_2`: debug.Map{42, 42, 1},
+ `local_map_3`: debug.Map{42, 42, 2},
+ `local_map_empty`: debug.Map{42, 42, 0},
+ `local_map_nil`: debug.Map{42, 42, 0},
+ `local_pointer`: debug.Pointer{42, 42},
+ `local_pointer_nil`: debug.Pointer{42, 0},
+ `local_slice`: debug.Slice{debug.Array{42, 42, 5, 8}, 5},
+ `local_slice_2`: debug.Slice{debug.Array{42, 42, 2, 8}, 5},
+ `local_slice_nil`: debug.Slice{debug.Array{42, 0, 0, 8}, 0},
+ `local_string`: debug.String{12, `I'm a string`},
+ `local_struct`: debug.Struct{[]debug.StructField{{"a", debug.Var{}}, {"b", debug.Var{}}}},
`local_uint`: uint(21),
`local_uint16`: uint16(54321),
`local_uint32`: uint32(3217654321),
`local_uint64`: uint64(12345678900987654321),
`local_uint8`: uint8(231),
`local_uintptr`: uint(21),
- `local_unsafe_pointer`: program.Pointer{0, 42},
- `local_unsafe_pointer_nil`: program.Pointer{0, 0},
+ `local_unsafe_pointer`: debug.Pointer{0, 42},
+ `local_unsafe_pointer_nil`: debug.Pointer{0, 0},
`x + 5`: int16(47),
`x - 5`: int16(37),
`x / 5`: int16(8),
@@ -156,9 +153,9 @@
`1e5`: 100000.0,
`0x42`: 66,
`'c'`: 'c',
- `"de"`: program.String{2, `de`},
- "`ef`": program.String{2, `ef`},
- `"de" + "fg"`: program.String{4, `defg`},
+ `"de"`: debug.String{2, `de`},
+ "`ef`": debug.String{2, `ef`},
+ `"de" + "fg"`: debug.String{4, `defg`},
`/* comment */ -5`: -5,
`false`: false,
`true`: true,
@@ -182,16 +179,16 @@
`(6 + 8i) * (1 + 1i)`: -2 + 14i,
`(6 + 8i) * (6 - 8i)`: complex128(100),
`(6 + 8i) / (3 + 4i)`: complex128(2),
- `local_string + "!"`: program.String{13, `I'm a string!`},
- `*local_pointer`: program.Struct{[]program.StructField{{"a", program.Var{}}, {"b", program.Var{}}}},
- `&local_int16`: program.Pointer{42, 42},
+ `local_string + "!"`: debug.String{13, `I'm a string!`},
+ `*local_pointer`: debug.Struct{[]debug.StructField{{"a", debug.Var{}}, {"b", debug.Var{}}}},
+ `&local_int16`: debug.Pointer{42, 42},
`*&local_int16`: int16(-32321),
`*&*&*&*&local_int16`: int16(-32321),
`local_array[2]`: int8(3),
`local_slice[1]`: uint8(108),
`local_slice_2[1]`: int8(121),
- `&local_array[1]`: program.Pointer{42, 42},
- `&local_slice[1]`: program.Pointer{42, 42},
+ `&local_array[1]`: debug.Pointer{42, 42},
+ `&local_slice[1]`: debug.Pointer{42, 42},
`local_map[-21]`: float32(3.54321),
`local_map[+21]`: float32(0),
`local_map_3[1024]`: int8(1),
@@ -202,78 +199,78 @@
`"hello"[2]`: uint8('l'),
`local_array[1:3][1]`: int8(3),
`local_array[0:4][2:3][0]`: int8(3),
- `local_array[:]`: program.Slice{program.Array{42, 42, 5, 8}, 5},
- `local_array[:2]`: program.Slice{program.Array{42, 42, 2, 8}, 5},
- `local_array[2:]`: program.Slice{program.Array{42, 42, 3, 8}, 3},
- `local_array[1:3]`: program.Slice{program.Array{42, 42, 2, 8}, 4},
- `local_array[:3:4]`: program.Slice{program.Array{42, 42, 3, 8}, 4},
- `local_array[1:3:4]`: program.Slice{program.Array{42, 42, 2, 8}, 3},
- `local_array[1:][1:][1:]`: program.Slice{program.Array{42, 42, 2, 8}, 2},
- `(&local_array)[:]`: program.Slice{program.Array{42, 42, 5, 8}, 5},
- `(&local_array)[:2]`: program.Slice{program.Array{42, 42, 2, 8}, 5},
- `(&local_array)[2:]`: program.Slice{program.Array{42, 42, 3, 8}, 3},
- `(&local_array)[1:3]`: program.Slice{program.Array{42, 42, 2, 8}, 4},
- `(&local_array)[:3:4]`: program.Slice{program.Array{42, 42, 3, 8}, 4},
- `(&local_array)[1:3:4]`: program.Slice{program.Array{42, 42, 2, 8}, 3},
+ `local_array[:]`: debug.Slice{debug.Array{42, 42, 5, 8}, 5},
+ `local_array[:2]`: debug.Slice{debug.Array{42, 42, 2, 8}, 5},
+ `local_array[2:]`: debug.Slice{debug.Array{42, 42, 3, 8}, 3},
+ `local_array[1:3]`: debug.Slice{debug.Array{42, 42, 2, 8}, 4},
+ `local_array[:3:4]`: debug.Slice{debug.Array{42, 42, 3, 8}, 4},
+ `local_array[1:3:4]`: debug.Slice{debug.Array{42, 42, 2, 8}, 3},
+ `local_array[1:][1:][1:]`: debug.Slice{debug.Array{42, 42, 2, 8}, 2},
+ `(&local_array)[:]`: debug.Slice{debug.Array{42, 42, 5, 8}, 5},
+ `(&local_array)[:2]`: debug.Slice{debug.Array{42, 42, 2, 8}, 5},
+ `(&local_array)[2:]`: debug.Slice{debug.Array{42, 42, 3, 8}, 3},
+ `(&local_array)[1:3]`: debug.Slice{debug.Array{42, 42, 2, 8}, 4},
+ `(&local_array)[:3:4]`: debug.Slice{debug.Array{42, 42, 3, 8}, 4},
+ `(&local_array)[1:3:4]`: debug.Slice{debug.Array{42, 42, 2, 8}, 3},
`local_slice[1:5][0:3][1]`: uint8('i'),
- `local_slice[:]`: program.Slice{program.Array{42, 42, 5, 8}, 5},
- `local_slice[:2]`: program.Slice{program.Array{42, 42, 2, 8}, 5},
- `local_slice[2:]`: program.Slice{program.Array{42, 42, 3, 8}, 3},
- `local_slice[1:3]`: program.Slice{program.Array{42, 42, 2, 8}, 4},
- `local_slice[:3:4]`: program.Slice{program.Array{42, 42, 3, 8}, 4},
- `local_slice[1:3:4]`: program.Slice{program.Array{42, 42, 2, 8}, 3},
+ `local_slice[:]`: debug.Slice{debug.Array{42, 42, 5, 8}, 5},
+ `local_slice[:2]`: debug.Slice{debug.Array{42, 42, 2, 8}, 5},
+ `local_slice[2:]`: debug.Slice{debug.Array{42, 42, 3, 8}, 3},
+ `local_slice[1:3]`: debug.Slice{debug.Array{42, 42, 2, 8}, 4},
+ `local_slice[:3:4]`: debug.Slice{debug.Array{42, 42, 3, 8}, 4},
+ `local_slice[1:3:4]`: debug.Slice{debug.Array{42, 42, 2, 8}, 3},
`local_struct.a`: 21,
`(&local_struct).a`: 21,
`(*local_pointer).a`: 21,
`(&*local_pointer).a`: 21,
- `(*local_pointer).b`: program.String{2, `hi`},
+ `(*local_pointer).b`: debug.String{2, `hi`},
`local_pointer.a`: 21,
- `local_pointer.b`: program.String{2, `hi`},
- `lookup("main.Z_array")`: program.Array{42, 42, 5, 8},
- `lookup("main.Z_array_empty")`: program.Array{42, 42, 0, 8},
+ `local_pointer.b`: debug.String{2, `hi`},
+ `lookup("main.Z_array")`: debug.Array{42, 42, 5, 8},
+ `lookup("main.Z_array_empty")`: debug.Array{42, 42, 0, 8},
`lookup("main.Z_bool_false")`: false,
`lookup("main.Z_bool_true")`: true,
- `lookup("main.Z_channel")`: program.Channel{42, 42, 42, 0, 0, 2, 0},
- `lookup("main.Z_channel_buffered")`: program.Channel{42, 42, 42, 6, 10, 2, 8},
- `lookup("main.Z_channel_nil")`: program.Channel{42, 0, 0, 0, 0, 2, 0},
- `lookup("main.Z_array_of_empties")`: program.Array{42, 42, 2, 0},
+ `lookup("main.Z_channel")`: debug.Channel{42, 42, 42, 0, 0, 2, 0},
+ `lookup("main.Z_channel_buffered")`: debug.Channel{42, 42, 42, 6, 10, 2, 8},
+ `lookup("main.Z_channel_nil")`: debug.Channel{42, 0, 0, 0, 0, 2, 0},
+ `lookup("main.Z_array_of_empties")`: debug.Array{42, 42, 2, 0},
`lookup("main.Z_complex128")`: complex128(1.987654321 - 2.987654321i),
`lookup("main.Z_complex64")`: complex64(1.54321 + 2.54321i),
`lookup("main.Z_float32")`: float32(1.54321),
`lookup("main.Z_float64")`: float64(1.987654321),
- `lookup("main.Z_func_int8_r_int8")`: program.Func{42},
- `lookup("main.Z_func_int8_r_pint8")`: program.Func{42},
- `lookup("main.Z_func_bar")`: program.Func{42},
- `lookup("main.Z_func_nil")`: program.Func{0},
+ `lookup("main.Z_func_int8_r_int8")`: debug.Func{42},
+ `lookup("main.Z_func_int8_r_pint8")`: debug.Func{42},
+ `lookup("main.Z_func_bar")`: debug.Func{42},
+ `lookup("main.Z_func_nil")`: debug.Func{0},
`lookup("main.Z_int")`: -21,
`lookup("main.Z_int16")`: int16(-32321),
`lookup("main.Z_int32")`: int32(-1987654321),
`lookup("main.Z_int64")`: int64(-9012345678987654321),
`lookup("main.Z_int8")`: int8(-121),
`lookup("main.Z_int_typedef")`: int16(88),
- `lookup("main.Z_interface")`: program.Interface{},
- `lookup("main.Z_interface_nil")`: program.Interface{},
- `lookup("main.Z_interface_typed_nil")`: program.Interface{},
- `lookup("main.Z_map")`: program.Map{42, 42, 1},
- `lookup("main.Z_map_2")`: program.Map{42, 42, 1},
- `lookup("main.Z_map_3")`: program.Map{42, 42, 2},
- `lookup("main.Z_map_empty")`: program.Map{42, 42, 0},
- `lookup("main.Z_map_nil")`: program.Map{42, 42, 0},
- `lookup("main.Z_pointer")`: program.Pointer{42, 42},
- `lookup("main.Z_pointer_nil")`: program.Pointer{42, 0},
- `lookup("main.Z_slice")`: program.Slice{program.Array{42, 42, 5, 8}, 5},
- `lookup("main.Z_slice_2")`: program.Slice{program.Array{42, 42, 2, 8}, 5},
- `lookup("main.Z_slice_nil")`: program.Slice{program.Array{42, 0, 0, 8}, 0},
- `lookup("main.Z_string")`: program.String{12, `I'm a string`},
- `lookup("main.Z_struct")`: program.Struct{[]program.StructField{{"a", program.Var{}}, {"b", program.Var{}}}},
+ `lookup("main.Z_interface")`: debug.Interface{},
+ `lookup("main.Z_interface_nil")`: debug.Interface{},
+ `lookup("main.Z_interface_typed_nil")`: debug.Interface{},
+ `lookup("main.Z_map")`: debug.Map{42, 42, 1},
+ `lookup("main.Z_map_2")`: debug.Map{42, 42, 1},
+ `lookup("main.Z_map_3")`: debug.Map{42, 42, 2},
+ `lookup("main.Z_map_empty")`: debug.Map{42, 42, 0},
+ `lookup("main.Z_map_nil")`: debug.Map{42, 42, 0},
+ `lookup("main.Z_pointer")`: debug.Pointer{42, 42},
+ `lookup("main.Z_pointer_nil")`: debug.Pointer{42, 0},
+ `lookup("main.Z_slice")`: debug.Slice{debug.Array{42, 42, 5, 8}, 5},
+ `lookup("main.Z_slice_2")`: debug.Slice{debug.Array{42, 42, 2, 8}, 5},
+ `lookup("main.Z_slice_nil")`: debug.Slice{debug.Array{42, 0, 0, 8}, 0},
+ `lookup("main.Z_string")`: debug.String{12, `I'm a string`},
+ `lookup("main.Z_struct")`: debug.Struct{[]debug.StructField{{"a", debug.Var{}}, {"b", debug.Var{}}}},
`lookup("main.Z_uint")`: uint(21),
`lookup("main.Z_uint16")`: uint16(54321),
`lookup("main.Z_uint32")`: uint32(3217654321),
`lookup("main.Z_uint64")`: uint64(12345678900987654321),
`lookup("main.Z_uint8")`: uint8(231),
`lookup("main.Z_uintptr")`: uint(21),
- `lookup("main.Z_unsafe_pointer")`: program.Pointer{0, 42},
- `lookup("main.Z_unsafe_pointer_nil")`: program.Pointer{0, 0},
+ `lookup("main.Z_unsafe_pointer")`: debug.Pointer{0, 42},
+ `lookup("main.Z_unsafe_pointer_nil")`: debug.Pointer{0, 0},
`lookup("main.Z_int") + lookup("main.Z_int")`: -42,
`lookup("main.Z_int16") < 0`: true,
`lookup("main.Z_uint32") + lookup("main.Z_uint32")`: uint32(2140341346),
@@ -285,7 +282,7 @@
`lookup("main.Z_array")[2]`: int8(3),
`lookup("main.Z_array")[1:3][1]`: int8(3),
`lookup("main.Z_array")[0:4][2:3][0]`: int8(3),
- `lookup("main.Z_array_of_empties")[0]`: program.Struct{},
+ `lookup("main.Z_array_of_empties")[0]`: debug.Struct{},
`lookup("main.Z_complex128") * 10.0`: complex128(19.87654321 - 29.87654321i),
`lookup("main.Z_complex64") * 0.1`: complex64(0.154321 + 0.254321i),
`lookup("main.Z_float32") * 10.0`: float32(15.4321),
@@ -301,9 +298,9 @@
`lookup("main.Z_slice")[1]`: uint8(108),
`lookup("main.Z_slice_2")[1]`: int8(121),
`lookup("main.Z_slice")[1:5][0:3][1]`: uint8('i'),
- `lookup("main.Z_array")[1:3:4]`: program.Slice{program.Array{42, 42, 2, 8}, 3},
- `(&lookup("main.Z_array"))[1:3:4]`: program.Slice{program.Array{42, 42, 2, 8}, 3},
- `lookup("main.Z_string") + "!"`: program.String{13, `I'm a string!`},
+ `lookup("main.Z_array")[1:3:4]`: debug.Slice{debug.Array{42, 42, 2, 8}, 3},
+ `(&lookup("main.Z_array"))[1:3:4]`: debug.Slice{debug.Array{42, 42, 2, 8}, 3},
+ `lookup("main.Z_string") + "!"`: debug.String{13, `I'm a string!`},
`lookup("main.Z_struct").a`: 21,
`(&lookup("main.Z_struct")).a`: 21,
`lookup("main.Z_uint")/10`: uint(2),
@@ -314,16 +311,16 @@
`lookup("main.Z_pointer").a`: 21,
`(*lookup("main.Z_pointer")).a`: 21,
`(&*lookup("main.Z_pointer")).a`: 21,
- `lookup("main.Z_pointer").b`: program.String{2, `hi`},
- `(*lookup("main.Z_pointer")).b`: program.String{2, `hi`},
- `(&*lookup("main.Z_pointer")).b`: program.String{2, `hi`},
+ `lookup("main.Z_pointer").b`: debug.String{2, `hi`},
+ `(*lookup("main.Z_pointer")).b`: debug.String{2, `hi`},
+ `(&*lookup("main.Z_pointer")).b`: debug.String{2, `hi`},
`lookup("main.Z_map_nil")[32]`: float32(0),
- `&lookup("main.Z_int16")`: program.Pointer{42, 42},
- `&lookup("main.Z_array")[1]`: program.Pointer{42, 42},
- `&lookup("main.Z_slice")[1]`: program.Pointer{42, 42},
+ `&lookup("main.Z_int16")`: debug.Pointer{42, 42},
+ `&lookup("main.Z_array")[1]`: debug.Pointer{42, 42},
+ `&lookup("main.Z_slice")[1]`: debug.Pointer{42, 42},
`*&lookup("main.Z_int16")`: int16(-32321),
`*&*&*&*&lookup("main.Z_int16")`: int16(-32321),
- `lookup("time.Local")`: program.Pointer{42, 42},
+ `lookup("time.Local")`: debug.Pointer{42, 42},
`5 + false`: nil,
``: nil,
`x + ""`: nil,
@@ -400,10 +397,10 @@
}
const (
- proxySrc = "golang.org/x/debug/ogle/cmd/ogleproxy"
- proxyBinary = "./ogleproxy"
- traceeSrc = "golang.org/x/debug/ogle/demo/tracee"
- traceeBinary = "./tracee"
+ proxySrc = "golang.org/x/debug/cmd/debugproxy"
+ proxyBinary = "./debugproxy.out"
+ traceeSrc = "golang.org/x/debug/tests/peek/testdata"
+ traceeBinary = "./tracee.out"
)
func TestMain(m *testing.M) {
@@ -415,7 +412,7 @@
fmt.Println(err)
return 1
}
- client.OgleproxyCmd = proxyBinary
+ remote.DebugproxyCmd = proxyBinary
defer os.Remove(proxyBinary)
if err := run("go", "build", "-o", traceeBinary, traceeSrc); err != nil {
fmt.Println(err)
@@ -434,14 +431,14 @@
}
func TestRemoteProgram(t *testing.T) {
- prog, err := client.New("localhost", traceeBinary)
+ prog, err := remote.New("localhost", traceeBinary)
if err != nil {
- t.Fatal("client.New:", err)
+ t.Fatal("remote.New:", err)
}
testProgram(t, prog)
}
-func testProgram(t *testing.T, prog program.Program) {
+func testProgram(t *testing.T, prog debug.Program) {
_, err := prog.Run("some", "arguments")
if err != nil {
log.Fatalf("Run: %v", err)
@@ -595,8 +592,8 @@
if v != val {
t.Errorf("got Evaluate(%s) = %T(%v), expected %T(%v)", k, val, val, v, v)
}
- case program.Array:
- val := val.(program.Array)
+ case debug.Array:
+ val := val.(debug.Array)
if v.ElementTypeID == 0 && val.ElementTypeID != 0 {
t.Errorf("got Evaluate(%s) = %+v, expected zero ElementTypeID", k, val)
}
@@ -609,8 +606,8 @@
if v.Address != 0 && val.Address == 0 {
t.Errorf("got Evaluate(%s) = %+v, expected non-zero Address", k, val)
}
- case program.Slice:
- val := val.(program.Slice)
+ case debug.Slice:
+ val := val.(debug.Slice)
if v.ElementTypeID == 0 && val.ElementTypeID != 0 {
t.Errorf("got Evaluate(%s) = %+v, expected zero ElementTypeID", k, val)
}
@@ -623,8 +620,8 @@
if v.Address != 0 && val.Address == 0 {
t.Errorf("got Evaluate(%s) = %+v, expected non-zero Address", k, val)
}
- case program.Map:
- val := val.(program.Map)
+ case debug.Map:
+ val := val.(debug.Map)
if v.TypeID == 0 && val.TypeID != 0 {
t.Errorf("got Evaluate(%s) = %+v, expected zero TypeID", k, val)
}
@@ -637,8 +634,8 @@
if v.Address != 0 && val.Address == 0 {
t.Errorf("got Evaluate(%s) = %+v, expected non-zero Address", k, val)
}
- case program.Pointer:
- val := val.(program.Pointer)
+ case debug.Pointer:
+ val := val.(debug.Pointer)
if v.TypeID == 0 && val.TypeID != 0 {
t.Errorf("got Evaluate(%s) = %+v, expected zero TypeID", k, val)
}
@@ -651,8 +648,8 @@
if v.Address != 0 && val.Address == 0 {
t.Errorf("got Evaluate(%s) = %+v, expected non-zero Address", k, val)
}
- case program.Channel:
- val := val.(program.Channel)
+ case debug.Channel:
+ val := val.(debug.Channel)
if v.ElementTypeID == 0 && val.ElementTypeID != 0 {
t.Errorf("got Evaluate(%s) = %+v, expected zero ElementTypeID", k, val)
}
@@ -671,8 +668,8 @@
if v.Buffer != 0 && val.Buffer == 0 {
t.Errorf("got Evaluate(%s) = %+v, expected non-zero Buffer", k, val)
}
- case program.Struct:
- val := val.(program.Struct)
+ case debug.Struct:
+ val := val.(debug.Struct)
if len(v.Fields) != len(val.Fields) {
t.Errorf("got Evaluate(%s) = %T(%v), expected %T(%v)", k, val, val, v, v)
break
@@ -685,8 +682,8 @@
break
}
}
- case program.Func:
- val := val.(program.Func)
+ case debug.Func:
+ val := val.(debug.Func)
if v.Address == 0 && val.Address != 0 {
t.Errorf("got Evaluate(%s) = %+v, expected zero Address", k, val)
}
@@ -729,9 +726,9 @@
if err != nil {
t.Fatalf("Evaluate: %s", err)
}
- s, ok := val.(program.Struct)
+ s, ok := val.(debug.Struct)
if !ok {
- t.Fatalf("got Evaluate(`local_struct`) = %T(%v), expected program.Struct", val, val)
+ t.Fatalf("got Evaluate(`local_struct`) = %T(%v), expected debug.Struct", val, val)
}
// Check the values of its fields.
if len(s.Fields) != 2 {
@@ -744,7 +741,7 @@
}
if v1, err := prog.Value(s.Fields[1].Var); err != nil {
t.Errorf("Value: %s", err)
- } else if v1 != (program.String{2, "hi"}) {
+ } else if v1 != (debug.String{2, "hi"}) {
t.Errorf("Value: got %T(%v), expected `hi`", v1, v1)
}
@@ -791,7 +788,7 @@
if _, err = prog.VarByName("not a real name"); err == nil {
t.Error("VarByName for invalid name: expected error")
}
- if _, err = prog.Value(program.Var{}); err == nil {
+ if _, err = prog.Value(debug.Var{}); err == nil {
t.Error("value of invalid var: expected error")
}
if v, err := prog.VarByName("main.Z_int16"); err != nil {
@@ -808,7 +805,7 @@
// checkValue tests that we can get a Var for a variable with the given name,
// that we can then get the value of that Var, and that calling fn for that
// value succeeds.
- checkValue := func(name string, fn func(val program.Value) error) {
+ checkValue := func(name string, fn func(val debug.Value) error) {
if v, err := prog.VarByName(name); err != nil {
t.Errorf("VarByName(%s): %s", name, err)
} else if val, err := prog.Value(v); err != nil {
@@ -818,7 +815,7 @@
}
}
- checkValue("main.Z_uintptr", func(val program.Value) error {
+ checkValue("main.Z_uintptr", func(val debug.Value) error {
if val != uint32(21) && val != uint64(21) {
// Z_uintptr should be an unsigned integer with size equal to the debugged
// program's address size.
@@ -827,29 +824,29 @@
return nil
})
- checkValue("main.Z_int", func(val program.Value) error {
+ checkValue("main.Z_int", func(val debug.Value) error {
if val != int32(-21) && val != int64(-21) {
return fmt.Errorf("got %T(%v) want -21", val, val)
}
return nil
})
- checkValue("main.Z_uint", func(val program.Value) error {
+ checkValue("main.Z_uint", func(val debug.Value) error {
if val != uint32(21) && val != uint64(21) {
return fmt.Errorf("got %T(%v) want 21", val, val)
}
return nil
})
- checkValue("main.Z_pointer", func(val program.Value) error {
- if _, ok := val.(program.Pointer); !ok {
+ checkValue("main.Z_pointer", func(val debug.Value) error {
+ if _, ok := val.(debug.Pointer); !ok {
return fmt.Errorf("got %T(%v) expected Pointer", val, val)
}
return nil
})
- checkValue("main.Z_pointer_nil", func(val program.Value) error {
- if p, ok := val.(program.Pointer); !ok {
+ checkValue("main.Z_pointer_nil", func(val debug.Value) error {
+ if p, ok := val.(debug.Pointer); !ok {
return fmt.Errorf("got %T(%v) expected Pointer", val, val)
} else if p.Address != 0 {
return fmt.Errorf("got %T(%v) expected nil pointer", val, val)
@@ -857,8 +854,8 @@
return nil
})
- checkValue("main.Z_array", func(val program.Value) error {
- a, ok := val.(program.Array)
+ checkValue("main.Z_array", func(val debug.Value) error {
+ a, ok := val.(debug.Array)
if !ok {
return fmt.Errorf("got %T(%v) expected Array", val, val)
}
@@ -876,8 +873,8 @@
return nil
})
- checkValue("main.Z_slice", func(val program.Value) error {
- s, ok := val.(program.Slice)
+ checkValue("main.Z_slice", func(val debug.Value) error {
+ s, ok := val.(debug.Slice)
if !ok {
return fmt.Errorf("got %T(%v) expected Slice", val, val)
}
@@ -895,8 +892,8 @@
return nil
})
- checkValue("main.Z_map_empty", func(val program.Value) error {
- m, ok := val.(program.Map)
+ checkValue("main.Z_map_empty", func(val debug.Value) error {
+ m, ok := val.(debug.Map)
if !ok {
return fmt.Errorf("got %T(%v) expected Map", val, val)
}
@@ -906,8 +903,8 @@
return nil
})
- checkValue("main.Z_map_nil", func(val program.Value) error {
- m, ok := val.(program.Map)
+ checkValue("main.Z_map_nil", func(val debug.Value) error {
+ m, ok := val.(debug.Map)
if !ok {
return fmt.Errorf("got %T(%v) expected Map", val, val)
}
@@ -917,8 +914,8 @@
return nil
})
- checkValue("main.Z_map_3", func(val program.Value) error {
- m, ok := val.(program.Map)
+ checkValue("main.Z_map_3", func(val debug.Value) error {
+ m, ok := val.(debug.Map)
if !ok {
return fmt.Errorf("got %T(%v) expected Map", val, val)
}
@@ -962,8 +959,8 @@
return nil
})
- checkValue("main.Z_string", func(val program.Value) error {
- s, ok := val.(program.String)
+ checkValue("main.Z_string", func(val debug.Value) error {
+ s, ok := val.(debug.String)
if !ok {
return fmt.Errorf("got %T(%v) expected String", val, val)
}
@@ -977,8 +974,8 @@
return nil
})
- checkValue("main.Z_channel", func(val program.Value) error {
- c, ok := val.(program.Channel)
+ checkValue("main.Z_channel", func(val debug.Value) error {
+ c, ok := val.(debug.Channel)
if !ok {
return fmt.Errorf("got %T(%v) expected Channel", val, val)
}
@@ -994,8 +991,8 @@
return nil
})
- checkValue("main.Z_channel_2", func(val program.Value) error {
- c, ok := val.(program.Channel)
+ checkValue("main.Z_channel_2", func(val debug.Value) error {
+ c, ok := val.(debug.Channel)
if !ok {
return fmt.Errorf("got %T(%v) expected Channel", val, val)
}
@@ -1011,8 +1008,8 @@
return nil
})
- checkValue("main.Z_channel_nil", func(val program.Value) error {
- c, ok := val.(program.Channel)
+ checkValue("main.Z_channel_nil", func(val debug.Value) error {
+ c, ok := val.(debug.Channel)
if !ok {
return fmt.Errorf("got %T(%v) expected Channel", val, val)
}
@@ -1028,8 +1025,8 @@
return nil
})
- checkValue("main.Z_channel_buffered", func(val program.Value) error {
- c, ok := val.(program.Channel)
+ checkValue("main.Z_channel_buffered", func(val debug.Value) error {
+ c, ok := val.(debug.Channel)
if !ok {
return fmt.Errorf("got %T(%v) expected Channel", val, val)
}
@@ -1060,8 +1057,8 @@
return nil
})
- checkValue("main.Z_func_bar", func(val program.Value) error {
- f, ok := val.(program.Func)
+ checkValue("main.Z_func_bar", func(val debug.Value) error {
+ f, ok := val.(debug.Func)
if !ok {
return fmt.Errorf("got %T(%v) expected Func", val, val)
}
@@ -1071,8 +1068,8 @@
return nil
})
- checkValue("main.Z_func_nil", func(val program.Value) error {
- f, ok := val.(program.Func)
+ checkValue("main.Z_func_nil", func(val debug.Value) error {
+ f, ok := val.(debug.Func)
if !ok {
return fmt.Errorf("got %T(%v) expected Func", val, val)
}
diff --git a/ogle/demo/tracee/main.go b/tests/peek/testdata/main.go
similarity index 98%
rename from ogle/demo/tracee/main.go
rename to tests/peek/testdata/main.go
index 91b942e..61a568e 100644
--- a/ogle/demo/tracee/main.go
+++ b/tests/peek/testdata/main.go
@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// Program for the Ogle demo to debug.
-
package main
import (