debug: make type "address" which the printer uses to refer to addresses and offsets in the tracee.

Change-Id: I5570a62829f318991f17a9a6810953a7e405800b
Reviewed-on: https://go-review.googlesource.com/1871
Reviewed-by: Rob Pike <r@golang.org>
diff --git a/ogle/program/server/print.go b/ogle/program/server/print.go
index 6658ec4..c407cdf 100644
--- a/ogle/program/server/print.go
+++ b/ogle/program/server/print.go
@@ -13,6 +13,9 @@
 	"golang.org/x/debug/ogle/arch"
 )
 
+// address is a type denoting addresses in the tracee.
+type address uintptr
+
 // Routines to print a value using DWARF type descriptions.
 // TODO: Does this deserve its own package? It has no dependencies on Server.
 
@@ -26,12 +29,12 @@
 	arch     *arch.Architecture
 	printBuf bytes.Buffer     // Accumulates the output.
 	tmp      []byte           // Temporary used for I/O.
-	visited  map[uintptr]bool // Prevents looping on cyclic data.
+	visited  map[address]bool // Prevents looping on cyclic data.
 	// The cache stores a local copy of part of the address space.
 	// Saves I/O overhead when scanning map buckets by letting
 	// printValueAt use the contents of already-read bucket data.
-	cache    []byte  // Already-read data.
-	cacheOff uintptr // Starting address of cache.
+	cache     []byte  // Already-read data.
+	cacheAddr address // Starting address of cache.
 }
 
 // printf prints to printBuf, unless there has been an error.
@@ -62,25 +65,25 @@
 
 // peek reads len bytes at offset, leaving p.tmp with the data and sized appropriately.
 // It uses the cache if the request is within it.
-func (p *Printer) peek(offset uintptr, length int64) bool {
+func (p *Printer) peek(a address, length int64) bool {
 	p.tmp = p.tmp[:length]
-	if p.cacheOff <= offset && offset+uintptr(length) <= p.cacheOff+uintptr(len(p.cache)) {
-		copy(p.tmp, p.cache[offset-p.cacheOff:])
+	if p.cacheAddr <= a && a+address(length) <= p.cacheAddr+address(len(p.cache)) {
+		copy(p.tmp, p.cache[a-p.cacheAddr:])
 		return true
 	}
-	return p.ok(p.peeker.peek(offset, p.tmp))
+	return p.ok(p.peeker.peek(uintptr(a), p.tmp))
 }
 
 // setCache initializes the cache to contain the contents of the
 // address space at the specified offset.
-func (p *Printer) setCache(offset, length uintptr) bool {
-	if uintptr(cap(p.cache)) >= length {
+func (p *Printer) setCache(a, length address) bool {
+	if address(cap(p.cache)) >= length {
 		p.cache = p.cache[:length]
 	} else {
 		p.cache = make([]byte, length)
 	}
-	p.cacheOff = offset
-	ok := p.ok(p.peeker.peek(offset, p.cache))
+	p.cacheAddr = a
+	ok := p.ok(p.peeker.peek(uintptr(a), p.cache))
 	if !ok {
 		p.resetCache()
 	}
@@ -89,7 +92,7 @@
 
 func (p *Printer) resetCache() {
 	p.cache = p.cache[0:0]
-	p.cacheOff = 0
+	p.cacheAddr = 0
 }
 
 // Peeker is like a read that probes the remote address space.
@@ -104,7 +107,7 @@
 		peeker:  peeker,
 		arch:    arch,
 		dwarf:   dwarf,
-		visited: make(map[uintptr]bool),
+		visited: make(map[address]bool),
 		tmp:     make([]byte, 100), // Enough for a largish string.
 	}
 }
@@ -130,12 +133,12 @@
 	p.reset()
 	switch entry.Tag {
 	case dwarf.TagVariable: // TODO: What other entries have global location attributes?
-		addr := uintptr(0)
+		var a address
 		iface := entry.Val(dwarf.AttrLocation)
 		if iface != nil {
-			addr = p.decodeLocation(iface.([]byte))
+			a = p.decodeLocation(iface.([]byte))
 		}
-		p.printEntryValueAt(entry, addr)
+		p.printEntryValueAt(entry, a)
 	default:
 		p.errorf("unrecognized entry type %s", entry.Tag)
 	}
@@ -148,10 +151,10 @@
 )
 
 // decodeLocation decodes the dwarf data describing an address.
-func (p *Printer) decodeLocation(data []byte) uintptr {
+func (p *Printer) decodeLocation(data []byte) address {
 	switch data[0] {
 	case locationAddr:
-		return uintptr(p.arch.Uintptr(data[1:]))
+		return address(p.arch.Uintptr(data[1:]))
 	default:
 		p.errorf("unimplemented location type %#x", data[0])
 	}
@@ -159,16 +162,16 @@
 }
 
 // SprintEntry returns the pretty-printed value of the item with the specified DWARF Entry and address.
-func (p *Printer) SprintEntry(entry *dwarf.Entry, addr uintptr) (string, error) {
+func (p *Printer) SprintEntry(entry *dwarf.Entry, a address) (string, error) {
 	p.reset()
-	p.printEntryValueAt(entry, addr)
+	p.printEntryValueAt(entry, a)
 	return p.printBuf.String(), p.err
 }
 
 // printEntryValueAt pretty-prints the data at the specified addresss
 // using the type information in the Entry.
-func (p *Printer) printEntryValueAt(entry *dwarf.Entry, addr uintptr) {
-	if addr == 0 {
+func (p *Printer) printEntryValueAt(entry *dwarf.Entry, a address) {
+	if a == 0 {
 		p.printf("<nil>")
 		return
 	}
@@ -189,15 +192,15 @@
 		p.errorf("type lookup: %v", err)
 		return
 	}
-	p.printValueAt(typ, addr)
+	p.printValueAt(typ, a)
 }
 
 // printValueAt pretty-prints the data at the specified addresss
 // using the provided type information.
-func (p *Printer) printValueAt(typ dwarf.Type, addr uintptr) {
+func (p *Printer) printValueAt(typ dwarf.Type, a address) {
 	// Make sure we don't recur forever.
-	if p.visited[addr] {
-		p.printf("(@%x...)", addr)
+	if p.visited[a] {
+		p.printf("(@%x...)", a)
 		return
 	}
 	switch typ := typ.(type) {
@@ -206,25 +209,25 @@
 			p.errorf("unrecognized bool size %d", typ.ByteSize)
 			return
 		}
-		if p.peek(addr, 1) {
+		if p.peek(a, 1) {
 			p.printf("%t", p.tmp[0] != 0)
 		}
 	case *dwarf.PtrType:
 		// This type doesn't define the ByteSize attribute.
-		if p.peek(addr, int64(p.arch.PointerSize)) {
+		if p.peek(a, int64(p.arch.PointerSize)) {
 			p.printf("%#x", p.arch.Uintptr(p.tmp))
 		}
 	case *dwarf.IntType:
 		// Sad we can't tell a rune from an int32.
-		if p.peek(addr, typ.ByteSize) {
+		if p.peek(a, typ.ByteSize) {
 			p.printf("%d", p.arch.IntN(p.tmp))
 		}
 	case *dwarf.UintType:
-		if p.peek(addr, typ.ByteSize) {
+		if p.peek(a, typ.ByteSize) {
 			p.printf("%d", p.arch.UintN(p.tmp))
 		}
 	case *dwarf.FloatType:
-		if !p.peek(addr, typ.ByteSize) {
+		if !p.peek(a, typ.ByteSize) {
 			return
 		}
 		switch typ.ByteSize {
@@ -236,7 +239,7 @@
 			p.errorf("unrecognized float size %d", typ.ByteSize)
 		}
 	case *dwarf.ComplexType:
-		if !p.peek(addr, typ.ByteSize) {
+		if !p.peek(a, typ.ByteSize) {
 			return
 		}
 		switch typ.ByteSize {
@@ -252,7 +255,7 @@
 			p.errorf("unrecognized complex size %d", typ.ByteSize)
 		}
 	case *dwarf.StructType:
-		p.visited[addr] = true
+		p.visited[a] = true
 		if typ.Kind != "struct" {
 			// Could be "class" or "union".
 			p.errorf("can't handle struct type %s", typ.Kind)
@@ -263,19 +266,19 @@
 			if i != 0 {
 				p.printf(", ")
 			}
-			p.printValueAt(field.Type, addr+uintptr(field.ByteOffset))
+			p.printValueAt(field.Type, a+address(field.ByteOffset))
 		}
 		p.printf("}")
 	case *dwarf.ArrayType:
-		p.printArrayAt(typ, addr)
+		p.printArrayAt(typ, a)
 	case *dwarf.MapType:
-		p.visited[addr] = true
-		p.printMapAt(typ, addr)
+		p.visited[a] = true
+		p.printMapAt(typ, a)
 	case *dwarf.SliceType:
-		p.visited[addr] = true
-		p.printSliceAt(typ, addr)
+		p.visited[a] = true
+		p.printSliceAt(typ, a)
 	case *dwarf.StringType:
-		p.printStringAt(typ, addr)
+		p.printStringAt(typ, a)
 	case *dwarf.TypedefType:
 		p.errorf("unimplemented typedef type %T %v", typ, typ)
 	default:
@@ -284,7 +287,7 @@
 	}
 }
 
-func (p *Printer) printArrayAt(typ *dwarf.ArrayType, addr uintptr) {
+func (p *Printer) printArrayAt(typ *dwarf.ArrayType, a address) {
 	elemType := typ.Type
 	length := typ.Count
 	stride := typ.StrideBitSize
@@ -305,8 +308,8 @@
 		if i != 0 {
 			p.printf(", ")
 		}
-		p.printValueAt(elemType, addr)
-		addr += uintptr(stride) // TODO: Alignment and padding - not given by Type
+		p.printValueAt(elemType, a)
+		a += address(stride) // TODO: Alignment and padding - not given by Type
 	}
 	if n < length {
 		p.printf(", ...")
@@ -319,21 +322,21 @@
 	typ        *dwarf.MapType
 	count      int
 	numBuckets int
-	keySize    uintptr
-	elemSize   uintptr
-	bucketSize uintptr
+	keySize    address
+	elemSize   address
+	bucketSize address
 }
 
-func (p *Printer) printMapAt(typ *dwarf.MapType, addr uintptr) {
+func (p *Printer) printMapAt(typ *dwarf.MapType, a address) {
 	// Maps are pointers to a struct type.
 	structType := typ.Type.(*dwarf.PtrType).Type.(*dwarf.StructType)
 	// Indirect through the pointer.
-	if !p.peek(addr, int64(p.arch.PointerSize)) {
+	if !p.peek(a, int64(p.arch.PointerSize)) {
 		return
 	}
-	addr = uintptr(p.arch.Uintptr(p.tmp[:p.arch.PointerSize]))
+	a = address(p.arch.Uintptr(p.tmp[:p.arch.PointerSize]))
 	// Now read the struct.
-	if !p.peek(addr, structType.ByteSize) {
+	if !p.peek(a, structType.ByteSize) {
 		return
 	}
 	// From runtime/hashmap.go; We need to walk the map data structure.
@@ -344,17 +347,17 @@
 	// uint8 Log2 of number of buckets.
 	b := uint(p.tmp[structType.Field[3].ByteOffset])
 	// uint8 key size in bytes.
-	keySize := uintptr(p.tmp[structType.Field[4].ByteOffset])
+	keySize := address(p.tmp[structType.Field[4].ByteOffset])
 	// uint8 element size in bytes.
-	elemSize := uintptr(p.tmp[structType.Field[5].ByteOffset])
+	elemSize := address(p.tmp[structType.Field[5].ByteOffset])
 	// uint16 bucket size in bytes.
-	bucketSize := uintptr(p.arch.Uint16(p.tmp[structType.Field[6].ByteOffset:]))
+	bucketSize := address(p.arch.Uint16(p.tmp[structType.Field[6].ByteOffset:]))
 	// pointer to buckets
 	offset = int(structType.Field[7].ByteOffset)
-	bucketPtr := uintptr(p.arch.Uintptr(p.tmp[offset : offset+p.arch.PointerSize]))
+	bucketPtr := address(p.arch.Uintptr(p.tmp[offset : offset+p.arch.PointerSize]))
 	// pointer to old buckets.
 	offset = int(structType.Field[8].ByteOffset)
-	oldBucketPtr := uintptr(p.arch.Uintptr(p.tmp[offset : offset+p.arch.PointerSize]))
+	oldBucketPtr := address(p.arch.Uintptr(p.tmp[offset : offset+p.arch.PointerSize]))
 	// Ready to print.
 	p.printf("%s{", typ)
 	desc := mapDesc{
@@ -376,19 +379,19 @@
 	minTopHash = 4
 )
 
-func (p *Printer) printMapBucketsAt(desc mapDesc, addr uintptr) {
-	if addr == 0 {
+func (p *Printer) printMapBucketsAt(desc mapDesc, a address) {
+	if a == 0 {
 		return
 	}
 	for i := 0; desc.count > 0 && i < desc.numBuckets; i++ {
 		// After the header, the bucket struct has an array of keys followed by an array of elements.
 		// Load this bucket struct into p's cache and initialize "pointers" to the key and value slices.
-		if !p.setCache(addr, desc.bucketSize) {
+		if !p.setCache(a, desc.bucketSize) {
 			return
 		}
-		keyAddr := addr + bucketCnt + uintptr(p.arch.PointerSize)
+		keyAddr := a + bucketCnt + address(p.arch.PointerSize)
 		elemAddr := keyAddr + bucketCnt*desc.keySize
-		addr += desc.bucketSize // Advance to next bucket; keyAddr and elemAddr are all we need now.
+		a += desc.bucketSize // Advance to next bucket; keyAddr and elemAddr are all we need now.
 		// tophash uint8 [bucketCnt] tells us which buckets are occupied.
 		// p.cache has the data but calls to printValueAt below may overwrite the
 		// cache, so grab a copy of the relevant data.
@@ -397,7 +400,7 @@
 			p.errorf("bad count copying hash flags")
 			return
 		}
-		overflow := uintptr(p.arch.Uintptr(p.cache[bucketCnt : bucketCnt+p.arch.PointerSize]))
+		overflow := address(p.arch.Uintptr(p.cache[bucketCnt : bucketCnt+p.arch.PointerSize]))
 		for j := 0; desc.count > 0 && j < bucketCnt; j++ {
 			if tophash[j] >= minTopHash {
 				p.printValueAt(desc.typ.KeyType, keyAddr)
@@ -416,16 +419,16 @@
 	}
 }
 
-func (p *Printer) printSliceAt(typ *dwarf.SliceType, addr uintptr) {
+func (p *Printer) printSliceAt(typ *dwarf.SliceType, a address) {
 	// 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
-	if !p.peek(addr, typ.ByteSize) {
+	if !p.peek(a, typ.ByteSize) {
 		p.errorf("slice header has no known size")
 		return
 	}
 	lo := typ.Field[0].ByteOffset
 	hi := lo + int64(p.arch.PointerSize)
-	ptr := uintptr(p.arch.UintN(p.tmp[lo:hi]))
+	ptr := address(p.arch.UintN(p.tmp[lo:hi]))
 	lo = typ.Field[1].ByteOffset
 	hi = lo + int64(p.arch.IntSize)
 	length := p.arch.UintN(p.tmp[lo:hi])
@@ -441,15 +444,15 @@
 			p.printf(", ")
 		}
 		p.printValueAt(elemType, ptr)
-		ptr += uintptr(size) // TODO: Alignment and padding - not given by Type
+		ptr += address(size) // TODO: Alignment and padding - not given by Type
 	}
 	p.printf("}")
 }
 
-func (p *Printer) printStringAt(typ *dwarf.StringType, addr uintptr) {
+func (p *Printer) printStringAt(typ *dwarf.StringType, a address) {
 	// Strings look like a struct with fields array *elemtype, len uint64.
 	// TODO uint64 on 386 too?
-	if !p.peek(addr, typ.ByteSize) {
+	if !p.peek(a, typ.ByteSize) {
 		p.errorf("string header has no known size")
 		return
 	}
@@ -461,11 +464,11 @@
 	hi = lo + int64(p.arch.IntSize) // TODO?
 	length := p.arch.UintN(p.tmp[lo:hi])
 	if length > uint64(cap(p.tmp)) {
-		if p.peek(uintptr(ptr), int64(cap(p.tmp))) {
+		if p.peek(address(ptr), int64(cap(p.tmp))) {
 			p.printf("%q...", p.tmp)
 		}
 	} else {
-		if p.peek(uintptr(ptr), int64(length)) {
+		if p.peek(address(ptr), int64(length)) {
 			p.printf("%q", p.tmp[:length])
 		}
 	}
diff --git a/ogle/program/server/server.go b/ogle/program/server/server.go
index 40da397..1717094 100644
--- a/ogle/program/server/server.go
+++ b/ogle/program/server/server.go
@@ -596,7 +596,7 @@
 					name = f.Val.(string)
 				}
 			}
-			str, err := s.printer.SprintEntry(entry, uintptr(fp)+uintptr(offset))
+			str, err := s.printer.SprintEntry(entry, address(fp)+address(offset))
 			fmt.Fprintf(b, "%s (%d(FP)) = %s ", name, offset, str)
 			if err != nil {
 				fmt.Fprintf(b, "(%s) ", err)