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 {