proc: handle moving of direct interface flag in Go 1.26 (#4032)

This flag in internal/abi.Type is moving from the Kind_ field to
the TFlag field. See https://go-review.googlesource.com/c/go/+/681936

A few of the other Kind fields dlv doesn't use (and don't exist
in Go anymore), so this code can be simplified somewhat.
This commit is contained in:
Keith Randall 2025-06-17 16:04:52 -07:00 committed by GitHub
parent a40a5e057b
commit 091ff50645
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 34 additions and 21 deletions

View File

@ -67,10 +67,8 @@ const internal/runtime/maps.ctrlEmpty = 128
const kindDirectIface|internal/abi.KindDirectIface = 32
const kindGCProg|internal/abi.KindGCProg = 64
const kindMask|internal/abi.KindMask = 31
const minTopHash = 4
or const minTopHash = 5
const tflagDirectIface|internal/abi.TFlagDirectIface = 32

View File

@ -1026,7 +1026,7 @@ type Image struct {
func (image *Image) registerRuntimeTypeToDIE(entry *dwarf.Entry, ardr *reader.Reader) {
if off, ok := entry.Val(godwarf.AttrGoRuntimeType).(uint64); ok {
if _, ok := image.runtimeTypeToDIE[off]; !ok {
image.runtimeTypeToDIE[off] = runtimeTypeDIE{entry.Offset, -1}
image.runtimeTypeToDIE[off] = runtimeTypeDIE{entry.Offset}
}
}
}

View File

@ -13,17 +13,16 @@ import (
// The kind field in runtime._type is a reflect.Kind value plus
// some extra flags defined here.
// See equivalent declaration in $GOROOT/src/reflect/type.go
// See equivalent declaration in $GOROOT/src/internal/abi/type.go
const (
// Go 1.25 and earlier
kindDirectIface = 1 << 5 // +rtype kindDirectIface|internal/abi.KindDirectIface
kindGCProg = 1 << 6 // +rtype kindGCProg|internal/abi.KindGCProg
kindNoPointers = 1 << 7
kindMask = (1 << 5) - 1 // +rtype kindMask|internal/abi.KindMask
// Go 1.26 and later
tflagDirectIface = 1 << 5 // +rtype go1.26 tflagDirectIface|internal/abi.TFlagDirectIface
)
type runtimeTypeDIE struct {
offset dwarf.Offset
kind int64
}
func pointerTo(typ godwarf.Type, arch *Arch) godwarf.Type {
@ -80,7 +79,7 @@ func (ctxt *loadDebugInfoMapsContext) lookupAbstractOrigin(bi *BinaryInfo, off d
// debug_info
// - After go1.11 the runtimeTypeToDIE map is used to look up the address of
// the type and map it directly to a DIE.
func RuntimeTypeToDIE(_type *Variable, dataAddr uint64, mds []ModuleData) (typ godwarf.Type, kind int64, err error) {
func RuntimeTypeToDIE(_type *Variable, dataAddr uint64, mds []ModuleData) (typ godwarf.Type, directIface bool, err error) {
bi := _type.bi
_type = _type.maybeDereference()
@ -94,21 +93,37 @@ func RuntimeTypeToDIE(_type *Variable, dataAddr uint64, mds []ModuleData) (typ g
if rtdie, ok := so.runtimeTypeToDIE[_type.Addr-md.types]; ok {
typ, err := godwarf.ReadType(so.dwarf, so.index, rtdie.offset, so.typeCache)
if err != nil {
return nil, 0, fmt.Errorf("invalid interface type: %v", err)
return nil, false, fmt.Errorf("invalid interface type: %v", err)
}
if rtdie.kind == -1 {
if kindField := _type.loadFieldNamed("kind"); kindField != nil && kindField.Value != nil {
rtdie.kind, _ = constant.Int64Val(kindField.Value)
} else if kindField := _type.loadFieldNamed("Kind_"); kindField != nil && kindField.Value != nil {
rtdie.kind, _ = constant.Int64Val(kindField.Value)
// Figure out whether interfaces with this concrete type are direct or not.
// Go 1.26 and beyond have this flag in the TFlag field.
// Go 1.25 and earlier have this flag in the Kind field.
// If either flag is set, consider it direct.
var direct bool
if tflagField := _type.loadFieldNamed("TFlag"); tflagField != nil && tflagField.Value != nil {
tflag, _ := constant.Int64Val(tflagField.Value)
if tflag&tflagDirectIface != 0 {
direct = true
}
}
return typ, rtdie.kind, nil
if kindField := _type.loadFieldNamed("kind"); kindField != nil && kindField.Value != nil {
kind, _ := constant.Int64Val(kindField.Value)
if kind&kindDirectIface != 0 {
direct = true
}
} else if kindField := _type.loadFieldNamed("Kind_"); kindField != nil && kindField.Value != nil {
kind, _ := constant.Int64Val(kindField.Value)
if kind&kindDirectIface != 0 {
direct = true
}
}
return typ, direct, nil
}
}
}
return nil, 0, errors.New("could not resolve interface type")
return nil, false, errors.New("could not resolve interface type")
}
// resolveParametricType returns the real type of t if t is a parametric

View File

@ -2135,14 +2135,14 @@ func (v *Variable) loadInterface(recurseLevel int, loadData bool, cfg LoadConfig
return
}
typ, kind, err := RuntimeTypeToDIE(_type, data.Addr, mds)
typ, directIface, err := RuntimeTypeToDIE(_type, data.Addr, mds)
if err != nil {
v.Unreadable = err
return
}
deref := false
if kind&kindDirectIface == 0 {
if !directIface {
realtyp := godwarf.ResolveTypedef(typ)
if _, isptr := realtyp.(*godwarf.PtrType); !isptr {
typ = pointerTo(typ, v.bi.Arch)