x/debug: add support for selector expressions on structs and pointers to structs.
Change-Id: I008ab99e35716263a9ad4250f9cc9e899d242ddb
Reviewed-on: https://go-review.googlesource.com/16348
Reviewed-by: Dave Day <djd@golang.org>
diff --git a/ogle/demo/ogler/ogler_test.go b/ogle/demo/ogler/ogler_test.go
index 522fab0..d825fc9 100644
--- a/ogle/demo/ogler/ogler_test.go
+++ b/ogle/demo/ogler/ogler_test.go
@@ -222,6 +222,13 @@
`local_slice[1:3]`: program.Slice{program.Array{42, 42, 2, 8}, 4},
`local_slice[:3:4]`: program.Slice{program.Array{42, 42, 3, 8}, 4},
`local_slice[1:3:4]`: program.Slice{program.Array{42, 42, 2, 8}, 3},
+ `local_struct.a`: 21,
+ `(&local_struct).a`: 21,
+ `(*local_pointer).a`: 21,
+ `(&*local_pointer).a`: 21,
+ `(*local_pointer).b`: program.String{2, `hi`},
+ `local_pointer.a`: 21,
+ `local_pointer.b`: program.String{2, `hi`},
`5 + false`: nil,
``: nil,
`x + ""`: nil,
@@ -241,6 +248,10 @@
`local_string[22]`: nil,
`"hello"[-2]`: nil,
`"hello"[22]`: nil,
+ `local_pointer_nil.a`: nil,
+ `(local_struct).c`: nil,
+ `(&local_struct).c`: nil,
+ `(*local_pointer).c`: nil,
}
func isHex(r uint8) bool {
diff --git a/ogle/program/server/eval.go b/ogle/program/server/eval.go
index 475331a..72c3f56 100644
--- a/ogle/program/server/eval.go
+++ b/ogle/program/server/eval.go
@@ -294,6 +294,50 @@
}
return e.err("invalid indirect")
+ case *ast.SelectorExpr:
+ x := e.evalNode(n.X, false)
+ sel := n.Sel.Name
+ switch v := x.v.(type) {
+ case program.Struct:
+ for _, f := range v.Fields {
+ if f.Name == sel {
+ t, err := e.server.dwarfData.Type(dwarf.Offset(f.Var.TypeID))
+ if err != nil {
+ return e.err(err.Error())
+ }
+ return e.resultFrom(f.Var.Address, t, getAddress)
+ }
+ }
+ return e.err("struct field not found")
+ case program.Pointer:
+ pt, ok := followTypedefs(x.d).(*dwarf.PtrType) // x.d should be a pointer to struct.
+ if !ok {
+ return e.err("invalid DWARF information for pointer")
+ }
+ st, ok := followTypedefs(pt.Type).(*dwarf.StructType)
+ if !ok {
+ break
+ }
+ for _, f := range st.Field {
+ if f.Name == sel {
+ return e.resultFrom(v.Address+uint64(f.ByteOffset), f.Type, getAddress)
+ }
+ }
+ return e.err("struct field not found")
+ case pointerToValue:
+ st, ok := followTypedefs(x.d).(*dwarf.StructType) // x.d should be a struct.
+ if !ok {
+ break
+ }
+ for _, f := range st.Field {
+ if f.Name == sel {
+ return e.resultFrom(v.a+uint64(f.ByteOffset), f.Type, getAddress)
+ }
+ }
+ return e.err("struct field not found")
+ }
+ return e.err("invalid selector expression")
+
case *ast.IndexExpr:
x, index := e.evalNode(n.X, false), e.evalNode(n.Index, false)
if x.v == nil || index.v == nil {
diff --git a/ogle/program/server/eval.m4 b/ogle/program/server/eval.m4
index 694b7c1..8540ba5 100644
--- a/ogle/program/server/eval.m4
+++ b/ogle/program/server/eval.m4
@@ -294,6 +294,50 @@
}
return e.err("invalid indirect")
+ case *ast.SelectorExpr:
+ x := e.evalNode(n.X, false)
+ sel := n.Sel.Name
+ switch v := x.v.(type) {
+ case program.Struct:
+ for _, f := range v.Fields {
+ if f.Name == sel {
+ t, err := e.server.dwarfData.Type(dwarf.Offset(f.Var.TypeID))
+ if err != nil {
+ return e.err(err.Error())
+ }
+ return e.resultFrom(f.Var.Address, t, getAddress)
+ }
+ }
+ return e.err("struct field not found")
+ case program.Pointer:
+ pt, ok := followTypedefs(x.d).(*dwarf.PtrType) // x.d should be a pointer to struct.
+ if !ok {
+ return e.err("invalid DWARF information for pointer")
+ }
+ st, ok := followTypedefs(pt.Type).(*dwarf.StructType)
+ if !ok {
+ break
+ }
+ for _, f := range st.Field {
+ if f.Name == sel {
+ return e.resultFrom(v.Address+uint64(f.ByteOffset), f.Type, getAddress)
+ }
+ }
+ return e.err("struct field not found")
+ case pointerToValue:
+ st, ok := followTypedefs(x.d).(*dwarf.StructType) // x.d should be a struct.
+ if !ok {
+ break
+ }
+ for _, f := range st.Field {
+ if f.Name == sel {
+ return e.resultFrom(v.a+uint64(f.ByteOffset), f.Type, getAddress)
+ }
+ }
+ return e.err("struct field not found")
+ }
+ return e.err("invalid selector expression")
+
case *ast.IndexExpr:
x, index := e.evalNode(n.X, false), e.evalNode(n.Index, false)
if x.v == nil || index.v == nil {