Example #1
0
func newVariable(name string, addr uintptr, dwarfType dwarf.Type, thread *Thread) (*Variable, error) {
	v := &Variable{
		Name:      name,
		Addr:      addr,
		dwarfType: dwarfType,
		thread:    thread,
		Type:      dwarfType.String(),
	}

	switch t := dwarfType.(type) {
	case *dwarf.StructType:
		if strings.HasPrefix(t.StructName, "[]") {
			err := v.loadSliceInfo(t)
			if err != nil {
				return nil, err
			}
		}
	case *dwarf.ArrayType:
		v.base = v.Addr
		v.Len = t.Count
		v.Cap = -1
		v.fieldType = t.Type
		v.stride = 0

		if t.Count > 0 {
			v.stride = t.ByteSize / t.Count
		}
	}

	return v, nil
}
Example #2
0
func (v *Variable) isType(typ dwarf.Type, kind reflect.Kind) error {
	if v.DwarfType != nil {
		if typ != nil && typ.String() != v.RealType.String() {
			return fmt.Errorf("can not convert value of type %s to %s", v.DwarfType.String(), typ.String())
		}
		return nil
	}

	if typ == nil {
		return nil
	}

	if v == nilVariable {
		switch kind {
		case reflect.Slice, reflect.Map, reflect.Func, reflect.Ptr, reflect.Chan, reflect.Interface:
			return nil
		default:
			return fmt.Errorf("mismatched types nil and %s", typ.String())
		}
	}

	converr := fmt.Errorf("can not convert %s constant to %s", v.Value, typ.String())

	if v.Value == nil {
		return converr
	}

	switch t := typ.(type) {
	case *dwarf.IntType:
		if v.Value.Kind() != constant.Int {
			return converr
		}
	case *dwarf.UintType:
		if v.Value.Kind() != constant.Int {
			return converr
		}
	case *dwarf.FloatType:
		if (v.Value.Kind() != constant.Int) && (v.Value.Kind() != constant.Float) {
			return converr
		}
	case *dwarf.BoolType:
		if v.Value.Kind() != constant.Bool {
			return converr
		}
	case *dwarf.StructType:
		if t.StructName != "string" {
			return converr
		}
		if v.Value.Kind() != constant.String {
			return converr
		}
	case *dwarf.ComplexType:
		if v.Value.Kind() != constant.Complex && v.Value.Kind() != constant.Float && v.Value.Kind() != constant.Int {
			return converr
		}
	default:
		return converr
	}

	return nil
}
Example #3
0
// Eval type cast expressions
func (scope *EvalScope) evalTypeCast(node *ast.CallExpr) (*Variable, error) {
	if len(node.Args) != 1 {
		return nil, fmt.Errorf("wrong number of arguments for a type cast")
	}

	argv, err := scope.evalAST(node.Args[0])
	if err != nil {
		return nil, err
	}
	argv.loadValue()
	if argv.Unreadable != nil {
		return nil, argv.Unreadable
	}

	fnnode := node.Fun

	// remove all enclosing parenthesis from the type name
	for {
		p, ok := fnnode.(*ast.ParenExpr)
		if !ok {
			break
		}
		fnnode = p.X
	}

	var typ dwarf.Type

	if snode, ok := fnnode.(*ast.StarExpr); ok {
		// Pointer types only appear in the dwarf informations when
		// a pointer to the type is used in the target program, here
		// we create a pointer type on the fly so that the user can
		// specify a pointer to any variable used in the target program
		ptyp, err := scope.findType(exprToString(snode.X))
		if err != nil {
			return nil, err
		}
		typ = &dwarf.PtrType{dwarf.CommonType{int64(scope.Thread.dbp.arch.PtrSize()), exprToString(fnnode)}, ptyp}
	} else {
		typ, err = scope.findType(exprToString(fnnode))
		if err != nil {
			return nil, err
		}
	}

	// 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())
	}

	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())
	}

	n, _ := constant.Int64Val(argv.Value)

	v := newVariable("", 0, ptyp, scope.Thread)
	v.Children = []Variable{*newVariable("", uintptr(n), ptyp.Type, scope.Thread)}
	return v, nil
}