提交 844762a8 编写于 作者: A aarzilli 提交者: Derek Parker

proc: support access to chan buffers

Replace the unsafe.Pointer type of the buf field of channels with the
appropriate array type, allow expressions accessing member field of the
channel struct.

Fixes #962
上级 1ced7c3a
......@@ -108,7 +108,11 @@ func main() {
var fn2 functype = nil
var nilslice []int = nil
var nilptr *int = nil
ch1 := make(chan int, 2)
ch1 := make(chan int, 10)
ch1 <- 1
ch1 <- 4
ch1 <- 3
ch1 <- 2
var chnil chan int = nil
m1 := map[string]astruct{
"Malone": astruct{2, 3},
......
......@@ -647,12 +647,27 @@ func (scope *EvalScope) evalIndex(node *ast.IndexExpr) (*Variable, error) {
return nil, xev.Unreadable
}
xev = xev.maybeDereference()
idxev, err := scope.evalAST(node.Index)
if err != nil {
return nil, err
}
cantindex := fmt.Errorf("expression \"%s\" (%s) does not support indexing", exprToString(node.X), xev.TypeString())
switch xev.Kind {
case reflect.Ptr:
if xev == nilVariable {
return nil, cantindex
}
_, isarrptr := xev.RealType.(*godwarf.PtrType).Type.(*godwarf.ArrayType)
if !isarrptr {
return nil, cantindex
}
xev = xev.maybeDereference()
fallthrough
case reflect.Slice, reflect.Array, reflect.String:
if xev.Base == 0 {
return nil, fmt.Errorf("can not index \"%s\"", exprToString(node.X))
......@@ -670,8 +685,7 @@ func (scope *EvalScope) evalIndex(node *ast.IndexExpr) (*Variable, error) {
}
return xev.mapAccess(idxev)
default:
return nil, fmt.Errorf("expression \"%s\" (%s) does not support indexing", exprToString(node.X), xev.TypeString())
return nil, cantindex
}
}
......
......@@ -198,6 +198,9 @@ func newVariable(name string, addr uintptr, dwarfType godwarf.Type, bi *BinaryIn
}
case *godwarf.ChanType:
v.Kind = reflect.Chan
if v.Addr != 0 {
v.loadChanInfo()
}
case *godwarf.MapType:
v.Kind = reflect.Map
case *godwarf.StringType:
......@@ -663,6 +666,11 @@ func (v *Variable) structMember(memberName string) (*Variable, error) {
if v.Unreadable != nil {
return v.clone(), nil
}
switch v.Kind {
case reflect.Chan:
v = v.clone()
v.RealType = resolveTypedef(&(v.RealType.(*godwarf.ChanType).TypedefType))
}
structVar := v.maybeDereference()
structVar.Name = v.Name
if structVar.Unreadable != nil {
......@@ -1010,6 +1018,66 @@ func (v *Variable) loadSliceInfo(t *godwarf.SliceType) {
}
}
// loadChanInfo loads the buffer size of the channel and changes the type of
// the buf field from unsafe.Pointer to an array of the correct type.
func (v *Variable) loadChanInfo() {
chanType, ok := v.RealType.(*godwarf.ChanType)
if !ok {
v.Unreadable = errors.New("bad channel type")
return
}
sv := v.clone()
sv.RealType = resolveTypedef(&(chanType.TypedefType))
sv = sv.maybeDereference()
if sv.Unreadable != nil || sv.Addr == 0 {
return
}
structType, ok := sv.DwarfType.(*godwarf.StructType)
if !ok {
v.Unreadable = errors.New("bad channel type")
return
}
lenAddr, _ := sv.toField(structType.Field[1])
lenAddr.loadValue(loadSingleValue)
if lenAddr.Unreadable != nil {
v.Unreadable = fmt.Errorf("unreadable length: %v", lenAddr.Unreadable)
return
}
chanLen, _ := constant.Uint64Val(lenAddr.Value)
newStructType := &godwarf.StructType{}
*newStructType = *structType
newStructType.Field = make([]*godwarf.StructField, len(structType.Field))
for i := range structType.Field {
field := &godwarf.StructField{}
*field = *structType.Field[i]
if field.Name == "buf" {
stride := chanType.ElemType.Common().ByteSize
atyp := &godwarf.ArrayType{
CommonType: godwarf.CommonType{
ReflectKind: reflect.Array,
ByteSize: int64(chanLen) * stride,
Name: fmt.Sprintf("[%d]%s", chanLen, chanType.ElemType.String())},
Type: chanType.ElemType,
StrideBitSize: stride * 8,
Count: int64(chanLen)}
field.Type = pointerTo(atyp, v.bi.Arch)
}
newStructType.Field[i] = field
}
v.RealType = &godwarf.ChanType{
TypedefType: godwarf.TypedefType{
CommonType: chanType.TypedefType.CommonType,
Type: pointerTo(newStructType, v.bi.Arch),
},
ElemType: chanType.ElemType,
}
}
func (v *Variable) loadArrayValues(recurseLevel int, cfg LoadConfig) {
if v.Unreadable != nil {
return
......
......@@ -534,7 +534,7 @@ func TestEvalExpression(t *testing.T) {
{"*p3", false, "", "", "int", fmt.Errorf("nil pointer dereference")},
// channels
{"ch1", true, "chan int 0/2", "chan int 0/2", "chan int", nil},
{"ch1", true, "chan int 4/10", "chan int 4/10", "chan int", nil},
{"chnil", true, "chan int nil", "chan int nil", "chan int", nil},
{"ch1+1", false, "", "", "", fmt.Errorf("can not convert 1 constant to chan int")},
......@@ -626,8 +626,8 @@ func TestEvalExpression(t *testing.T) {
{"len(s3)", false, "0", "0", "", nil},
{"cap(nilslice)", false, "0", "0", "", nil},
{"len(nilslice)", false, "0", "0", "", nil},
{"cap(ch1)", false, "2", "2", "", nil},
{"len(ch1)", false, "0", "0", "", nil},
{"cap(ch1)", false, "10", "10", "", nil},
{"len(ch1)", false, "4", "4", "", nil},
{"cap(chnil)", false, "0", "0", "", nil},
{"len(chnil)", false, "0", "0", "", nil},
{"len(m1)", false, "41", "41", "", nil},
......@@ -727,6 +727,12 @@ func TestEvalExpression(t *testing.T) {
{"string(runeslice)", false, `"tèst"`, `""`, "string", nil},
{"[]byte(string(runeslice))", false, `[]uint8 len: 5, cap: 5, [116,195,168,115,116]`, `[]uint8 len: 0, cap: 0, nil`, "[]uint8", nil},
{"*(*[5]byte)(uintptr(&byteslice[0]))", false, `[5]uint8 [116,195,168,115,116]`, `[5]uint8 [...]`, "[5]uint8", nil},
// access to channel field members
{"ch1.qcount", false, "4", "4", "uint", nil},
{"ch1.dataqsiz", false, "10", "10", "uint", nil},
{"ch1.buf", false, `*[10]int [1,4,3,2,0,0,0,0,0,0]`, `(*[10]int)(…`, "*[10]int", nil},
{"ch1.buf[0]", false, "1", "1", "int", nil},
}
ver, _ := goversion.Parse(runtime.Version())
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册