proc/eval: Support type casts between basic types
This commit is contained in:
parent
a0ba48184e
commit
ff3e2344c4
@ -93,11 +93,14 @@ func main() {
|
||||
m2 := map[int]*astruct{1: &astruct{10, 11}}
|
||||
m3 := map[astruct]int{{1, 1}: 42, {2, 2}: 43}
|
||||
up1 := unsafe.Pointer(&i1)
|
||||
i4 := 800
|
||||
i5 := -3
|
||||
i6 := -500
|
||||
|
||||
var amb1 = 1
|
||||
runtime.Breakpoint()
|
||||
for amb1 := 0; amb1 < 10; amb1++ {
|
||||
fmt.Println(amb1)
|
||||
}
|
||||
fmt.Println(i1, i2, i3, p1, amb1, s1, a1, p2, p3, s2, as1, str1, f1, fn1, fn2, nilslice, nilptr, ch1, chnil, m1, mnil, m2, m3, up1)
|
||||
fmt.Println(i1, i2, i3, p1, amb1, s1, a1, p2, p3, s2, as1, str1, f1, fn1, fn2, nilslice, nilptr, ch1, chnil, m1, mnil, m2, m3, up1, i4, i5, i6)
|
||||
}
|
||||
|
109
proc/eval.go
109
proc/eval.go
@ -3,6 +3,7 @@ package proc
|
||||
import (
|
||||
"bytes"
|
||||
"debug/dwarf"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"go/ast"
|
||||
"go/constant"
|
||||
@ -165,7 +166,7 @@ func (scope *EvalScope) evalTypeCast(node *ast.CallExpr) (*Variable, error) {
|
||||
fnnode = p.X
|
||||
}
|
||||
|
||||
var typ dwarf.Type
|
||||
var styp, typ dwarf.Type
|
||||
|
||||
if snode, ok := fnnode.(*ast.StarExpr); ok {
|
||||
// Pointer types only appear in the dwarf informations when
|
||||
@ -177,33 +178,103 @@ func (scope *EvalScope) evalTypeCast(node *ast.CallExpr) (*Variable, error) {
|
||||
return nil, err
|
||||
}
|
||||
typ = &dwarf.PtrType{dwarf.CommonType{int64(scope.Thread.dbp.arch.PtrSize()), exprToString(fnnode)}, ptyp}
|
||||
styp = typ
|
||||
} else {
|
||||
typ, err = scope.findType(exprToString(fnnode))
|
||||
styp, err = scope.findType(exprToString(fnnode))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
typ = resolveTypedef(styp)
|
||||
}
|
||||
|
||||
// only supports cast of integer constants into pointers
|
||||
ptyp, isptrtyp := typ.(*dwarf.PtrType)
|
||||
if !isptrtyp {
|
||||
return nil, fmt.Errorf("can not convert \"%s\" to %s", exprToString(node.Args[0]), typ.String())
|
||||
converr := fmt.Errorf("can not convert \"%s\" to %s", exprToString(node.Args[0]), typ.String())
|
||||
|
||||
v := newVariable("", 0, styp, scope.Thread)
|
||||
v.loaded = true
|
||||
|
||||
switch ttyp := typ.(type) {
|
||||
case *dwarf.PtrType:
|
||||
switch argv.Kind {
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
// ok
|
||||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
|
||||
// ok
|
||||
default:
|
||||
return nil, converr
|
||||
}
|
||||
|
||||
n, _ := constant.Int64Val(argv.Value)
|
||||
|
||||
v.Children = []Variable{*newVariable("", uintptr(n), ttyp.Type, scope.Thread)}
|
||||
return v, nil
|
||||
|
||||
case *dwarf.UintType:
|
||||
switch argv.Kind {
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
n, _ := constant.Int64Val(argv.Value)
|
||||
v.Value = constant.MakeUint64(convertInt(uint64(n), false, ttyp.Size()))
|
||||
return v, nil
|
||||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
|
||||
n, _ := constant.Uint64Val(argv.Value)
|
||||
v.Value = constant.MakeUint64(convertInt(n, false, ttyp.Size()))
|
||||
return v, nil
|
||||
case reflect.Float32, reflect.Float64:
|
||||
x, _ := constant.Float64Val(argv.Value)
|
||||
v.Value = constant.MakeUint64(uint64(x))
|
||||
return v, nil
|
||||
}
|
||||
case *dwarf.IntType:
|
||||
switch argv.Kind {
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
n, _ := constant.Int64Val(argv.Value)
|
||||
v.Value = constant.MakeInt64(int64(convertInt(uint64(n), true, ttyp.Size())))
|
||||
return v, nil
|
||||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
|
||||
n, _ := constant.Uint64Val(argv.Value)
|
||||
v.Value = constant.MakeInt64(int64(convertInt(n, true, ttyp.Size())))
|
||||
return v, nil
|
||||
case reflect.Float32, reflect.Float64:
|
||||
x, _ := constant.Float64Val(argv.Value)
|
||||
v.Value = constant.MakeInt64(int64(x))
|
||||
return v, nil
|
||||
}
|
||||
case *dwarf.FloatType:
|
||||
switch argv.Kind {
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
fallthrough
|
||||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
|
||||
fallthrough
|
||||
case reflect.Float32, reflect.Float64:
|
||||
v.Value = argv.Value
|
||||
return v, nil
|
||||
}
|
||||
case *dwarf.ComplexType:
|
||||
switch argv.Kind {
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
fallthrough
|
||||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
|
||||
fallthrough
|
||||
case reflect.Float32, reflect.Float64:
|
||||
v.Value = argv.Value
|
||||
return v, nil
|
||||
}
|
||||
}
|
||||
|
||||
switch argv.Kind {
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
// ok
|
||||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
|
||||
// ok
|
||||
default:
|
||||
return nil, fmt.Errorf("can not convert \"%s\" to %s", exprToString(node.Args[0]), typ.String())
|
||||
return nil, converr
|
||||
}
|
||||
|
||||
func convertInt(n uint64, signed bool, size int64) uint64 {
|
||||
buf := make([]byte, 64/8)
|
||||
binary.BigEndian.PutUint64(buf, n)
|
||||
m := 64/8 - int(size)
|
||||
s := byte(0)
|
||||
if signed && (buf[m]&0x80 > 0) {
|
||||
s = 0xff
|
||||
}
|
||||
|
||||
n, _ := constant.Int64Val(argv.Value)
|
||||
|
||||
v := newVariable("", 0, ptyp, scope.Thread)
|
||||
v.Children = []Variable{*newVariable("", uintptr(n), ptyp.Type, scope.Thread)}
|
||||
return v, nil
|
||||
for i := 0; i < m; i++ {
|
||||
buf[i] = s
|
||||
}
|
||||
return uint64(binary.BigEndian.Uint64(buf))
|
||||
}
|
||||
|
||||
// Evaluates identifier expressions
|
||||
|
@ -118,14 +118,7 @@ func newVariable(name string, addr uintptr, dwarfType dwarf.Type, thread *Thread
|
||||
thread: thread,
|
||||
}
|
||||
|
||||
v.RealType = v.DwarfType
|
||||
for {
|
||||
if tt, ok := v.RealType.(*dwarf.TypedefType); ok {
|
||||
v.RealType = tt.Type
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
v.RealType = resolveTypedef(v.DwarfType)
|
||||
|
||||
switch t := v.RealType.(type) {
|
||||
case *dwarf.PtrType:
|
||||
@ -201,6 +194,16 @@ func newVariable(name string, addr uintptr, dwarfType dwarf.Type, thread *Thread
|
||||
return v
|
||||
}
|
||||
|
||||
func resolveTypedef(typ dwarf.Type) dwarf.Type {
|
||||
for {
|
||||
if tt, ok := typ.(*dwarf.TypedefType); ok {
|
||||
typ = tt.Type
|
||||
} else {
|
||||
return typ
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func newConstant(val constant.Value, thread *Thread) *Variable {
|
||||
v := &Variable{Value: val, thread: thread, loaded: true}
|
||||
switch val.Kind() {
|
||||
|
@ -487,6 +487,16 @@ func TestEvalExpression(t *testing.T) {
|
||||
{"*(i2 + i3)", false, "", "", "", fmt.Errorf("expression \"(i2 + i3)\" (int) can not be dereferenced")},
|
||||
{"i2.member", false, "", "", "", fmt.Errorf("i2 (type int) is not a struct")},
|
||||
{"fmt.Println(\"hello\")", false, "", "", "", fmt.Errorf("no type entry found")},
|
||||
|
||||
// typecasts
|
||||
{"uint(i2)", false, "2", "", "uint", nil},
|
||||
{"int8(i2)", false, "2", "", "int8", nil},
|
||||
{"int(f1)", false, "3", "", "int", nil},
|
||||
{"complex128(f1)", false, "(3 + 0i)", "", "complex128", nil},
|
||||
{"uint8(i4)", false, "32", "", "uint8", nil},
|
||||
{"uint8(i5)", false, "253", "", "uint8", nil},
|
||||
{"int8(i5)", false, "-3", "", "int8", nil},
|
||||
{"int8(i6)", false, "12", "", "int8", nil},
|
||||
}
|
||||
|
||||
withTestProcess("testvariables3", t, func(p *proc.Process, fixture protest.Fixture) {
|
||||
|
Loading…
Reference in New Issue
Block a user