From d65e832524ee9f4ba6baf5b05e8a13445b3cc313 Mon Sep 17 00:00:00 2001 From: aarzilli Date: Wed, 21 Oct 2015 09:06:36 +0200 Subject: [PATCH] proc/variable: changed Value's type to constant.Value --- proc/proc.go | 3 ++- proc/proc_test.go | 27 +++++++++++++++++---------- proc/variables.go | 29 ++++++++++++++++++++--------- service/api/conversions.go | 22 ++++++++++++++-------- 4 files changed, 53 insertions(+), 28 deletions(-) diff --git a/proc/proc.go b/proc/proc.go index 09565517..d864f92a 100644 --- a/proc/proc.go +++ b/proc/proc.go @@ -5,6 +5,7 @@ import ( "debug/gosym" "encoding/binary" "fmt" + "go/constant" "os" "path/filepath" "runtime" @@ -707,7 +708,7 @@ func (dbp *Process) getGoInformation() (ver GoVersion, isextld bool, err error) return } - ver, ok := parseVersionString(vv.Value.(string)) + ver, ok := parseVersionString(constant.StringVal(vv.Value)) if !ok { err = fmt.Errorf("Could not parse version number: %v\n", vv.Value) return diff --git a/proc/proc_test.go b/proc/proc_test.go index 0657424e..e7ae5ef4 100644 --- a/proc/proc_test.go +++ b/proc/proc_test.go @@ -3,6 +3,7 @@ package proc import ( "bytes" "fmt" + "go/constant" "net" "net/http" "os" @@ -317,6 +318,7 @@ func TestNextConcurrent(t *testing.T) { 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() @@ -334,7 +336,8 @@ func TestNextConcurrent(t *testing.T) { } v, err := evalVariable(p, "n") assertNoError(err, t, "EvalVariable") - if v.Value.(int64) != initV.Value.(int64) { + vval, _ := constant.Int64Val(v.Value) + if vval != initVval { t.Fatal("Did not end up on same goroutine") } } @@ -877,17 +880,19 @@ func TestVariableEvaluation(t *testing.T) { if v.Value == nil && tc.value != nil { t.Fatalf("%s value: expected: %v got: %v", tc.name, tc.value, v.Value) } else { - switch x := v.Value.(type) { - case int64: + 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 float64: + 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 string: - if y, ok := tc.value.(string); !ok || x != y { + 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) } } @@ -940,7 +945,8 @@ func TestFrameEvaluation(t *testing.T) { t.Logf("Goroutine %d: %v\n", g.Id, err) continue } - found[v.Value.(int64)] = true + vval, _ := constant.Int64Val(v.Value) + found[vval] = true } for i := range found { @@ -959,7 +965,7 @@ func TestFrameEvaluation(t *testing.T) { 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 := v.Value.(int64) + 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) @@ -975,8 +981,9 @@ func TestPointerSetting(t *testing.T) { pval := func(n int64) { variable, err := evalVariable(p, "p1") assertNoError(err, t, "EvalVariable()") - if variable.Children[0].Value.(int64) != n { - t.Fatalf("Wrong value of p1, *%d expected *%d", variable.Children[0].Value.(int64), n) + c0val, _ := constant.Int64Val(variable.Children[0].Value) + if c0val != n { + t.Fatalf("Wrong value of p1, *%d expected *%d", c0val, n) } } diff --git a/proc/variables.go b/proc/variables.go index 22d0da2f..e17bf349 100644 --- a/proc/variables.go +++ b/proc/variables.go @@ -6,6 +6,7 @@ import ( "encoding/binary" "fmt" "go/ast" + "go/constant" "go/parser" "go/token" "reflect" @@ -35,7 +36,7 @@ type Variable struct { Kind reflect.Kind thread *Thread - Value interface{} + Value constant.Value Len int64 Cap int64 @@ -681,7 +682,9 @@ func (v *Variable) loadValueInternal(recurseLevel int) { v.Children[0].loadValueInternal(recurseLevel) case reflect.String: - v.Value, v.Len, v.Unreadable = v.thread.readString(uintptr(v.Addr)) + var val string + val, v.Len, v.Unreadable = v.thread.readString(uintptr(v.Addr)) + v.Value = constant.MakeString(val) case reflect.Slice, reflect.Array: v.loadArrayValues(recurseLevel) @@ -704,17 +707,24 @@ func (v *Variable) loadValueInternal(recurseLevel int) { case reflect.Complex64, reflect.Complex128: v.readComplex(v.RealType.(*dwarf.ComplexType).ByteSize) case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: - v.Value, v.Unreadable = v.thread.readIntRaw(v.Addr, v.RealType.(*dwarf.IntType).ByteSize) + 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: - v.Value, v.Unreadable = v.thread.readUintRaw(v.Addr, v.RealType.(*dwarf.UintType).ByteSize) + 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 = val[0] != 0 + v.Value = constant.MakeBool(val[0] != 0) } case reflect.Float32, reflect.Float64: - v.Value, v.Unreadable = v.readFloatRaw(v.RealType.(*dwarf.FloatType).ByteSize) + var val float64 + val, v.Unreadable = v.readFloatRaw(v.RealType.(*dwarf.FloatType).ByteSize) + v.Value = constant.MakeFloat64(val) case reflect.Func: v.readFunctionPtr() case reflect.Map: @@ -804,14 +814,14 @@ func (v *Variable) loadSliceInfo(t *dwarf.StructType) { lstrAddr.loadValue() err = lstrAddr.Unreadable if err == nil { - v.Len = lstrAddr.Value.(int64) + v.Len, _ = constant.Int64Val(lstrAddr.Value) } case "cap": cstrAddr, _ := v.toField(f) cstrAddr.loadValue() err = cstrAddr.Unreadable if err == nil { - v.Cap = cstrAddr.Value.(int64) + v.Cap, _ = constant.Int64Val(cstrAddr.Value) } } if err != nil { @@ -875,6 +885,7 @@ func (v *Variable) readComplex(size int64) { imagvar.loadValue() v.Len = 2 v.Children = []Variable{*realvar, *imagvar} + v.Value = constant.BinaryOp(realvar.Value, token.ADD, imagvar.Value) } func (v *Variable) writeComplex(value string, size int64) error { @@ -1114,7 +1125,7 @@ func (v *Variable) readFunctionPtr() { return } - v.Value = fn.Name + v.Value = constant.MakeString(fn.Name) } // Fetches all variables of a specific type in the current function scope diff --git a/service/api/conversions.go b/service/api/conversions.go index 60e302c2..c079b0ce 100644 --- a/service/api/conversions.go +++ b/service/api/conversions.go @@ -1,9 +1,9 @@ package api import ( - "debug/dwarf" "debug/gosym" - "fmt" + "go/constant" + "reflect" "strconv" "github.com/derekparker/delve/proc" @@ -80,12 +80,18 @@ func ConvertVar(v *proc.Variable) *Variable { r.Unreadable = v.Unreadable.Error() } - switch typ := v.RealType.(type) { - case *dwarf.FloatType: - r.Value = strconv.FormatFloat(v.Value.(float64), 'f', -1, int(typ.Size()*8)) - default: - if v.Value != nil { - r.Value = fmt.Sprintf("%v", v.Value) + if v.Value != nil { + switch v.Kind { + case reflect.Float32: + f, _ := constant.Float64Val(v.Value) + r.Value = strconv.FormatFloat(f, 'f', -1, 32) + case reflect.Float64: + f, _ := constant.Float64Val(v.Value) + r.Value = strconv.FormatFloat(f, 'f', -1, 64) + case reflect.String, reflect.Func: + r.Value = constant.StringVal(v.Value) + default: + r.Value = v.Value.String() } }