diff --git a/pkg/proc/eval.go b/pkg/proc/eval.go index 5433badcb2..94ef278433 100644 --- a/pkg/proc/eval.go +++ b/pkg/proc/eval.go @@ -739,9 +739,14 @@ func (scope *EvalScope) evalTypeCastOrFuncCall(node *ast.CallExpr) (*Variable, e return v, err } - fnnode := removeParen(node.Fun) - if n, _ := fnnode.(*ast.StarExpr); n != nil { - fnnode = removeParen(n.X) + fnnode := node.Fun + for { + fnnode = removeParen(fnnode) + n, _ := fnnode.(*ast.StarExpr) + if n == nil { + break + } + fnnode = n.X } switch n := fnnode.(type) { @@ -811,6 +816,11 @@ func (scope *EvalScope) evalTypeCast(node *ast.CallExpr) (*Variable, error) { // compatible underlying types if typeCastCompatibleTypes(argv.RealType, typ) { + if ptyp, isptr := typ.(*godwarf.PtrType); argv.Kind == reflect.Ptr && argv.loaded && len(argv.Children) > 0 && isptr { + cv := argv.Children[0] + argv.Children[0] = *newVariable(cv.Name, cv.Addr, ptyp.Type, cv.bi, cv.mem) + argv.Children[0].OnlyAddr = true + } argv.RealType = typ argv.DwarfType = styp return argv, nil @@ -1028,6 +1038,11 @@ func typeCastCompatibleTypes(typ1, typ2 godwarf.Type) bool { switch ttyp1 := typ1.(type) { case *godwarf.PtrType: if ttyp2, ok := typ2.(*godwarf.PtrType); ok { + _, isvoid1 := ttyp1.Type.(*godwarf.VoidType) + _, isvoid2 := ttyp2.Type.(*godwarf.VoidType) + if isvoid1 || isvoid2 { + return true + } // pointer types are compatible if their element types are compatible return typeCastCompatibleTypes(resolveTypedef(ttyp1.Type), resolveTypedef(ttyp2.Type)) } diff --git a/pkg/proc/variables_test.go b/pkg/proc/variables_test.go index 1c84f7eb1f..22c350375e 100644 --- a/pkg/proc/variables_test.go +++ b/pkg/proc/variables_test.go @@ -820,6 +820,15 @@ func TestEvalExpression(t *testing.T) { {`(*string)(&typedstringvar)`, false, `(*string)(…`, `(*string)(…`, "*string", nil}, {`(*main.astruct)(&namedA1)`, false, `(*main.astruct)(…`, `(*main.astruct)(…`, "*main.astruct", nil}, {`(*main.astructName2)(&namedA1)`, false, `(*main.astructName2)(…`, `(*main.astructName2)(…`, "*main.astructName2", nil}, + + // Conversions to and from uintptr/unsafe.Pointer + {`*(*uint)(uintptr(p1))`, false, `1`, `1`, "uint", nil}, + {`*(*uint)(uintptr(&i1))`, false, `1`, `1`, "uint", nil}, + {`*(*uint)(unsafe.Pointer(p1))`, false, `1`, `1`, "uint", nil}, + {`*(*uint)(unsafe.Pointer(&i1))`, false, `1`, `1`, "uint", nil}, + + // Conversions to ptr-to-ptr types + {`**(**runtime.hmap)(uintptr(&m1))`, false, `…`, `…`, "runtime.hmap", nil}, } ver, _ := goversion.Parse(runtime.Version())