proc: make structMember work on pointer Variables created through cast

When casting an integer into a struct pointer we make a fake pointer
variable that doesn't have an address, maybeDereference and
structMember should still work on this kind of Variable.

Fixes #1432
This commit is contained in:
aarzilli 2018-12-03 14:53:39 +01:00 committed by Derek Parker
parent d7d4c144c8
commit 34e802a42b
3 changed files with 38 additions and 0 deletions

16
_fixtures/issue1432.go Normal file

@ -0,0 +1,16 @@
package main
import "runtime"
type s struct {
i int64
}
func main() {
i := 1
p := &i
s := s{i: 1}
_ = s
runtime.Breakpoint()
println(i, p)
}

@ -4117,3 +4117,21 @@ func TestIssue1374(t *testing.T) {
} }
}) })
} }
func TestIssue1432(t *testing.T) {
// Check that taking the address of a struct, casting it into a pointer to
// the struct's type and then accessing a member field will still:
// - perform auto-dereferencing on struct member access
// - yield a Variable that's ultimately assignable (i.e. has an address)
withTestProcess("issue1432", t, func(p proc.Process, fixture protest.Fixture) {
assertNoError(proc.Continue(p), t, "Continue")
svar := evalVariable(p, t, "s")
t.Logf("%#x", svar.Addr)
scope, err := proc.GoroutineScope(p.CurrentThread())
assertNoError(err, t, "GoroutineScope()")
err = scope.SetVariable(fmt.Sprintf("(*\"main.s\")(%#x).i", svar.Addr), "10")
assertNoError(err, t, "SetVariable")
})
}

@ -932,6 +932,10 @@ func (v *Variable) maybeDereference() *Variable {
switch t := v.RealType.(type) { switch t := v.RealType.(type) {
case *godwarf.PtrType: case *godwarf.PtrType:
if v.Addr == 0 && len(v.Children) == 1 && v.loaded {
// fake pointer variable constructed by casting an integer to a pointer type
return &v.Children[0]
}
ptrval, err := readUintRaw(v.mem, uintptr(v.Addr), t.ByteSize) ptrval, err := readUintRaw(v.mem, uintptr(v.Addr), t.ByteSize)
r := v.newVariable("", uintptr(ptrval), t.Type, DereferenceMemory(v.mem)) r := v.newVariable("", uintptr(ptrval), t.Type, DereferenceMemory(v.mem))
if err != nil { if err != nil {