提交 ff3e2344 编写于 作者: A aarzilli 提交者: Derek Parker

proc/eval: Support type casts between basic types

上级 a0ba4818
......@@ -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)
}
......@@ -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())
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())
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
}
}
n, _ := constant.Int64Val(argv.Value)
return nil, converr
}
v := newVariable("", 0, ptyp, scope.Thread)
v.Children = []Variable{*newVariable("", uintptr(n), ptyp.Type, scope.Thread)}
return v, nil
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
}
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) {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册