func (dbp *Process) resolveNameOff(typeAddr uintptr, off uintptr) (uintptr, error) { // See runtime.resolveNameOff in $GOROOT/src/runtime/type.go if err := dbp.loadModuleData(); err != nil { return 0, err } for _, md := range dbp.moduleData { if typeAddr >= md.types && typeAddr < md.etypes { return md.types + off, nil } } scope := &EvalScope{Thread: dbp.CurrentThread, PC: 0, CFA: 0} reflectOffs, err := scope.packageVarAddr("runtime.reflectOffs") if err != nil { return 0, err } reflectOffsm, err := reflectOffs.structMember("m") if err != nil { return 0, err } v, err := reflectOffsm.mapAccess(newConstant(constant.MakeUint64(uint64(off)), dbp.CurrentThread)) if err != nil { return 0, err } resv := v.maybeDereference() if resv.Unreadable != nil { return 0, resv.Unreadable } return resv.Addr, nil }
func (s *scanner) scanParam(lval *sqlSymType) { start := s.pos for isDigit(s.peek()) { s.pos++ } lval.str = s.in[start:s.pos] uval, err := strconv.ParseUint(lval.str, 10, 64) if err == nil && uval > 1<<63 { err = fmt.Errorf("integer value out of range: %d", uval) } if err != nil { lval.id = ERROR lval.str = err.Error() return } // uval is now in the range [0, 1<<63]. Casting to an int64 leaves the range // [0, 1<<63 - 1] intact and moves 1<<63 to -1<<63 (a.k.a. math.MinInt64). lval.union.val = &NumVal{Value: constant.MakeUint64(uval)} lval.id = PARAM }
func (v *Variable) loadValueInternal(recurseLevel int, cfg LoadConfig) { if v.Unreadable != nil || v.loaded || (v.Addr == 0 && v.Base == 0) { return } v.loaded = true switch v.Kind { case reflect.Ptr, reflect.UnsafePointer: v.Len = 1 v.Children = []Variable{*v.maybeDereference()} if cfg.FollowPointers { // Don't increase the recursion level when dereferencing pointers v.Children[0].loadValueInternal(recurseLevel, cfg) } else { v.Children[0].OnlyAddr = true } case reflect.Chan: sv := v.clone() sv.RealType = resolveTypedef(&(sv.RealType.(*dwarf.ChanType).TypedefType)) sv = sv.maybeDereference() sv.loadValueInternal(0, loadFullValue) v.Children = sv.Children v.Len = sv.Len v.Base = sv.Addr case reflect.Map: if recurseLevel <= cfg.MaxVariableRecurse { v.loadMap(recurseLevel, cfg) } case reflect.String: var val string val, v.Unreadable = readStringValue(v.mem, v.Base, v.Len, cfg) v.Value = constant.MakeString(val) case reflect.Slice, reflect.Array: v.loadArrayValues(recurseLevel, cfg) case reflect.Struct: v.mem = cacheMemory(v.mem, v.Addr, int(v.RealType.Size())) t := v.RealType.(*dwarf.StructType) v.Len = int64(len(t.Field)) // Recursively call extractValue to grab // the value of all the members of the struct. if recurseLevel <= cfg.MaxVariableRecurse { v.Children = make([]Variable, 0, len(t.Field)) for i, field := range t.Field { if cfg.MaxStructFields >= 0 && len(v.Children) >= cfg.MaxStructFields { break } f, _ := v.toField(field) v.Children = append(v.Children, *f) v.Children[i].Name = field.Name v.Children[i].loadValueInternal(recurseLevel+1, cfg) } } case reflect.Interface: v.loadInterface(recurseLevel, true, cfg) case reflect.Complex64, reflect.Complex128: v.readComplex(v.RealType.(*dwarf.ComplexType).ByteSize) case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: var val int64 val, v.Unreadable = readIntRaw(v.mem, v.Addr, v.RealType.(*dwarf.IntType).ByteSize) v.Value = constant.MakeInt64(val) case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: var val uint64 val, v.Unreadable = readUintRaw(v.mem, v.Addr, v.RealType.(*dwarf.UintType).ByteSize) v.Value = constant.MakeUint64(val) case reflect.Bool: val, err := v.mem.readMemory(v.Addr, 1) v.Unreadable = err if err == nil { v.Value = constant.MakeBool(val[0] != 0) } case reflect.Float32, reflect.Float64: var val float64 val, v.Unreadable = v.readFloatRaw(v.RealType.(*dwarf.FloatType).ByteSize) v.Value = constant.MakeFloat64(val) case reflect.Func: v.readFunctionPtr() default: v.Unreadable = fmt.Errorf("unknown or unsupported kind: \"%s\"", v.Kind.String()) } }
// Eval type cast expressions func (scope *EvalScope) evalTypeCast(node *ast.CallExpr) (*Variable, error) { 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 } styp, err := scope.Thread.dbp.findTypeExpr(fnnode) if err != nil { return nil, err } typ := resolveTypedef(styp) converr := fmt.Errorf("can not convert %q to %s", exprToString(node.Args[0]), typ.String()) v := newVariable("", 0, styp, scope.Thread.dbp, 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{*(scope.newVariable("", uintptr(n), ttyp.Type))} 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 } } return nil, converr }
func (v *Variable) loadValueInternal(recurseLevel int) { if v.Unreadable != nil || v.loaded || (v.Addr == 0 && v.base == 0) { return } v.loaded = true switch v.Kind { case reflect.Ptr, reflect.UnsafePointer: v.Len = 1 v.Children = []Variable{*v.maybeDereference()} // Don't increase the recursion level when dereferencing pointers v.Children[0].loadValueInternal(recurseLevel) case reflect.Chan: sv := v.maybeDereference() sv.loadValueInternal(recurseLevel) v.Children = sv.Children v.Len = sv.Len v.base = sv.Addr case reflect.Map: v.loadMap(recurseLevel) case reflect.String: var val string val, v.Unreadable = v.thread.readStringValue(v.base, v.Len) v.Value = constant.MakeString(val) case reflect.Slice, reflect.Array: v.loadArrayValues(recurseLevel) case reflect.Struct: t := v.RealType.(*dwarf.StructType) v.Len = int64(len(t.Field)) // Recursively call extractValue to grab // the value of all the members of the struct. if recurseLevel <= maxVariableRecurse { v.Children = make([]Variable, 0, len(t.Field)) for i, field := range t.Field { f, _ := v.toField(field) v.Children = append(v.Children, *f) v.Children[i].Name = field.Name v.Children[i].loadValueInternal(recurseLevel + 1) } } case reflect.Complex64, reflect.Complex128: v.readComplex(v.RealType.(*dwarf.ComplexType).ByteSize) case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: var val int64 val, v.Unreadable = v.thread.readIntRaw(v.Addr, v.RealType.(*dwarf.IntType).ByteSize) v.Value = constant.MakeInt64(val) case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: var val uint64 val, v.Unreadable = v.thread.readUintRaw(v.Addr, v.RealType.(*dwarf.UintType).ByteSize) v.Value = constant.MakeUint64(val) case reflect.Bool: val, err := v.thread.readMemory(v.Addr, 1) v.Unreadable = err if err == nil { v.Value = constant.MakeBool(val[0] != 0) } case reflect.Float32, reflect.Float64: var val float64 val, v.Unreadable = v.readFloatRaw(v.RealType.(*dwarf.FloatType).ByteSize) v.Value = constant.MakeFloat64(val) case reflect.Func: v.readFunctionPtr() default: v.Unreadable = fmt.Errorf("unknown or unsupported kind: \"%s\"", v.Kind.String()) } }