Skip to content

Commit

Permalink
Two fixes to type cast evaluation (go-delve#3186)
Browse files Browse the repository at this point in the history
* proc: allow casts form unsafe.Pointer to any pointer and vice versa

We've allowed doing this with uintptr but we should allow
unsafe.Pointer to be used like Go uses it.

* proc: fix type casts to ptr-to-ptr types

Fix type casts to **type.
  • Loading branch information
aarzilli authored Nov 10, 2022
1 parent c7fa713 commit 824e0a8
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 3 deletions.
21 changes: 18 additions & 3 deletions pkg/proc/eval.go
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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))
}
Expand Down
9 changes: 9 additions & 0 deletions pkg/proc/variables_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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())
Expand Down

0 comments on commit 824e0a8

Please sign in to comment.