@@ -111,6 +111,7 @@ func (p *Process) DynamicType(t *Type, a core.Address) *Type {
111111}
112112
113113// Convert the address of a runtime._type to a *Type.
114+ // The "d" is the address of the second field of an interface.
114115// Guaranteed to return a non-nil *Type.
115116func (p * Process ) runtimeType2Type (a core.Address , d core.Address ) * Type {
116117if t := p .runtimeMap [a ]; t != nil {
@@ -176,16 +177,27 @@ func (p *Process) runtimeType2Type(a core.Address, d core.Address) *Type {
176177// in the same package name, but in the different package paths. eg. path-1/pkg.Foo and path-2/pkg.Foo.
177178// Match the object size may be a proper choice, just for try best, since we have no other choices.
178179if len (candidates ) > 1 && nptrs == 1 && candidates [0 ].Size == ptrSize {
179- o := p .proc .ReadPtr (d )
180- sz := p .Size (Object (o ))
181- var tmp []* Type
182- for _ , t := range candidates {
183- if t .Elem != nil && t .Elem .Size == sz {
184- tmp = append (tmp , t )
185- }
180+ ptr := p .proc .ReadPtr (d )
181+ if ifaceIndir (a , p ) {
182+ // Indirect interface: the interface introduced a new
183+ // level of indirection, not reflected in the type.
184+ // Read through it.
185+ ptr = p .proc .ReadPtr (ptr )
186186}
187- if len (tmp ) > 0 {
188- candidates = tmp
187+ obj , off := p .FindObject (ptr )
188+ // only usefull while it point to the head of an object,
189+ // otherwise, the GC object size should bigger than t.Elem.Size.
190+ if obj != 0 && off == 0 {
191+ sz := p .Size (obj )
192+ var tmp []* Type
193+ for _ , t := range candidates {
194+ if t .Elem != nil && t .Elem .Size == sz {
195+ tmp = append (tmp , t )
196+ }
197+ }
198+ if len (tmp ) > 0 {
199+ candidates = tmp
200+ }
189201}
190202}
191203var t * Type
@@ -541,6 +553,15 @@ func (fr *frameReader) ReadInt(a core.Address) int64 {
541553return fr .p .proc .ReadInt (a )
542554}
543555
556+ // ifaceIndir reports whether t is stored indirectly in an interface value.
557+ func ifaceIndir (t core.Address , p * Process ) bool {
558+ typr := region {p : p , a : t , typ : p .findType ("runtime._type" )}
559+ if typr .Field ("kind" ).Uint8 ()& uint8 (p .rtConstants ["kindDirectIface" ]) == 0 {
560+ return true
561+ }
562+ return false
563+ }
564+
544565// typeObject takes an address and a type for the data at that address.
545566// For each pointer it finds in the memory at that address, it calls add with the pointer
546567// and the type + repeat count of the thing that it points to.
@@ -564,8 +585,7 @@ func (p *Process) typeObject(a core.Address, t *Type, r reader, add func(core.Ad
564585// TODO: for KindEface, type typPtr. It might point to the heap
565586// if the type was allocated with reflect.
566587typ := p .runtimeType2Type (typPtr , data )
567- typr := region {p : p , a : typPtr , typ : p .findType ("runtime._type" )}
568- if typr .Field ("kind" ).Uint8 ()& uint8 (p .rtConstants ["kindDirectIface" ]) == 0 {
588+ if ifaceIndir (typPtr , p ) {
569589// Indirect interface: the interface introduced a new
570590// level of indirection, not reflected in the type.
571591// Read through it.
0 commit comments