x/debug: change various peeking functions to be methods of Server instead of Printer so they can be used elsewhere.

Make them return error values instead of a bool that indicates success.

Move these functions to peek.go.

Change-Id: Ifbd198ccd162e49e277c7a3b927abe47d18c6955
Reviewed-on: https://go-review.googlesource.com/11881
Reviewed-by: Rob Pike <r@golang.org>
diff --git a/ogle/program/server/peek.go b/ogle/program/server/peek.go
new file mode 100644
index 0000000..484b3f1
--- /dev/null
+++ b/ogle/program/server/peek.go
@@ -0,0 +1,95 @@
+// Copyright 2015 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.
+
+// Functions for reading values of various types from a program's memory.
+
+package server
+
+import (
+	"fmt"
+
+	"golang.org/x/debug/dwarf"
+)
+
+// peekBytes reads len(buf) bytes at addr.
+func (s *Server) peekBytes(addr uint64, buf []byte) error {
+	return s.ptracePeek(s.stoppedPid, uintptr(addr), buf)
+}
+
+// peekPtr reads a pointer at addr.
+func (s *Server) peekPtr(addr uint64) (uint64, error) {
+	buf := make([]byte, s.arch.PointerSize)
+	if err := s.peekBytes(addr, buf); err != nil {
+		return 0, err
+	}
+	return s.arch.Uintptr(buf), nil
+}
+
+// peekUint8 reads a single byte at addr.
+func (s *Server) peekUint8(addr uint64) (byte, error) {
+	buf := make([]byte, 1)
+	if err := s.peekBytes(addr, buf); err != nil {
+		return 0, err
+	}
+	return uint8(s.arch.UintN(buf)), nil
+}
+
+// peekInt reads an int of size n bytes at addr.
+func (s *Server) peekInt(addr uint64, n int64) (int64, error) {
+	buf := make([]byte, n)
+	if err := s.peekBytes(addr, buf); err != nil {
+		return 0, err
+	}
+	return s.arch.IntN(buf), nil
+}
+
+// peekUint reads a uint of size n bytes at addr.
+func (s *Server) peekUint(addr uint64, n int64) (uint64, error) {
+	buf := make([]byte, n)
+	if err := s.peekBytes(addr, buf); err != nil {
+		return 0, err
+	}
+	return s.arch.UintN(buf), nil
+}
+
+// peekPtrStructField reads a pointer in the field fieldName of the struct
+// of type t at addr.
+func (s *Server) peekPtrStructField(t *dwarf.StructType, addr uint64, fieldName string) (uint64, error) {
+	f, err := getField(t, fieldName)
+	if err != nil {
+		return 0, fmt.Errorf("reading field %s: %s", fieldName, err)
+	}
+	if _, ok := f.Type.(*dwarf.PtrType); !ok {
+		return 0, fmt.Errorf("field %s is not a pointer", fieldName)
+	}
+	return s.peekPtr(addr + uint64(f.ByteOffset))
+}
+
+// peekUintStructField reads a uint in the field fieldName of the struct
+// of type t at addr.  The size of the uint is determined by the field.
+func (s *Server) peekUintStructField(t *dwarf.StructType, addr uint64, fieldName string) (uint64, error) {
+	f, err := getField(t, fieldName)
+	if err != nil {
+		return 0, fmt.Errorf("reading field %s: %s", fieldName, err)
+	}
+	ut, ok := f.Type.(*dwarf.UintType)
+	if !ok {
+		return 0, fmt.Errorf("field %s is not an unsigned integer", fieldName)
+	}
+	return s.peekUint(addr+uint64(f.ByteOffset), ut.ByteSize)
+}
+
+// peekIntStructField reads an int in the field fieldName of the struct
+// of type t at addr.  The size of the int is determined by the field.
+func (s *Server) peekIntStructField(t *dwarf.StructType, addr uint64, fieldName string) (int64, error) {
+	f, err := getField(t, fieldName)
+	if err != nil {
+		return 0, fmt.Errorf("reading field %s: %s", fieldName, err)
+	}
+	it, ok := f.Type.(*dwarf.IntType)
+	if !ok {
+		return 0, fmt.Errorf("field %s is not a signed integer", fieldName)
+	}
+	return s.peekInt(addr+uint64(f.ByteOffset), it.ByteSize)
+}
diff --git a/ogle/program/server/print.go b/ogle/program/server/print.go
index 8c5a838..f78a2cb 100644
--- a/ogle/program/server/print.go
+++ b/ogle/program/server/print.go
@@ -22,16 +22,15 @@
 // Routines to print a value using DWARF type descriptions.
 // TODO: Does this deserve its own package? It has no dependencies on Server.
 
-// A Printer pretty-prints a values in the target address space.
+// A Printer pretty-prints values in the target address space.
 // It can be reused after each printing operation to avoid unnecessary
 // allocations. However, it is not safe for concurrent access.
 type Printer struct {
 	err      error // Sticky error value.
-	peeker   Peeker
+	server   *Server
 	dwarf    *dwarf.Data
 	arch     *arch.Architecture
 	printBuf bytes.Buffer            // Accumulates the output.
-	tmp      []byte                  // Temporary used for I/O.
 	visited  map[typeAndAddress]bool // Prevents looping on cyclic data.
 }
 
@@ -50,103 +49,14 @@
 	p.err = fmt.Errorf(format, args...)
 }
 
-// peek reads len bytes at addr, leaving p.tmp with the data and sized appropriately.
-func (p *Printer) peek(addr uint64, length int64) bool {
-	p.tmp = p.tmp[:length]
-	err := p.peeker.peek(uintptr(addr), p.tmp)
-	return err == nil
-}
-
-// peekPtr reads a pointer at addr.
-func (p *Printer) peekPtr(addr uint64) (uint64, bool) {
-	if p.peek(addr, int64(p.arch.PointerSize)) {
-		return p.arch.Uintptr(p.tmp), true
-	}
-	return 0, false
-}
-
-// peekUint8 reads a uint8 at addr.
-func (p *Printer) peekUint8(addr uint64) (uint8, bool) {
-	if p.peek(addr, 1) {
-		return p.tmp[0], true
-	}
-	return 0, false
-}
-
-// peekInt reads an int of size s at addr.
-func (p *Printer) peekInt(addr uint64, s int64) (int64, bool) {
-	if p.peek(addr, s) {
-		return p.arch.IntN(p.tmp), true
-	}
-	return 0, false
-}
-
-// peekUint reads a uint of size s at addr.
-func (p *Printer) peekUint(addr uint64, s int64) (uint64, bool) {
-	if p.peek(addr, s) {
-		return p.arch.UintN(p.tmp), true
-	}
-	return 0, false
-}
-
-// peekPtrStructField reads a pointer in the field fieldName of the struct
-// of type t at address addr.
-func (p *Printer) peekPtrStructField(t *dwarf.StructType, addr uint64, fieldName string) (uint64, bool) {
-	f, err := getField(t, fieldName)
-	if err != nil {
-		p.errorf("%s", err)
-		return 0, false
-	}
-	_, ok := f.Type.(*dwarf.PtrType)
-	if !ok {
-		p.errorf("struct field %s is not a pointer", fieldName)
-		return 0, false
-	}
-	return p.peekPtr(addr + uint64(f.ByteOffset))
-}
-
-// peekUintStructField reads a uint in the field fieldName of the struct
-// of type t at address addr.  The size of the uint is determined by the field.
-func (p *Printer) peekUintStructField(t *dwarf.StructType, addr uint64, fieldName string) (uint64, bool) {
-	f, err := getField(t, fieldName)
-	if err != nil {
-		return 0, false
-	}
-	ut, ok := f.Type.(*dwarf.UintType)
-	if !ok {
-		return 0, false
-	}
-	return p.peekUint(addr+uint64(f.ByteOffset), ut.ByteSize)
-}
-
-// peekIntStructField reads an int in the field fieldName of the struct
-// of type t at address addr.  The size of the int is determined by the field.
-func (p *Printer) peekIntStructField(t *dwarf.StructType, addr uint64, fieldName string) (int64, bool) {
-	f, err := getField(t, fieldName)
-	if err != nil {
-		return 0, false
-	}
-	it, ok := f.Type.(*dwarf.IntType)
-	if !ok {
-		return 0, false
-	}
-	return p.peekInt(addr+uint64(f.ByteOffset), it.ByteSize)
-}
-
-// Peeker is like a read that probes the remote address space.
-type Peeker interface {
-	peek(offset uintptr, buf []byte) error
-}
-
-// NewPrinter returns a printer that can use the Peeker to access and print
+// NewPrinter returns a printer that can use the Server to access and print
 // values of the specified architecture described by the provided DWARF data.
-func NewPrinter(arch *arch.Architecture, dwarf *dwarf.Data, peeker Peeker) *Printer {
+func NewPrinter(arch *arch.Architecture, dwarf *dwarf.Data, server *Server) *Printer {
 	return &Printer{
-		peeker:  peeker,
+		server:  server,
 		arch:    arch,
 		dwarf:   dwarf,
 		visited: make(map[typeAndAddress]bool),
-		tmp:     make([]byte, 100), // Enough for a largish string.
 	}
 }
 
@@ -250,56 +160,58 @@
 			p.errorf("unrecognized bool size %d", typ.ByteSize)
 			return
 		}
-		if b, ok := p.peekUint8(a); ok {
-			p.printf("%t", b != 0)
+		if b, err := p.server.peekUint8(a); err != nil {
+			p.errorf("reading bool: %s", err)
 		} else {
-			p.errorf("couldn't read bool")
+			p.printf("%t", b != 0)
 		}
 	case *dwarf.PtrType:
-		if ptr, ok := p.peekPtr(a); ok {
-			p.printf("%#x", ptr)
+		if ptr, err := p.server.peekPtr(a); err != nil {
+			p.errorf("reading pointer: %s", err)
 		} else {
-			p.errorf("couldn't read pointer")
+			p.printf("%#x", ptr)
 		}
 	case *dwarf.IntType:
 		// Sad we can't tell a rune from an int32.
-		if i, ok := p.peekInt(a, typ.ByteSize); ok {
-			p.printf("%d", i)
+		if i, err := p.server.peekInt(a, typ.ByteSize); err != nil {
+			p.errorf("reading integer: %s", err)
 		} else {
-			p.errorf("couldn't read int")
+			p.printf("%d", i)
 		}
 	case *dwarf.UintType:
-		if u, ok := p.peekUint(a, typ.ByteSize); ok {
-			p.printf("%d", u)
+		if u, err := p.server.peekUint(a, typ.ByteSize); err != nil {
+			p.errorf("reading unsigned integer: %s", err)
 		} else {
-			p.errorf("couldn't read uint")
+			p.printf("%d", u)
 		}
 	case *dwarf.FloatType:
-		if !p.peek(a, typ.ByteSize) {
-			p.errorf("couldn't read float")
+		buf := make([]byte, typ.ByteSize)
+		if err := p.server.peekBytes(a, buf); err != nil {
+			p.errorf("reading float: %s", err)
 			return
 		}
 		switch typ.ByteSize {
 		case 4:
-			p.printf("%g", math.Float32frombits(uint32(p.arch.UintN(p.tmp))))
+			p.printf("%g", math.Float32frombits(uint32(p.arch.UintN(buf))))
 		case 8:
-			p.printf("%g", math.Float64frombits(p.arch.UintN(p.tmp)))
+			p.printf("%g", math.Float64frombits(p.arch.UintN(buf)))
 		default:
 			p.errorf("unrecognized float size %d", typ.ByteSize)
 		}
 	case *dwarf.ComplexType:
-		if !p.peek(a, typ.ByteSize) {
-			p.errorf("couldn't read complex")
+		buf := make([]byte, typ.ByteSize)
+		if err := p.server.peekBytes(a, buf); err != nil {
+			p.errorf("reading complex: %s", err)
 			return
 		}
 		switch typ.ByteSize {
 		case 8:
-			r := math.Float32frombits(uint32(p.arch.UintN(p.tmp[:4])))
-			i := math.Float32frombits(uint32(p.arch.UintN(p.tmp[4:8])))
+			r := math.Float32frombits(uint32(p.arch.UintN(buf[:4])))
+			i := math.Float32frombits(uint32(p.arch.UintN(buf[4:8])))
 			p.printf("%g", complex(r, i))
 		case 16:
-			r := math.Float64frombits(p.arch.UintN(p.tmp[:8]))
-			i := math.Float64frombits(p.arch.UintN(p.tmp[8:16]))
+			r := math.Float64frombits(p.arch.UintN(buf[:8]))
+			i := math.Float64frombits(p.arch.UintN(buf[8:16]))
 			p.printf("%g", complex(r, i))
 		default:
 			p.errorf("unrecognized complex size %d", typ.ByteSize)
@@ -379,21 +291,21 @@
 		return
 	}
 	p.printf("(")
-	tab, ok := p.peekPtrStructField(st, a, "tab")
-	if ok {
+	tab, err := p.server.peekPtrStructField(st, a, "tab")
+	if err != nil {
+		p.errorf("reading interface type: %s", err)
+	} else {
 		f, err := getField(st, "tab")
 		if err != nil {
 			p.errorf("%s", err)
 		} else {
 			p.printTypeOfInterface(f.Type, tab)
 		}
-	} else {
-		p.errorf("couldn't read interface type")
 	}
 	p.printf(", ")
-	data, ok := p.peekPtrStructField(st, a, "data")
-	if !ok {
-		p.errorf("couldn't read interface value")
+	data, err := p.server.peekPtrStructField(st, a, "data")
+	if err != nil {
+		p.errorf("reading interface value: %s", err)
 	} else if data == 0 {
 		p.printf("<nil>")
 	} else {
@@ -461,14 +373,14 @@
 		p.errorf("bad type")
 		return
 	}
-	typeAddr, ok := p.peekPtrStructField(t3, a, "_type")
-	if !ok {
-		p.errorf("couldn't read type structure pointer")
+	typeAddr, err := p.server.peekPtrStructField(t3, a, "_type")
+	if err != nil {
+		p.errorf("reading interface type: %s", err)
 		return
 	}
-	stringAddr, ok := p.peekPtrStructField(t6, typeAddr, "_string")
-	if !ok {
-		p.errorf("couldn't read type name")
+	stringAddr, err := p.server.peekPtrStructField(t6, typeAddr, "_string")
+	if err != nil {
+		p.errorf("reading interface type: %s", err)
 		return
 	}
 	p.printStringAt(stringType, stringAddr)
@@ -490,28 +402,28 @@
 		p.errorf("bad map type: not a pointer to a struct")
 		return
 	}
-	a, ok = p.peekPtr(a)
-	if !ok {
-		p.errorf("couldn't read map pointer")
+	a, err := p.server.peekPtr(a)
+	if err != nil {
+		p.errorf("reading map pointer: %s", err)
 		return
 	}
 	if a == 0 {
 		p.printf("<nil>")
 		return
 	}
-	b, ok := p.peekUintStructField(st, a, "B")
-	if !ok {
-		p.errorf(`couldn't read map field "B"`)
+	b, err := p.server.peekUintStructField(st, a, "B")
+	if err != nil {
+		p.errorf("reading map: %s", err)
 		return
 	}
-	buckets, ok := p.peekPtrStructField(st, a, "buckets")
-	if !ok {
-		p.errorf(`couldn't read map field "buckets"`)
+	buckets, err := p.server.peekPtrStructField(st, a, "buckets")
+	if err != nil {
+		p.errorf("reading map: %s", err)
 		return
 	}
-	oldbuckets, ok := p.peekPtrStructField(st, a, "oldbuckets")
-	if !ok {
-		p.errorf(`couldn't read map field "oldbuckets"`)
+	oldbuckets, err := p.server.peekPtrStructField(st, a, "oldbuckets")
+	if err != nil {
+		p.errorf("reading map: %s", err)
 		return
 	}
 
@@ -608,9 +520,9 @@
 		// TODO: check for repeated bucket pointers.
 		for bucketAddr != 0 {
 			for j := uint64(0); j < bucketCnt; j++ {
-				tophash, ok := p.peekUint8(bucketAddr + uint64(tophashField.ByteOffset) + j)
-				if !ok {
-					p.errorf("couldn't read map")
+				tophash, err := p.server.peekUint8(bucketAddr + uint64(tophashField.ByteOffset) + j)
+				if err != nil {
+					p.errorf("reading map: ", err)
 					return
 				}
 				if tophash < minTopHash {
@@ -634,10 +546,9 @@
 					bucketAddr+uint64(valuesField.ByteOffset)+j*valuesStride)
 			}
 
-			var ok bool
-			bucketAddr, ok = p.peekPtrStructField(bt, bucketAddr, "overflow")
-			if !ok {
-				p.errorf("couldn't read map")
+			bucketAddr, err = p.server.peekPtrStructField(bt, bucketAddr, "overflow")
+			if err != nil {
+				p.errorf("reading map: ", err)
 				return
 			}
 		}
@@ -648,9 +559,9 @@
 	p.printf("(chan %s ", ct.ElemType)
 	defer p.printf(")")
 
-	a, ok := p.peekPtr(a)
-	if !ok {
-		p.errorf("couldn't read channel")
+	a, err := p.server.peekPtr(a)
+	if err != nil {
+		p.errorf("reading channel: %s", err)
 		return
 	}
 	if a == 0 {
@@ -673,14 +584,14 @@
 
 	// Print the channel buffer's length (qcount) and capacity (dataqsiz),
 	// if not 0/0.
-	qcount, ok := p.peekUintStructField(st, a, "qcount")
-	if !ok {
-		p.errorf(`couldn't read channel field "qcount"`)
+	qcount, err := p.server.peekUintStructField(st, a, "qcount")
+	if err != nil {
+		p.errorf("reading channel: %s", err)
 		return
 	}
-	dataqsiz, ok := p.peekUintStructField(st, a, "dataqsiz")
-	if !ok {
-		p.errorf(`couldn't read channel field "dataqsiz"`)
+	dataqsiz, err := p.server.peekUintStructField(st, a, "dataqsiz")
+	if err != nil {
+		p.errorf("reading channel: %s", err)
 		return
 	}
 	if qcount != 0 || dataqsiz != 0 {
@@ -691,21 +602,29 @@
 func (p *Printer) printSliceAt(typ *dwarf.SliceType, a uint64) {
 	// Slices look like a struct with fields array *elemtype, len uint32/64, cap uint32/64.
 	// BUG: Slice header appears to have fields with ByteSize == 0
-	ptr, ok1 := p.peekPtrStructField(&typ.StructType, a, "array")
-	length, ok2 := p.peekIntStructField(&typ.StructType, a, "len")
-	if !ok2 {
+	ptr, err := p.server.peekPtrStructField(&typ.StructType, a, "array")
+	if err != nil {
+		p.errorf("reading slice: %s", err)
+		return
+	}
+	length, err := p.server.peekIntStructField(&typ.StructType, a, "len")
+	if err != nil {
 		var u uint64
-		u, ok2 = p.peekUintStructField(&typ.StructType, a, "len")
+		u, err = p.server.peekUintStructField(&typ.StructType, a, "len")
+		if err != nil {
+			p.errorf("reading slice: %s", err)
+			return
+		}
 		length = int64(u)
 	}
 	// Capacity is not used yet.
-	_, ok3 := p.peekIntStructField(&typ.StructType, a, "cap")
-	if !ok3 {
-		_, ok3 = p.peekUintStructField(&typ.StructType, a, "cap")
-	}
-	if !ok1 || !ok2 || !ok3 {
-		p.errorf("couldn't read slice")
-		return
+	_, err = p.server.peekIntStructField(&typ.StructType, a, "cap")
+	if err != nil {
+		_, err = p.server.peekUintStructField(&typ.StructType, a, "cap")
+		if err != nil {
+			p.errorf("reading slice: %s", err)
+			return
+		}
 	}
 	elemType := typ.ElemType
 	size, ok := p.sizeof(typ.ElemType)
@@ -725,29 +644,30 @@
 
 func (p *Printer) printStringAt(typ *dwarf.StringType, a uint64) {
 	// BUG: String header appears to have fields with ByteSize == 0
-	ptr, ok := p.peekPtrStructField(&typ.StructType, a, "str")
-	if !ok {
-		p.errorf("couldn't read string")
+	ptr, err := p.server.peekPtrStructField(&typ.StructType, a, "str")
+	if err != nil {
+		p.errorf("reading string: %s", err)
 		return
 	}
-	length, ok := p.peekIntStructField(&typ.StructType, a, "len")
-	if !ok {
-		p.errorf("couldn't read string")
+	length, err := p.server.peekIntStructField(&typ.StructType, a, "len")
+	if err != nil {
+		p.errorf("reading string: %s", err)
 		return
 	}
-	if length > int64(cap(p.tmp)) {
-		if p.peek(ptr, int64(cap(p.tmp))) {
-			p.printf("%q...", p.tmp)
+	const maxStringSize = 100
+	if length > maxStringSize {
+		buf := make([]byte, maxStringSize)
+		if err := p.server.peekBytes(ptr, buf); err != nil {
+			p.errorf("reading string: %s", err)
 		} else {
-			p.errorf("couldn't read string")
-			return
+			p.printf("%q...", string(buf))
 		}
 	} else {
-		if p.peek(ptr, int64(length)) {
-			p.printf("%q", p.tmp[:length])
+		buf := make([]byte, length)
+		if err := p.server.peekBytes(ptr, buf); err != nil {
+			p.errorf("reading string: %s", err)
 		} else {
-			p.errorf("couldn't read string")
-			return
+			p.printf("%q", string(buf))
 		}
 	}
 }