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, &regs); err != nil {
-				log.Fatalf("PtraceGetRegs: %v", err)
-			}
-			regs.Rip -= breakpointInstrLen
-			if err := syscall.PtraceSetRegs(pid, &regs); 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 (