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