]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/link/internal/ld: fix DWARF type DIE "go kind" bug for synthetic ptr types
authorThan McIntosh <thanm@google.com>
Tue, 21 Nov 2023 19:44:41 +0000 (14:44 -0500)
committerThan McIntosh <thanm@google.com>
Wed, 22 Nov 2023 15:50:07 +0000 (15:50 +0000)
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 <cherryyz@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>

src/cmd/link/internal/dwtest/dwtest.go
src/cmd/link/internal/ld/dwarf.go
src/cmd/link/internal/ld/dwarf_test.go

index c68edf4187fe1d7e9366f1aa8ebaa70c90aae271..3fb02ee1db2fb893eb9920cb32663395bdcf5c1c 100644 (file)
@@ -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]
index dcbe719c96f1e30720460cf166a095e872e63cd5..17f2803ebfb23dbc7e0922ff2b602a8f2d40b56e 100644 (file)
@@ -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))
        }
 
index 6ca2a844f5cffc672e7e598026a00b013b4f8ff2..e431427249db071a850a136afc3307458448b981 100644 (file)
@@ -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)
+       }
+}