proc: early fixes for Go 1.26 (#4070)

Change 091ff506 fixed loading the direct flag for Go 1.26 when we go
from a runtime type to a dwarf type, we also did the same check from
the dwarf type to a runtime type when converting variables into
'interface {}'.
This commit deletes unifies the two code paths deleting the one that
wasn't updated.

Fixes the tests on tip.
This commit is contained in:
Alessandro Arzilli
2025-08-20 19:40:36 +02:00
committed by GitHub
parent e4623bcb56
commit c6bc2dc38b
3 changed files with 39 additions and 46 deletions

View File

@ -1227,7 +1227,7 @@ func TestRangeOverFuncNextInlined(t *testing.T) {
if !goversion.VersionAfterOrEqual(runtime.Version(), 1, 23) {
t.Skip("N/A")
}
if goversion.VersionAfterOrEqual(runtime.Version(), 1, 24) && !goversion.VersionAfterOrEqual(runtime.Version(), 1, 26) {
if goversion.VersionAfterOrEqual(runtime.Version(), 1, 24) && !goversion.VersionAfterOrEqual(runtime.Version(), 1, 27) {
t.Skip("broken due to inlined symbol names")
}

View File

@ -95,30 +95,7 @@ func RuntimeTypeToDIE(_type *Variable, dataAddr uint64, mds []ModuleData) (typ g
if err != nil {
return nil, false, fmt.Errorf("invalid interface type: %v", err)
}
// 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
}
}
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 typ, getRuntimeTypeDirect(_type), nil
}
}
}
@ -159,30 +136,30 @@ func resolveParametricType(bi *BinaryInfo, mem MemoryReadWriter, t godwarf.Type,
return typ, nil
}
func dwarfToRuntimeType(bi *BinaryInfo, mem MemoryReadWriter, typ godwarf.Type) (typeAddr uint64, typeKind uint64, found bool, err error) {
func dwarfToRuntimeType(bi *BinaryInfo, mem MemoryReadWriter, typ godwarf.Type) (typeAddr uint64, direct, found bool, err error) {
so := bi.typeToImage(typ)
rdr := so.DwarfReader()
rdr.Seek(typ.Common().Offset)
e, err := rdr.Next()
if err != nil {
return 0, 0, false, err
return 0, false, false, err
}
off, ok := e.Val(godwarf.AttrGoRuntimeType).(uint64)
if !ok {
return 0, 0, false, nil
return 0, false, false, nil
}
mds, err := LoadModuleData(bi, mem)
if err != nil {
return 0, 0, false, err
return 0, false, false, err
}
md := bi.imageToModuleData(so, mds)
if md == nil {
if so.index > 0 {
return 0, 0, false, fmt.Errorf("could not find module data for type %s (shared object: %q)", typ, so.Path)
return 0, false, false, fmt.Errorf("could not find module data for type %s (shared object: %q)", typ, so.Path)
} else {
return 0, 0, false, fmt.Errorf("could not find module data for type %s", typ)
return 0, false, false, fmt.Errorf("could not find module data for type %s", typ)
}
}
@ -190,19 +167,35 @@ func dwarfToRuntimeType(bi *BinaryInfo, mem MemoryReadWriter, typ godwarf.Type)
rtyp, err := bi.findType(bi.runtimeTypeTypename())
if err != nil {
return 0, 0, false, err
return 0, false, false, err
}
_type := newVariable("", typeAddr, rtyp, bi, mem)
kindv := _type.loadFieldNamed("kind")
if kindv == nil || kindv.Unreadable != nil || kindv.Kind != reflect.Uint {
kindv = _type.loadFieldNamed("Kind_")
}
if kindv == nil {
return 0, 0, false, fmt.Errorf("unreadable interface type (no kind field)")
}
if kindv.Unreadable != nil || kindv.Kind != reflect.Uint {
return 0, 0, false, fmt.Errorf("unreadable interface type: %v", kindv.Unreadable)
}
typeKind, _ = constant.Uint64Val(kindv.Value)
return typeAddr, typeKind, true, nil
return typeAddr, getRuntimeTypeDirect(_type), true, nil
}
// getRuntimeTypeDirect returns a bool that says if the type in _type can be stored directly into an interface variable.
func getRuntimeTypeDirect(_type *Variable) bool {
// 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
}
}
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 direct
}

View File

@ -1514,11 +1514,11 @@ func convertToEface(srcv, dstv *Variable) error {
dstv.writeEmptyInterface(_type.Addr, data)
return nil
}
typeAddr, typeKind, runtimeTypeFound, err := dwarfToRuntimeType(srcv.bi, srcv.mem, srcv.RealType)
typeAddr, direct, runtimeTypeFound, err := dwarfToRuntimeType(srcv.bi, srcv.mem, srcv.RealType)
if err != nil {
return fmt.Errorf("can not convert value of type %s to %s: %v", srcv.DwarfType.String(), dstv.DwarfType.String(), err)
}
if !runtimeTypeFound || typeKind&kindDirectIface == 0 {
if !runtimeTypeFound || !direct {
return &typeConvErr{srcv.DwarfType, dstv.RealType}
}
return dstv.writeEmptyInterface(typeAddr, srcv)