x/debug: allow various internal struct fields to be signed or unsigned.

The DWARF output can change between compiler versions.

Change-Id: I2f1d7d1fed854ef6ad5aafa94b08bd73ce410506
Reviewed-on: https://go-review.googlesource.com/12402
Reviewed-by: Rob Pike <r@golang.org>
diff --git a/ogle/program/server/peek.go b/ogle/program/server/peek.go
index 484b3f1..a2f03ce 100644
--- a/ogle/program/server/peek.go
+++ b/ogle/program/server/peek.go
@@ -66,6 +66,33 @@
 	return s.peekPtr(addr + uint64(f.ByteOffset))
 }
 
+// peekUintOrIntStructField reads a signed or unsigned integer in the field fieldName
+// of the struct of type t at addr. If the value is negative, it returns an error.
+// This function is used when the value should be non-negative, but the DWARF
+// type of the field may be signed or unsigned.
+func (s *Server) peekUintOrIntStructField(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 s.peekUint(addr+uint64(f.ByteOffset), ut.ByteSize)
+	}
+	it, ok := f.Type.(*dwarf.IntType)
+	if !ok {
+		return 0, fmt.Errorf("field %s is not an integer", fieldName)
+	}
+	i, err := s.peekInt(addr+uint64(f.ByteOffset), it.ByteSize)
+	if err != nil {
+		return 0, err
+	}
+	if i < 0 {
+		return 0, fmt.Errorf("field %s is negative", fieldName)
+	}
+	return uint64(i), nil
+}
+
 // 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) {
diff --git a/ogle/program/server/print.go b/ogle/program/server/print.go
index f78a2cb..b133dd3 100644
--- a/ogle/program/server/print.go
+++ b/ogle/program/server/print.go
@@ -584,12 +584,12 @@
 
 	// Print the channel buffer's length (qcount) and capacity (dataqsiz),
 	// if not 0/0.
-	qcount, err := p.server.peekUintStructField(st, a, "qcount")
+	qcount, err := p.server.peekUintOrIntStructField(st, a, "qcount")
 	if err != nil {
 		p.errorf("reading channel: %s", err)
 		return
 	}
-	dataqsiz, err := p.server.peekUintStructField(st, a, "dataqsiz")
+	dataqsiz, err := p.server.peekUintOrIntStructField(st, a, "dataqsiz")
 	if err != nil {
 		p.errorf("reading channel: %s", err)
 		return
@@ -607,24 +607,16 @@
 		p.errorf("reading slice: %s", err)
 		return
 	}
-	length, err := p.server.peekIntStructField(&typ.StructType, a, "len")
+	length, err := p.server.peekUintOrIntStructField(&typ.StructType, a, "len")
 	if err != nil {
-		var u uint64
-		u, err = p.server.peekUintStructField(&typ.StructType, a, "len")
-		if err != nil {
-			p.errorf("reading slice: %s", err)
-			return
-		}
-		length = int64(u)
+		p.errorf("reading slice: %s", err)
+		return
 	}
 	// Capacity is not used yet.
-	_, err = p.server.peekIntStructField(&typ.StructType, a, "cap")
+	_, err = p.server.peekUintOrIntStructField(&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
-		}
+		p.errorf("reading slice: %s", err)
+		return
 	}
 	elemType := typ.ElemType
 	size, ok := p.sizeof(typ.ElemType)
@@ -632,7 +624,7 @@
 		p.errorf("can't determine element size")
 	}
 	p.printf("%s{", typ)
-	for i := int64(0); i < length; i++ {
+	for i := uint64(0); i < length; i++ {
 		if i != 0 {
 			p.printf(", ")
 		}
@@ -649,7 +641,7 @@
 		p.errorf("reading string: %s", err)
 		return
 	}
-	length, err := p.server.peekIntStructField(&typ.StructType, a, "len")
+	length, err := p.server.peekUintOrIntStructField(&typ.StructType, a, "len")
 	if err != nil {
 		p.errorf("reading string: %s", err)
 		return