Пример #1
0
func TestNextConcurrentVariant2(t *testing.T) {
	// Just like TestNextConcurrent but instead of removing the initial breakpoint we check that when it happens is for other goroutines
	testcases := []nextTest{
		{8, 9},
		{9, 10},
		{10, 11},
	}
	withTestProcess("parallel_next", t, func(p *Process, fixture protest.Fixture) {
		_, err := setFunctionBreakpoint(p, "main.sayhi")
		assertNoError(err, t, "SetBreakpoint")
		assertNoError(p.Continue(), t, "Continue")
		f, ln := currentLineNumber(p, t)
		initV, err := evalVariable(p, "n")
		initVval, _ := constant.Int64Val(initV.Value)
		assertNoError(err, t, "EvalVariable")
		for _, tc := range testcases {
			g, err := p.CurrentThread.GetG()
			assertNoError(err, t, "GetG()")
			if p.SelectedGoroutine.ID != g.ID {
				t.Fatalf("SelectedGoroutine not CurrentThread's goroutine: %d %d", g.ID, p.SelectedGoroutine.ID)
			}
			if ln != tc.begin {
				t.Fatalf("Program not stopped at correct spot expected %d was %s:%d", tc.begin, filepath.Base(f), ln)
			}
			assertNoError(p.Next(), t, "Next() returned an error")
			var vval int64
			for {
				v, err := evalVariable(p, "n")
				assertNoError(err, t, "EvalVariable")
				vval, _ = constant.Int64Val(v.Value)
				if p.CurrentThread.CurrentBreakpoint == nil {
					if vval != initVval {
						t.Fatal("Did not end up on same goroutine")
					}
					break
				} else {
					if vval == initVval {
						t.Fatal("Initial breakpoint triggered twice for the same goroutine")
					}
					assertNoError(p.Continue(), t, "Continue 2")
				}
			}
			f, ln = currentLineNumber(p, t)
			if ln != tc.end {
				t.Fatalf("Program did not continue to correct next location expected %d was %s:%d", tc.end, filepath.Base(f), ln)
			}
		}
	})
}
Пример #2
0
// goVal returns the Go value for val, or nil.
func goVal(val constant.Value) interface{} {
	// val should exist, but be conservative and check
	if val == nil {
		return nil
	}
	// Match implementation restriction of other compilers.
	// gc only checks duplicates for integer, floating-point
	// and string values, so only create Go values for these
	// types.
	switch val.Kind() {
	case constant.Int:
		if x, ok := constant.Int64Val(val); ok {
			return x
		}
		if x, ok := constant.Uint64Val(val); ok {
			return x
		}
	case constant.Float:
		if x, ok := constant.Float64Val(val); ok {
			return x
		}
	case constant.String:
		return constant.StringVal(val)
	}
	return nil
}
Пример #3
0
func (g *javaGen) genConst(o *types.Const) {
	// TODO(hyangah): should const names use upper cases + "_"?
	// TODO(hyangah): check invalid names.
	jType := g.javaType(o.Type())
	val := o.Val().String()
	switch b := o.Type().(*types.Basic); b.Kind() {
	case types.Int64, types.UntypedInt:
		i, exact := constant.Int64Val(o.Val())
		if !exact {
			g.errorf("const value %s for %s cannot be represented as %s", val, o.Name(), jType)
			return
		}
		val = fmt.Sprintf("%dL", i)

	case types.Float32:
		f, _ := constant.Float32Val(o.Val())
		val = fmt.Sprintf("%gf", f)

	case types.Float64, types.UntypedFloat:
		f, _ := constant.Float64Val(o.Val())
		if math.IsInf(f, 0) || math.Abs(f) > math.MaxFloat64 {
			g.errorf("const value %s for %s cannot be represented as %s", val, o.Name(), jType)
			return
		}
		val = fmt.Sprintf("%g", f)
	}
	g.Printf("public static final %s %s = %s;\n", g.javaType(o.Type()), o.Name(), val)
}
Пример #4
0
func TestPointerSetting(t *testing.T) {
	withTestProcess("testvariables3", t, func(p *Process, fixture protest.Fixture) {
		assertNoError(p.Continue(), t, "Continue() returned an error")

		pval := func(n int64) {
			variable, err := evalVariable(p, "p1")
			assertNoError(err, t, "EvalVariable()")
			c0val, _ := constant.Int64Val(variable.Children[0].Value)
			if c0val != n {
				t.Fatalf("Wrong value of p1, *%d expected *%d", c0val, n)
			}
		}

		pval(1)

		// change p1 to point to i2
		scope, err := p.CurrentThread.Scope()
		assertNoError(err, t, "Scope()")
		i2addr, err := scope.EvalExpression("i2")
		assertNoError(err, t, "EvalExpression()")
		assertNoError(setVariable(p, "p1", fmt.Sprintf("(*int)(0x%x)", i2addr.Addr)), t, "SetVariable()")
		pval(2)

		// change the value of i2 check that p1 also changes
		assertNoError(setVariable(p, "i2", "5"), t, "SetVariable()")
		pval(5)
	})
}
Пример #5
0
func (p *exporter) value(x constant.Value) {
	if trace {
		p.tracef("value { ")
		defer p.tracef("} ")
	}

	switch kind := x.Kind(); kind {
	case constant.Bool:
		tag := falseTag
		if constant.BoolVal(x) {
			tag = trueTag
		}
		p.int(tag)
	case constant.Int:
		if i, ok := constant.Int64Val(x); ok {
			p.int(int64Tag)
			p.int64(i)
			return
		}
		p.int(floatTag)
		p.float(x)
	case constant.Float:
		p.int(fractionTag)
		p.fraction(x)
	case constant.Complex:
		p.int(complexTag)
		p.fraction(constant.Real(x))
		p.fraction(constant.Imag(x))
	case constant.String:
		p.int(stringTag)
		p.string(constant.StringVal(x))
	default:
		panic(fmt.Sprintf("unexpected value kind %d", kind))
	}
}
Пример #6
0
func (n *Node) Val() Val {
	var expr ast.Expr
	var ok bool
	if expr, ok = n.Node.(ast.Expr); ok {
		var typeAndValue types.TypeAndValue
		if typeAndValue, ok = n.Ctx.fn.Types[expr]; ok {
			if typeAndValue.Value == nil {
				panic("internal compiler error")
			}
			if typeAndValue.Value.Kind() != constant.Int {
				panic("unimplemented")
			}
			if i64, exact := constant.Int64Val(typeAndValue.Value); exact {
				mpInt := Mpint{}
				mpInt.Val = *big.NewInt(i64)
				val := Val{}
				val.U = &mpInt
				return val
			} else {
				panic("internal compiler error")
			}
		} else {
			panic("internal compiler error")
		}
	} else if _, ok = n.Node.(*ast.BasicLit); ok {
		panic("unimplemented")

	} else {
		// TODO: other ast.*
		return Val{}
	}
}
Пример #7
0
func (v *Variable) setValue(y *Variable) error {
	var err error
	switch v.Kind {
	case reflect.Float32, reflect.Float64:
		f, _ := constant.Float64Val(y.Value)
		err = v.writeFloatRaw(f, v.RealType.Size())
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		n, _ := constant.Int64Val(y.Value)
		err = v.writeUint(uint64(n), v.RealType.Size())
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
		n, _ := constant.Uint64Val(y.Value)
		err = v.writeUint(n, v.RealType.Size())
	case reflect.Bool:
		err = v.writeBool(constant.BoolVal(y.Value))
	case reflect.Complex64, reflect.Complex128:
		real, _ := constant.Float64Val(constant.Real(y.Value))
		imag, _ := constant.Float64Val(constant.Imag(y.Value))
		err = v.writeComplex(real, imag, v.RealType.Size())
	default:
		fmt.Printf("default\n")
		if t, isptr := v.RealType.(*dwarf.PtrType); isptr {
			err = v.writeUint(uint64(y.Children[0].Addr), int64(t.ByteSize))
		} else {
			return fmt.Errorf("can not set variables of type %s (not implemented)", v.Kind.String())
		}
	}

	return err
}
Пример #8
0
func (v *Variable) loadSliceInfo(t *dwarf.SliceType) {
	v.mem = cacheMemory(v.mem, v.Addr, int(t.Size()))

	var err error
	for _, f := range t.Field {
		switch f.Name {
		case "array":
			var base uint64
			base, err = readUintRaw(v.mem, uintptr(int64(v.Addr)+f.ByteOffset), f.Type.Size())
			if err == nil {
				v.Base = uintptr(base)
				// Dereference array type to get value type
				ptrType, ok := f.Type.(*dwarf.PtrType)
				if !ok {
					v.Unreadable = fmt.Errorf("Invalid type %s in slice array", f.Type)
					return
				}
				v.fieldType = ptrType.Type
			}
		case "len":
			lstrAddr, _ := v.toField(f)
			lstrAddr.loadValue(loadSingleValue)
			err = lstrAddr.Unreadable
			if err == nil {
				v.Len, _ = constant.Int64Val(lstrAddr.Value)
			}
		case "cap":
			cstrAddr, _ := v.toField(f)
			cstrAddr.loadValue(loadSingleValue)
			err = cstrAddr.Unreadable
			if err == nil {
				v.Cap, _ = constant.Int64Val(cstrAddr.Value)
			}
		}
		if err != nil {
			v.Unreadable = err
			return
		}
	}

	v.stride = v.fieldType.Size()
	if t, ok := v.fieldType.(*dwarf.PtrType); ok {
		v.stride = t.ByteSize
	}

	return
}
Пример #9
0
func (v *Variable) loadSliceInfo(t *dwarf.StructType) {
	var err error
	for _, f := range t.Field {
		switch f.Name {
		case "array":
			var base uint64
			base, err = v.thread.readUintRaw(uintptr(int64(v.Addr)+f.ByteOffset), int64(v.thread.dbp.arch.PtrSize()))
			if err == nil {
				v.base = uintptr(base)
				// Dereference array type to get value type
				ptrType, ok := f.Type.(*dwarf.PtrType)
				if !ok {
					v.Unreadable = fmt.Errorf("Invalid type %s in slice array", f.Type)
					return
				}
				v.fieldType = ptrType.Type
			}
		case "len":
			lstrAddr, _ := v.toField(f)
			lstrAddr.loadValue()
			err = lstrAddr.Unreadable
			if err == nil {
				v.Len, _ = constant.Int64Val(lstrAddr.Value)
			}
		case "cap":
			cstrAddr, _ := v.toField(f)
			cstrAddr.loadValue()
			err = cstrAddr.Unreadable
			if err == nil {
				v.Cap, _ = constant.Int64Val(cstrAddr.Value)
			}
		}
		if err != nil {
			v.Unreadable = err
			return
		}
	}

	v.stride = v.fieldType.Size()
	if _, ok := v.fieldType.(*dwarf.PtrType); ok {
		v.stride = int64(v.thread.dbp.arch.PtrSize())
	}

	return
}
Пример #10
0
// asInt64 returns the value as a 64-bit integer if possible, or returns an
// error if not possible.
func (expr *NumVal) asInt64() (int64, error) {
	intVal, ok := expr.asConstantInt()
	if !ok {
		return 0, fmt.Errorf("cannot represent %v as an int", expr.Value)
	}
	i, exact := constant.Int64Val(intVal)
	if !exact {
		return 0, fmt.Errorf("representing %v as an int would overflow", intVal)
	}
	return i, nil
}
Пример #11
0
// asInt64 returns the value as a 64-bit integer if possible, or returns an
// error if not possible. The method will set expr.resInt to the value of
// this int64 if it is successful, avoiding the need to call the method again.
func (expr *NumVal) asInt64() (int64, error) {
	intVal, ok := expr.asConstantInt()
	if !ok {
		return 0, errConstNotInt
	}
	i, exact := constant.Int64Val(intVal)
	if !exact {
		return 0, errConstOutOfRange
	}
	expr.resInt = DInt(i)
	return i, nil
}
Пример #12
0
// Conversion type-checks the conversion T(x).
// The result is in x.
func (check *Checker) conversion(x *operand, T Type) {
	constArg := x.mode == constant_

	var ok bool
	switch {
	case constArg && isConstType(T):
		// constant conversion
		switch t := T.Underlying().(*Basic); {
		case representableConst(x.val, check.conf, t.kind, &x.val):
			ok = true
		case isInteger(x.typ) && isString(t):
			codepoint := int64(-1)
			if i, ok := constant.Int64Val(x.val); ok {
				codepoint = i
			}
			// If codepoint < 0 the absolute value is too large (or unknown) for
			// conversion. This is the same as converting any other out-of-range
			// value - let string(codepoint) do the work.
			x.val = constant.MakeString(string(codepoint))
			ok = true
		}
	case x.convertibleTo(check.conf, T):
		// non-constant conversion
		x.mode = value
		ok = true
	}

	if !ok {
		check.errorf(x.pos(), "cannot convert %s to %s", x, T)
		x.mode = invalid
		return
	}

	// The conversion argument types are final. For untyped values the
	// conversion provides the type, per the spec: "A constant may be
	// given a type explicitly by a constant declaration or conversion,...".
	final := x.typ
	if isUntyped(x.typ) {
		final = T
		// - For conversions to interfaces, use the argument's default type.
		// - For conversions of untyped constants to non-constant types, also
		//   use the default type (e.g., []byte("foo") should report string
		//   not []byte as type for the constant "foo").
		// - Keep untyped nil for untyped nil arguments.
		if IsInterface(T) || constArg && !isConstType(T) {
			final = defaultType(x.typ)
		}
		check.updateExprType(x.expr, final, true)
	}

	x.typ = T
}
Пример #13
0
func (gvar *Variable) parseG() (*G, error) {
	mem := gvar.mem
	dbp := gvar.dbp
	gaddr := uint64(gvar.Addr)
	_, deref := gvar.RealType.(*dwarf.PtrType)

	initialInstructions := make([]byte, dbp.arch.PtrSize()+1)
	initialInstructions[0] = op.DW_OP_addr
	binary.LittleEndian.PutUint64(initialInstructions[1:], gaddr)
	if deref {
		gaddrbytes, err := mem.readMemory(uintptr(gaddr), dbp.arch.PtrSize())
		if err != nil {
			return nil, fmt.Errorf("error derefing *G %s", err)
		}
		initialInstructions = append([]byte{op.DW_OP_addr}, gaddrbytes...)
		gaddr = binary.LittleEndian.Uint64(gaddrbytes)
		if gaddr == 0 {
			id := 0
			if thread, ok := mem.(*Thread); ok {
				id = thread.ID
			}
			return nil, NoGError{tid: id}
		}
	}
	if gaddr == 0 {
		return nil, NoGError{}
	}
	gvar.loadValue()
	if gvar.Unreadable != nil {
		return nil, gvar.Unreadable
	}
	schedVar := gvar.toFieldNamed("sched")
	pc, _ := constant.Int64Val(schedVar.toFieldNamed("pc").Value)
	sp, _ := constant.Int64Val(schedVar.toFieldNamed("sp").Value)
	id, _ := constant.Int64Val(gvar.toFieldNamed("goid").Value)
	gopc, _ := constant.Int64Val(gvar.toFieldNamed("gopc").Value)
	waitReason := constant.StringVal(gvar.toFieldNamed("waitreason").Value)
	d := gvar.toFieldNamed("_defer")
	deferPC := int64(0)
	fnvar := d.toFieldNamed("fn")
	if fnvar != nil {
		fnvalvar := fnvar.toFieldNamed("fn")
		deferPC, _ = constant.Int64Val(fnvalvar.Value)
	}
	status, _ := constant.Int64Val(gvar.toFieldNamed("atomicstatus").Value)
	f, l, fn := gvar.dbp.goSymTable.PCToLine(uint64(pc))
	g := &G{
		ID:         int(id),
		GoPC:       uint64(gopc),
		PC:         uint64(pc),
		SP:         uint64(sp),
		WaitReason: waitReason,
		DeferPC:    uint64(deferPC),
		Status:     uint64(status),
		CurrentLoc: Location{PC: uint64(pc), File: f, Line: l, Fn: fn},
		dbp:        gvar.dbp,
	}
	return g, nil
}
Пример #14
0
func TestNextConcurrent(t *testing.T) {
	testcases := []nextTest{
		{8, 9},
		{9, 10},
		{10, 11},
	}
	withTestProcess("parallel_next", t, func(p *Process, fixture protest.Fixture) {
		bp, err := setFunctionBreakpoint(p, "main.sayhi")
		assertNoError(err, t, "SetBreakpoint")
		assertNoError(p.Continue(), t, "Continue")
		f, ln := currentLineNumber(p, t)
		initV, err := evalVariable(p, "n")
		initVval, _ := constant.Int64Val(initV.Value)
		assertNoError(err, t, "EvalVariable")
		_, err = p.ClearBreakpoint(bp.Addr)
		assertNoError(err, t, "ClearBreakpoint()")
		for _, tc := range testcases {
			g, err := p.CurrentThread.GetG()
			assertNoError(err, t, "GetG()")
			if p.SelectedGoroutine.ID != g.ID {
				t.Fatalf("SelectedGoroutine not CurrentThread's goroutine: %d %d", g.ID, p.SelectedGoroutine.ID)
			}
			if ln != tc.begin {
				t.Fatalf("Program not stopped at correct spot expected %d was %s:%d", tc.begin, filepath.Base(f), ln)
			}
			assertNoError(p.Next(), t, "Next() returned an error")
			f, ln = currentLineNumber(p, t)
			if ln != tc.end {
				t.Fatalf("Program did not continue to correct next location expected %d was %s:%d", tc.end, filepath.Base(f), ln)
			}
			v, err := evalVariable(p, "n")
			assertNoError(err, t, "EvalVariable")
			vval, _ := constant.Int64Val(v.Value)
			if vval != initVval {
				t.Fatal("Did not end up on same goroutine")
			}
		}
	})
}
Пример #15
0
// Int64 returns the numeric value of this constant truncated to fit
// a signed 64-bit integer.
//
func (c *Const) Int64() int64 {
	switch x := c.Value; x.Kind() {
	case exact.Int:
		if i, ok := exact.Int64Val(x); ok {
			return i
		}
		return 0
	case exact.Float:
		f, _ := exact.Float64Val(x)
		return int64(f)
	}
	panic(fmt.Sprintf("unexpected constant value: %T", c.Value))
}
Пример #16
0
func (g *ObjcGen) genConstM(o *types.Const) {
	if _, ok := o.Type().(*types.Basic); !ok {
		g.Printf("// skipped const %s with unsupported type: %T\n\n", o.Name(), o)
		return
	}
	cName := fmt.Sprintf("%s%s", g.namePrefix, o.Name())
	objcType := g.objcType(o.Type())

	switch b := o.Type().(*types.Basic); b.Kind() {
	case types.Bool, types.UntypedBool:
		v := "NO"
		if constant.BoolVal(o.Val()) {
			v = "YES"
		}
		g.Printf("const BOOL %s = %s;\n", cName, v)

	case types.String, types.UntypedString:
		g.Printf("NSString* const %s = @%s;\n", cName, constExactString(o))

	case types.Int, types.Int8, types.Int16, types.Int32:
		g.Printf("const %s %s = %s;\n", objcType, cName, o.Val())

	case types.Int64, types.UntypedInt:
		i, exact := constant.Int64Val(o.Val())
		if !exact {
			g.errorf("const value %s for %s cannot be represented as %s", o.Val(), o.Name(), objcType)
			return
		}
		if i == math.MinInt64 {
			// -9223372036854775808LL does not work because 922337203685477508 is
			// larger than max int64.
			g.Printf("const int64_t %s = %dLL-1;\n", cName, i+1)
		} else {
			g.Printf("const int64_t %s = %dLL;\n", cName, i)
		}

	case types.Float32, types.Float64, types.UntypedFloat:
		f, _ := constant.Float64Val(o.Val())
		if math.IsInf(f, 0) || math.Abs(f) > math.MaxFloat64 {
			g.errorf("const value %s for %s cannot be represented as double", o.Val(), o.Name())
			return
		}
		g.Printf("const %s %s = %g;\n", objcType, cName, f)

	default:
		g.errorf("unsupported const type %s for %s", b, o.Name())
	}
}
Пример #17
0
func (v *Variable) asInt() (int64, error) {
	if v.DwarfType == nil {
		if v.Value.Kind() != constant.Int {
			return 0, fmt.Errorf("can not convert constant %s to int", v.Value)
		}
	} else {
		v.loadValue()
		if v.Unreadable != nil {
			return 0, v.Unreadable
		}
		if _, ok := v.DwarfType.(*dwarf.IntType); !ok {
			return 0, fmt.Errorf("can not convert value of type %s to int", v.DwarfType.String())
		}
	}
	n, _ := constant.Int64Val(v.Value)
	return n, nil
}
Пример #18
0
// checkLongShift checks if shift or shift-assign operations shift by more than
// the length of the underlying variable.
func checkLongShift(f *File, node ast.Node, x, y ast.Expr) {
	if f.pkg.types[x].Value != nil {
		// Ignore shifts of constants.
		// These are frequently used for bit-twiddling tricks
		// like ^uint(0) >> 63 for 32/64 bit detection and compatibility.
		return
	}
	v := f.pkg.types[y].Value
	if v == nil {
		return
	}
	amt, ok := constant.Int64Val(v)
	if !ok {
		return
	}
	t := f.pkg.types[x].Type
	if t == nil {
		return
	}
	b, ok := t.Underlying().(*types.Basic)
	if !ok {
		return
	}
	var size int64
	var msg string
	switch b.Kind() {
	case types.Uint8, types.Int8:
		size = 8
	case types.Uint16, types.Int16:
		size = 16
	case types.Uint32, types.Int32:
		size = 32
	case types.Uint64, types.Int64:
		size = 64
	case types.Int, types.Uint, types.Uintptr:
		// These types may be as small as 32 bits, but no smaller.
		size = 32
		msg = "might be "
	default:
		return
	}
	if amt >= size {
		ident := f.gofmt(x)
		f.Badf(node.Pos(), "%s %stoo small for shift of %d", ident, msg, amt)
	}
}
Пример #19
0
func (p *exporter) value(x constant.Value) {
	if trace {
		p.tracef("= ")
	}

	switch x.Kind() {
	case constant.Bool:
		tag := falseTag
		if constant.BoolVal(x) {
			tag = trueTag
		}
		p.tag(tag)

	case constant.Int:
		if v, exact := constant.Int64Val(x); exact {
			// common case: x fits into an int64 - use compact encoding
			p.tag(int64Tag)
			p.int64(v)
			return
		}
		// uncommon case: large x - use float encoding
		// (powers of 2 will be encoded efficiently with exponent)
		p.tag(floatTag)
		p.float(constant.ToFloat(x))

	case constant.Float:
		p.tag(floatTag)
		p.float(x)

	case constant.Complex:
		p.tag(complexTag)
		p.float(constant.Real(x))
		p.float(constant.Imag(x))

	case constant.String:
		p.tag(stringTag)
		p.string(constant.StringVal(x))

	case constant.Unknown:
		// package contains type errors
		p.tag(unknownTag)

	default:
		log.Fatalf("gcimporter: unexpected value %v (%T)", x, x)
	}
}
Пример #20
0
func TestCondBreakpointError(t *testing.T) {
	withTestProcess("parallel_next", t, func(p *Process, fixture protest.Fixture) {
		addr, _, err := p.goSymTable.LineToPC(fixture.Source, 9)
		assertNoError(err, t, "LineToPC")
		bp, err := p.SetBreakpoint(addr)
		assertNoError(err, t, "SetBreakpoint()")
		bp.Cond = &ast.BinaryExpr{
			Op: token.EQL,
			X:  &ast.Ident{Name: "nonexistentvariable"},
			Y:  &ast.BasicLit{Kind: token.INT, Value: "7"},
		}

		err = p.Continue()
		if err == nil {
			t.Fatalf("No error on first Continue()")
		}

		if err.Error() != "error evaluating expression: could not find symbol value for nonexistentvariable" && err.Error() != "multiple errors evaluating conditions" {
			t.Fatalf("Unexpected error on first Continue(): %v", err)
		}

		bp.Cond = &ast.BinaryExpr{
			Op: token.EQL,
			X:  &ast.Ident{Name: "n"},
			Y:  &ast.BasicLit{Kind: token.INT, Value: "7"},
		}

		err = p.Continue()
		if err != nil {
			if _, exited := err.(ProcessExitedError); !exited {
				t.Fatalf("Unexpected error on second Continue(): %v", err)
			}
		} else {
			nvar, err := evalVariable(p, "n")
			assertNoError(err, t, "EvalVariable()")

			n, _ := constant.Int64Val(nvar.Value)
			if n != 7 {
				t.Fatalf("Stoppend on wrong goroutine %d\n", n)
			}
		}
	})
}
Пример #21
0
func (check *Checker) arrayLength(e ast.Expr) int64 {
	var x operand
	check.expr(&x, e)
	if x.mode != constant {
		if x.mode != invalid {
			check.errorf(x.pos(), "array length %s must be constant", &x)
		}
		return 0
	}
	if !x.isInteger() {
		check.errorf(x.pos(), "array length %s must be integer", &x)
		return 0
	}
	n, ok := exact.Int64Val(x.val)
	if !ok || n < 0 {
		check.errorf(x.pos(), "invalid array length %s", &x)
		return 0
	}
	return n
}
Пример #22
0
// checkLongShift checks if shift or shift-assign operations shift by more than
// the length of the underlying variable.
func checkLongShift(f *File, node ast.Node, x, y ast.Expr) {
	v := f.pkg.types[y].Value
	if v == nil {
		return
	}
	amt, ok := exact.Int64Val(v)
	if !ok {
		return
	}
	t := f.pkg.types[x].Type
	if t == nil {
		return
	}
	b, ok := t.Underlying().(*types.Basic)
	if !ok {
		return
	}
	var size int64
	var msg string
	switch b.Kind() {
	case types.Uint8, types.Int8:
		size = 8
	case types.Uint16, types.Int16:
		size = 16
	case types.Uint32, types.Int32:
		size = 32
	case types.Uint64, types.Int64:
		size = 64
	case types.Int, types.Uint, types.Uintptr:
		// These types may be as small as 32 bits, but no smaller.
		size = 32
		msg = "might be "
	default:
		return
	}
	if amt >= size {
		ident := f.gofmt(x)
		f.Badf(node.Pos(), "%s %stoo small for shift of %d", ident, msg, amt)
	}
}
Пример #23
0
// ResolveAsType implements the Constant interface.
func (expr *NumVal) ResolveAsType(typ Datum) (Datum, error) {
	switch {
	case typ.TypeEqual(TypeInt):
		i, exact := constant.Int64Val(constant.ToInt(expr.Value))
		if !exact {
			return nil, fmt.Errorf("integer value out of range: %v", expr.Value)
		}
		return NewDInt(DInt(i)), nil
	case typ.TypeEqual(TypeFloat):
		f, _ := constant.Float64Val(constant.ToFloat(expr.Value))
		return NewDFloat(DFloat(f)), nil
	case typ.TypeEqual(TypeDecimal):
		dd := &DDecimal{}
		s := expr.ExactString()
		if idx := strings.IndexRune(s, '/'); idx != -1 {
			// Handle constant.ratVal, which will return a rational string
			// like 6/7. If only we could call big.Rat.FloatString() on it...
			num, den := s[:idx], s[idx+1:]
			if _, ok := dd.SetString(num); !ok {
				return nil, fmt.Errorf("could not evaluate numerator of %v as Datum type DDecimal "+
					"from string %q", expr, num)
			}
			denDec := new(inf.Dec)
			if _, ok := denDec.SetString(den); !ok {
				return nil, fmt.Errorf("could not evaluate denominator %v as Datum type DDecimal "+
					"from string %q", expr, den)
			}
			dd.QuoRound(&dd.Dec, denDec, decimal.Precision, inf.RoundHalfUp)
		} else {
			if _, ok := dd.SetString(s); !ok {
				return nil, fmt.Errorf("could not evaluate %v as Datum type DDecimal from "+
					"string %q", expr, s)
			}
		}
		return dd, nil
	default:
		return nil, fmt.Errorf("could not resolve %T %v into a %T", expr, expr, typ)
	}
}
Пример #24
0
func TestCondBreakpoint(t *testing.T) {
	withTestProcess("parallel_next", t, func(p *Process, fixture protest.Fixture) {
		addr, _, err := p.goSymTable.LineToPC(fixture.Source, 9)
		assertNoError(err, t, "LineToPC")
		bp, err := p.SetBreakpoint(addr)
		assertNoError(err, t, "SetBreakpoint()")
		bp.Cond = &ast.BinaryExpr{
			Op: token.EQL,
			X:  &ast.Ident{Name: "n"},
			Y:  &ast.BasicLit{Kind: token.INT, Value: "7"},
		}

		assertNoError(p.Continue(), t, "Continue()")

		nvar, err := evalVariable(p, "n")
		assertNoError(err, t, "EvalVariable()")

		n, _ := constant.Int64Val(nvar.Value)
		if n != 7 {
			t.Fatalf("Stoppend on wrong goroutine %d\n", n)
		}
	})
}
Пример #25
0
func (check *Checker) arrayLength(e ast.Expr) int64 {
	var x operand
	check.expr(&x, e)
	if x.mode != constant_ {
		if x.mode != invalid {
			check.errorf(x.pos(), "array length %s must be constant", &x)
		}
		return 0
	}
	if isUntyped(x.typ) || isInteger(x.typ) {
		if val := constant.ToInt(x.val); val.Kind() == constant.Int {
			if representableConst(val, check.conf, Typ[Int], nil) {
				if n, ok := constant.Int64Val(val); ok && n >= 0 {
					return n
				}
				check.errorf(x.pos(), "invalid array length %s", &x)
				return 0
			}
		}
	}
	check.errorf(x.pos(), "array length %s must be integer", &x)
	return 0
}
Пример #26
0
Файл: expr.go Проект: 2thetop/go
// index checks an index expression for validity.
// If max >= 0, it is the upper bound for index.
// If index is valid and the result i >= 0, then i is the constant value of index.
func (check *Checker) index(index ast.Expr, max int64) (i int64, valid bool) {
	var x operand
	check.expr(&x, index)
	if x.mode == invalid {
		return
	}

	// an untyped constant must be representable as Int
	check.convertUntyped(&x, Typ[Int])
	if x.mode == invalid {
		return
	}

	// the index must be of integer type
	if !isInteger(x.typ) {
		check.invalidArg(x.pos(), "index %s must be integer", &x)
		return
	}

	// a constant index i must be in bounds
	if x.mode == constant_ {
		if constant.Sign(x.val) < 0 {
			check.invalidArg(x.pos(), "index %s must not be negative", &x)
			return
		}
		i, valid = constant.Int64Val(constant.ToInt(x.val))
		if !valid || max >= 0 && i >= max {
			check.errorf(x.pos(), "index %s is out of bounds", &x)
			return i, false
		}
		// 0 <= i [ && i < max ]
		return i, true
	}

	return -1, true
}
Пример #27
0
// genDecl processes one declaration clause.
func (f *File) genDecl(node ast.Node) bool {
	decl, ok := node.(*ast.GenDecl)
	if !ok || decl.Tok != token.CONST {
		// We only care about const declarations.
		return true
	}
	// The name of the type of the constants we are declaring.
	// Can change if this is a multi-element declaration.
	typ := ""
	// Loop over the elements of the declaration. Each element is a ValueSpec:
	// a list of names possibly followed by a type, possibly followed by values.
	// If the type and value are both missing, we carry down the type (and value,
	// but the "go/types" package takes care of that).
	for _, spec := range decl.Specs {
		vspec := spec.(*ast.ValueSpec) // Guaranteed to succeed as this is CONST.
		if vspec.Type == nil && len(vspec.Values) > 0 {
			// "X = 1". With no type but a value, the constant is untyped.
			// Skip this vspec and reset the remembered type.
			typ = ""
			continue
		}
		if vspec.Type != nil {
			// "X T". We have a type. Remember it.
			ident, ok := vspec.Type.(*ast.Ident)
			if !ok {
				continue
			}
			typ = ident.Name
		}
		if typ != f.typeName {
			// This is not the type we're looking for.
			continue
		}
		// We now have a list of names (from one line of source code) all being
		// declared with the desired type.
		// Grab their names and actual values and store them in f.values.
		for _, name := range vspec.Names {
			if name.Name == "_" {
				continue
			}
			// This dance lets the type checker find the values for us. It's a
			// bit tricky: look up the object declared by the name, find its
			// types.Const, and extract its value.
			obj, ok := f.pkg.defs[name]
			if !ok {
				log.Fatalf("no value for constant %s", name)
			}
			info := obj.Type().Underlying().(*types.Basic).Info()
			if info&types.IsInteger == 0 {
				log.Fatalf("can't handle non-integer constant type %s", typ)
			}
			value := obj.(*types.Const).Val() // Guaranteed to succeed as this is CONST.
			if value.Kind() != exact.Int {
				log.Fatalf("can't happen: constant is not an integer %s", name)
			}
			i64, isInt := exact.Int64Val(value)
			u64, isUint := exact.Uint64Val(value)
			if !isInt && !isUint {
				log.Fatalf("internal error: value of %s is not an integer: %s", name, value.String())
			}
			if !isInt {
				u64 = uint64(i64)
			}
			v := Value{
				name:   name.Name,
				value:  u64,
				signed: info&types.IsUnsigned == 0,
				str:    value.String(),
			}
			f.values = append(f.values, v)
		}
	}
	return false
}
Пример #28
0
func TestVariableEvaluation(t *testing.T) {
	testcases := []struct {
		name        string
		st          reflect.Kind
		value       interface{}
		length, cap int64
		childrenlen int
	}{
		{"a1", reflect.String, "foofoofoofoofoofoo", 18, 0, 0},
		{"a11", reflect.Array, nil, 3, -1, 3},
		{"a12", reflect.Slice, nil, 2, 2, 2},
		{"a13", reflect.Slice, nil, 3, 3, 3},
		{"a2", reflect.Int, int64(6), 0, 0, 0},
		{"a3", reflect.Float64, float64(7.23), 0, 0, 0},
		{"a4", reflect.Array, nil, 2, -1, 2},
		{"a5", reflect.Slice, nil, 5, 5, 5},
		{"a6", reflect.Struct, nil, 2, 0, 2},
		{"a7", reflect.Ptr, nil, 1, 0, 1},
		{"a8", reflect.Struct, nil, 2, 0, 2},
		{"a9", reflect.Ptr, nil, 1, 0, 1},
		{"baz", reflect.String, "bazburzum", 9, 0, 0},
		{"neg", reflect.Int, int64(-1), 0, 0, 0},
		{"f32", reflect.Float32, float64(float32(1.2)), 0, 0, 0},
		{"c64", reflect.Complex64, complex128(complex64(1 + 2i)), 0, 0, 0},
		{"c128", reflect.Complex128, complex128(2 + 3i), 0, 0, 0},
		{"a6.Baz", reflect.Int, int64(8), 0, 0, 0},
		{"a7.Baz", reflect.Int, int64(5), 0, 0, 0},
		{"a8.Baz", reflect.String, "feh", 3, 0, 0},
		{"a8", reflect.Struct, nil, 2, 0, 2},
		{"i32", reflect.Array, nil, 2, -1, 2},
		{"b1", reflect.Bool, true, 0, 0, 0},
		{"b2", reflect.Bool, false, 0, 0, 0},
		{"f", reflect.Func, "main.barfoo", 0, 0, 0},
		{"ba", reflect.Slice, nil, 200, 200, 64},
	}

	withTestProcess("testvariables", t, func(p *Process, fixture protest.Fixture) {
		assertNoError(p.Continue(), t, "Continue() returned an error")

		for _, tc := range testcases {
			v, err := evalVariable(p, tc.name)
			assertNoError(err, t, fmt.Sprintf("EvalVariable(%s)", tc.name))

			if v.Kind != tc.st {
				t.Fatalf("%s simple type: expected: %s got: %s", tc.name, tc.st, v.Kind.String())
			}
			if v.Value == nil && tc.value != nil {
				t.Fatalf("%s value: expected: %v got: %v", tc.name, tc.value, v.Value)
			} else {
				switch v.Kind {
				case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
					x, _ := constant.Int64Val(v.Value)
					if y, ok := tc.value.(int64); !ok || x != y {
						t.Fatalf("%s value: expected: %v got: %v", tc.name, tc.value, v.Value)
					}
				case reflect.Float32, reflect.Float64:
					x, _ := constant.Float64Val(v.Value)
					if y, ok := tc.value.(float64); !ok || x != y {
						t.Fatalf("%s value: expected: %v got: %v", tc.name, tc.value, v.Value)
					}
				case reflect.Complex64, reflect.Complex128:
					xr, _ := constant.Float64Val(constant.Real(v.Value))
					xi, _ := constant.Float64Val(constant.Imag(v.Value))
					if y, ok := tc.value.(complex128); !ok || complex(xr, xi) != y {
						t.Fatalf("%s value: expected: %v got: %v", tc.name, tc.value, v.Value)
					}
				case reflect.String:
					if y, ok := tc.value.(string); !ok || constant.StringVal(v.Value) != y {
						t.Fatalf("%s value: expected: %v got: %v", tc.name, tc.value, v.Value)
					}
				}
			}
			if v.Len != tc.length {
				t.Fatalf("%s len: expected: %d got: %d", tc.name, tc.length, v.Len)
			}
			if v.Cap != tc.cap {
				t.Fatalf("%s cap: expected: %d got: %d", tc.name, tc.cap, v.Cap)
			}
			if len(v.Children) != tc.childrenlen {
				t.Fatalf("%s children len: expected %d got: %d", tc.name, tc.childrenlen, len(v.Children))
			}
		}
	})
}
Пример #29
0
func TestBreakpointCountsWithDetection(t *testing.T) {
	if !doTestBreakpointCountsWithDetection {
		return
	}
	m := map[int64]int64{}
	withTestProcess("bpcountstest", t, func(p *Process, fixture protest.Fixture) {
		addr, _, err := p.goSymTable.LineToPC(fixture.Source, 12)
		assertNoError(err, t, "LineToPC")
		bp, err := p.SetBreakpoint(addr)
		assertNoError(err, t, "SetBreakpoint()")

		for {
			if err := p.Continue(); err != nil {
				if _, exited := err.(ProcessExitedError); exited {
					break
				}
				assertNoError(err, t, "Continue()")
			}
			fmt.Printf("Continue returned %d\n", bp.TotalHitCount)
			for _, th := range p.Threads {
				if th.CurrentBreakpoint == nil {
					continue
				}
				scope, err := th.Scope()
				assertNoError(err, t, "Scope()")
				v, err := scope.EvalVariable("i")
				assertNoError(err, t, "evalVariable")
				i, _ := constant.Int64Val(v.Value)
				v, err = scope.EvalVariable("id")
				assertNoError(err, t, "evalVariable")
				id, _ := constant.Int64Val(v.Value)
				m[id] = i
				fmt.Printf("\tgoroutine (%d) %d: %d\n", th.ID, id, i)
			}

			total := int64(0)
			for i := range m {
				total += m[i] + 1
			}

			if uint64(total) != bp.TotalHitCount {
				t.Fatalf("Mismatched total count %d %d\n", total, bp.TotalHitCount)
			}
		}

		t.Logf("TotalHitCount: %d", bp.TotalHitCount)
		if bp.TotalHitCount != 200 {
			t.Fatalf("Wrong TotalHitCount for the breakpoint (%d)", bp.TotalHitCount)
		}

		if len(bp.HitCount) != 2 {
			t.Fatalf("Wrong number of goroutines for breakpoint (%d)", len(bp.HitCount))
		}

		for _, v := range bp.HitCount {
			if v != 100 {
				t.Fatalf("Wrong HitCount for breakpoint (%v)", bp.HitCount)
			}
		}
	})
}
Пример #30
0
func TestFrameEvaluation(t *testing.T) {
	withTestProcess("goroutinestackprog", t, func(p *Process, fixture protest.Fixture) {
		_, err := setFunctionBreakpoint(p, "main.stacktraceme")
		assertNoError(err, t, "setFunctionBreakpoint")
		assertNoError(p.Continue(), t, "Continue()")

		// Testing evaluation on goroutines
		gs, err := p.GoroutinesInfo()
		assertNoError(err, t, "GoroutinesInfo")
		found := make([]bool, 10)
		for _, g := range gs {
			frame := -1
			frames, err := p.GoroutineStacktrace(g, 10)
			assertNoError(err, t, "GoroutineStacktrace()")
			for i := range frames {
				if frames[i].Call.Fn != nil && frames[i].Call.Fn.Name == "main.agoroutine" {
					frame = i
					break
				}
			}

			if frame < 0 {
				t.Logf("Goroutine %d: could not find correct frame", g.ID)
				continue
			}

			scope, err := p.ConvertEvalScope(g.ID, frame)
			assertNoError(err, t, "ConvertEvalScope()")
			t.Logf("scope = %v", scope)
			v, err := scope.EvalVariable("i")
			t.Logf("v = %v", v)
			if err != nil {
				t.Logf("Goroutine %d: %v\n", g.ID, err)
				continue
			}
			vval, _ := constant.Int64Val(v.Value)
			found[vval] = true
		}

		for i := range found {
			if !found[i] {
				t.Fatalf("Goroutine %d not found\n", i)
			}
		}

		// Testing evaluation on frames
		assertNoError(p.Continue(), t, "Continue() 2")
		g, err := p.CurrentThread.GetG()
		assertNoError(err, t, "GetG()")

		for i := 0; i <= 3; i++ {
			scope, err := p.ConvertEvalScope(g.ID, i+1)
			assertNoError(err, t, fmt.Sprintf("ConvertEvalScope() on frame %d", i+1))
			v, err := scope.EvalVariable("n")
			assertNoError(err, t, fmt.Sprintf("EvalVariable() on frame %d", i+1))
			n, _ := constant.Int64Val(v.Value)
			t.Logf("frame %d n %d\n", i+1, n)
			if n != int64(3-i) {
				t.Fatalf("On frame %d value of n is %d (not %d)", i+1, n, 3-i)
			}
		}
	})
}