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