From: Than McIntosh Date: Tue, 21 Nov 2023 19:44:41 +0000 (-0500) Subject: cmd/link/internal/ld: fix DWARF type DIE "go kind" bug for synthetic ptr types X-Git-Tag: go1.22rc1~166 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=37971b31dfde1b9c40f6d42484e528c17450a9ae;p=gostls13.git cmd/link/internal/ld: fix DWARF type DIE "go kind" bug for synthetic ptr types The code path in linker DWARF type generation that synthesizes pointer type DIEs needed for other synthesized types wasn't properly setting the DW_AT_go_kind attribute for the new pointer types. Fixes #64231. Change-Id: I70c338d2b33ae3b93a4c6f201e5836d91d368086 Reviewed-on: https://go-review.googlesource.com/c/go/+/544315 Reviewed-by: Cherry Mui LUCI-TryBot-Result: Go LUCI --- diff --git a/src/cmd/link/internal/dwtest/dwtest.go b/src/cmd/link/internal/dwtest/dwtest.go index c68edf4187..3fb02ee1db 100644 --- a/src/cmd/link/internal/dwtest/dwtest.go +++ b/src/cmd/link/internal/dwtest/dwtest.go @@ -90,7 +90,7 @@ func (ex *Examiner) DumpEntry(idx int, dumpKids bool, ilevel int) { fmt.Printf("0x%x: %v\n", idx, entry.Tag) for _, f := range entry.Field { indent(ilevel) - fmt.Printf("at=%v val=0x%x\n", f.Attr, f.Val) + fmt.Printf("at=%v val=%v\n", f.Attr, f.Val) } if dumpKids { ksl := ex.kids[idx] diff --git a/src/cmd/link/internal/ld/dwarf.go b/src/cmd/link/internal/ld/dwarf.go index dcbe719c96..17f2803ebf 100644 --- a/src/cmd/link/internal/ld/dwarf.go +++ b/src/cmd/link/internal/ld/dwarf.go @@ -748,6 +748,7 @@ func (d *dwctxt) defptrto(dwtype loader.Sym) loader.Sym { // pointers of slices. Link to the ones we can find. gts := d.ldr.Lookup("type:"+ptrname, 0) if gts != 0 && d.ldr.AttrReachable(gts) { + newattr(pdie, dwarf.DW_AT_go_kind, dwarf.DW_CLS_CONSTANT, int64(objabi.KindPtr), 0) newattr(pdie, dwarf.DW_AT_go_runtime_type, dwarf.DW_CLS_GO_TYPEREF, 0, dwSym(gts)) } diff --git a/src/cmd/link/internal/ld/dwarf_test.go b/src/cmd/link/internal/ld/dwarf_test.go index 6ca2a844f5..e431427249 100644 --- a/src/cmd/link/internal/ld/dwarf_test.go +++ b/src/cmd/link/internal/ld/dwarf_test.go @@ -1985,17 +1985,7 @@ func main() { } } -func TestZeroSizedVariable(t *testing.T) { - testenv.MustHaveGoBuild(t) - - mustHaveDWARF(t) - t.Parallel() - - // This test verifies that the compiler emits DIEs for zero sized variables - // (for example variables of type 'struct {}'). - // See go.dev/issues/54615. - - const prog = ` +const zeroSizedVarProg = ` package main import ( @@ -2008,10 +1998,24 @@ func main() { } ` +func TestZeroSizedVariable(t *testing.T) { + testenv.MustHaveGoBuild(t) + + mustHaveDWARF(t) + t.Parallel() + + if testing.Short() { + t.Skip("skipping test in short mode.") + } + + // This test verifies that the compiler emits DIEs for zero sized variables + // (for example variables of type 'struct {}'). + // See go.dev/issues/54615. + for _, opt := range []string{NoOpt, DefaultOpt} { opt := opt t.Run(opt, func(t *testing.T) { - _, ex := gobuildAndExamine(t, prog, opt) + _, ex := gobuildAndExamine(t, zeroSizedVarProg, opt) // Locate the main.zeroSizedVariable DIE abcs := ex.Named("zeroSizedVariable") @@ -2024,3 +2028,46 @@ func main() { }) } } + +func TestConsistentGoKindAndRuntimeType(t *testing.T) { + testenv.MustHaveGoBuild(t) + + mustHaveDWARF(t) + t.Parallel() + + if testing.Short() { + t.Skip("skipping test in short mode.") + } + + // Ensure that if we emit a "go runtime type" attr on a type DIE, + // we also include the "go kind" attribute. See issue #64231. + _, ex := gobuildAndExamine(t, zeroSizedVarProg, DefaultOpt) + + // Walk all dies. + typesChecked := 0 + failures := 0 + for _, die := range ex.DIEs() { + // For any type DIE with DW_AT_go_runtime_type set... + rtt, hasRT := die.Val(intdwarf.DW_AT_go_runtime_type).(uint64) + if !hasRT || rtt == 0 { + continue + } + typesChecked++ + // ... we want to see a meaningful DW_AT_go_kind value. + if val, ok := die.Val(intdwarf.DW_AT_go_kind).(int64); !ok || val == 0 { + failures++ + // dump DIEs for first 10 failures. + if failures <= 10 { + idx := ex.IdxFromOffset(die.Offset) + t.Logf("type DIE has DW_AT_go_runtime_type but invalid DW_AT_go_kind:\n") + ex.DumpEntry(idx, false, 0) + } + t.Errorf("bad type DIE at offset %d\n", die.Offset) + } + } + if typesChecked == 0 { + t.Fatalf("something went wrong, 0 types checked") + } else { + t.Logf("%d types checked\n", typesChecked) + } +}