proc/variables: Support chan types

Pretty print will print them with the format:
chan <element type> <queued elements>/<queue size>
This commit is contained in:
aarzilli
2015-11-03 19:11:08 +01:00
committed by Derek Parker
parent c25b9b369a
commit 988d529e91
5 changed files with 31 additions and 3 deletions

View File

@ -43,11 +43,13 @@ func main() {
var fn2 functype = nil var fn2 functype = nil
var nilslice []int = nil var nilslice []int = nil
var nilptr *int = nil var nilptr *int = nil
ch1 := make(chan int, 2)
var chnil chan int = nil
var amb1 = 1 var amb1 = 1
runtime.Breakpoint() runtime.Breakpoint()
for amb1 := 0; amb1 < 10; amb1++ { for amb1 := 0; amb1 < 10; amb1++ {
fmt.Println(amb1) fmt.Println(amb1)
} }
fmt.Println(i1, i2, i3, p1, amb1, s1, a1, p2, p3, s2, as1, str1, f1, fn1, fn2, nilslice, nilptr) fmt.Println(i1, i2, i3, p1, amb1, s1, a1, p2, p3, s2, as1, str1, f1, fn1, fn2, nilslice, nilptr, ch1, chnil)
} }

View File

@ -596,7 +596,7 @@ func compareOp(op token.Token, xv *Variable, yv *Variable) (bool, error) {
return false, fmt.Errorf("sturcture too deep for comparison") return false, fmt.Errorf("sturcture too deep for comparison")
} }
eql, err = equalChildren(xv, yv, false) eql, err = equalChildren(xv, yv, false)
case reflect.Slice, reflect.Map, reflect.Func: case reflect.Slice, reflect.Map, reflect.Func, reflect.Chan:
if xv != nilVariable && yv != nilVariable { if xv != nilVariable && yv != nilVariable {
return false, fmt.Errorf("can not compare %s variables", xv.Kind.String()) return false, fmt.Errorf("can not compare %s variables", xv.Kind.String())
} }

View File

@ -42,6 +42,7 @@ type Variable struct {
// base address of arrays, base address of the backing array for slices (0 for nil slices) // base address of arrays, base address of the backing array for slices (0 for nil slices)
// base address of the backing byte array for strings // base address of the backing byte array for strings
// address of the struct backing a chan variable
// address of the function entry point for function variables (0 for nil function pointers) // address of the function entry point for function variables (0 for nil function pointers)
base uintptr base uintptr
stride int64 stride int64
@ -122,7 +123,12 @@ func newVariable(name string, addr uintptr, dwarfType dwarf.Type, thread *Thread
switch t := v.RealType.(type) { switch t := v.RealType.(type) {
case *dwarf.PtrType: case *dwarf.PtrType:
structtyp, isstruct := t.Type.(*dwarf.StructType)
if isstruct && strings.HasPrefix(structtyp.StructName, "hchan<") {
v.Kind = reflect.Chan
} else {
v.Kind = reflect.Ptr v.Kind = reflect.Ptr
}
case *dwarf.StructType: case *dwarf.StructType:
switch { switch {
case t.StructName == "string": case t.StructName == "string":
@ -703,6 +709,13 @@ func (v *Variable) loadValueInternal(recurseLevel int) {
// Don't increase the recursion level when dereferencing pointers // Don't increase the recursion level when dereferencing pointers
v.Children[0].loadValueInternal(recurseLevel) 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.String: case reflect.String:
var val string var val string
val, v.Unreadable = v.thread.readStringValue(v.base, v.Len) val, v.Unreadable = v.thread.readStringValue(v.base, v.Len)

View File

@ -55,6 +55,12 @@ func (v *Variable) writeTo(buf *bytes.Buffer, top, newlines, includeType bool, i
} }
case reflect.String: case reflect.String:
v.writeStringTo(buf) v.writeStringTo(buf)
case reflect.Chan:
if newlines {
v.writeStructTo(buf, newlines, includeType, indent)
} else {
fmt.Fprintf(buf, "%s %s/%s", v.Type, v.Children[0].Value, v.Children[1].Value)
}
case reflect.Struct: case reflect.Struct:
v.writeStructTo(buf, newlines, includeType, indent) v.writeStructTo(buf, newlines, includeType, indent)
case reflect.Map: case reflect.Map:

View File

@ -385,6 +385,10 @@ func TestEvalExpression(t *testing.T) {
{"p3", true, "*int nil", "", "*int", nil}, {"p3", true, "*int nil", "", "*int", nil},
{"*p3", false, "", "", "int", fmt.Errorf("nil pointer dereference")}, {"*p3", false, "", "", "int", fmt.Errorf("nil pointer dereference")},
// channels
{"ch1", true, "chan int 0/2", "", "chan int", nil},
{"ch1+1", false, "", "", "", fmt.Errorf("can not convert 1 constant to chan int")},
// combined expressions // combined expressions
{"c1.pb.a.A", true, "1", "", "int", nil}, {"c1.pb.a.A", true, "1", "", "int", nil},
{"c1.sa[1].B", false, "3", "", "int", nil}, {"c1.sa[1].B", false, "3", "", "int", nil},
@ -455,6 +459,9 @@ func TestEvalExpression(t *testing.T) {
{"nilptr != nil", false, "false", "", "", nil}, {"nilptr != nil", false, "false", "", "", nil},
{"p1 == nil", false, "false", "", "", nil}, {"p1 == nil", false, "false", "", "", nil},
{"p1 != nil", false, "true", "", "", nil}, {"p1 != nil", false, "true", "", "", nil},
{"ch1 == nil", false, "false", "", "", nil},
{"chnil == nil", false, "true", "", "", nil},
{"ch1 == chnil", false, "", "", "", fmt.Errorf("can not compare chan variables")},
// errors // errors
{"&3", false, "", "", "", fmt.Errorf("can not take address of \"3\"")}, {"&3", false, "", "", "", fmt.Errorf("can not take address of \"3\"")},