]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/link: generate DWARF for moduledata
authorIan Lance Taylor <iant@golang.org>
Sat, 6 Dec 2025 23:06:11 +0000 (15:06 -0800)
committerGopher Robot <gobot@golang.org>
Mon, 8 Dec 2025 17:11:14 +0000 (09:11 -0800)
Fixes #76731

Change-Id: I5c686c91af8543b57880a89d30393912ef1958ad
Reviewed-on: https://go-review.googlesource.com/c/go/+/727760
Auto-Submit: Ian Lance Taylor <iant@golang.org>
Reviewed-by: Alessandro Arzilli <alessandro.arzilli@gmail.com>
Reviewed-by: Florian Lehner <lehner.florian86@gmail.com>
Reviewed-by: David Chase <drchase@google.com>
Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>

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

index d9916ae07999cd00bd08a5fbdb9785c63a881156..3900ae065457caf70c105db696d9a58e9da2d76b 100644 (file)
@@ -156,10 +156,102 @@ func testDWARF(t *testing.T, buildmode string, expectDWARF bool, env ...string)
                        if !strings.HasSuffix(line.File.Name, wantFile) || line.Line != wantLine {
                                t.Errorf("%#x is %s:%d, want %s:%d", addr, line.File.Name, line.Line, filepath.Join("...", wantFile), wantLine)
                        }
+
+                       if buildmode != "c-archive" {
+                               testModuledata(t, d)
+                       }
                })
        }
 }
 
+// testModuledata makes sure that runtime.firstmoduledata exists
+// and has a type. Issue #76731.
+func testModuledata(t *testing.T, d *dwarf.Data) {
+       const symName = "runtime.firstmoduledata"
+
+       r := d.Reader()
+       for {
+               e, err := r.Next()
+               if err != nil {
+                       t.Error(err)
+                       return
+               }
+               if e == nil {
+                       t.Errorf("did not find DWARF entry for %s", symName)
+                       return
+               }
+
+               switch e.Tag {
+               case dwarf.TagVariable:
+                       // carry on after switch
+               case dwarf.TagCompileUnit, dwarf.TagSubprogram:
+                       continue
+               default:
+                       r.SkipChildren()
+                       continue
+               }
+
+               nameIdx, typeIdx := -1, -1
+               for i := range e.Field {
+                       f := &e.Field[i]
+                       switch f.Attr {
+                       case dwarf.AttrName:
+                               nameIdx = i
+                       case dwarf.AttrType:
+                               typeIdx = i
+                       }
+               }
+               if nameIdx == -1 {
+                       // unnamed variable?
+                       r.SkipChildren()
+                       continue
+               }
+               nameStr, ok := e.Field[nameIdx].Val.(string)
+               if !ok {
+                       // variable name is not a string?
+                       r.SkipChildren()
+                       continue
+               }
+               if nameStr != symName {
+                       r.SkipChildren()
+                       continue
+               }
+
+               if typeIdx == -1 {
+                       t.Errorf("%s has no DWARF type", symName)
+                       return
+               }
+               off, ok := e.Field[typeIdx].Val.(dwarf.Offset)
+               if !ok {
+                       t.Errorf("unexpected Go type %T for DWARF type for %s; expected %T", e.Field[typeIdx].Val, symName, dwarf.Offset(0))
+                       return
+               }
+
+               typeInfo, err := d.Type(off)
+               if err != nil {
+                       t.Error(err)
+                       return
+               }
+
+               typeName := typeInfo.Common().Name
+               if want := "runtime.moduledata"; typeName != want {
+                       t.Errorf("type of %s is %s, expected %s", symName, typeName, want)
+               }
+               for {
+                       typedef, ok := typeInfo.(*dwarf.TypedefType)
+                       if !ok {
+                               break
+                       }
+                       typeInfo = typedef.Type
+               }
+               if _, ok := typeInfo.(*dwarf.StructType); !ok {
+                       t.Errorf("type of %s is %T, expected %T", symName, typeInfo, dwarf.StructType{})
+               }
+
+               return
+       }
+}
+
 func TestDWARF(t *testing.T) {
        testDWARF(t, "", true)
        if !testing.Short() {
index ff0fa5c377db7c47facba5edb2e98b8dcbbde1bb..5cd39fbc53eb90de0ccd2da365a81d9979c42f7d 100644 (file)
@@ -2036,7 +2036,7 @@ func dwarfGenerateDebugInfo(ctxt *Link) {
                t := d.ldr.SymType(idx)
                switch {
                case t.IsRODATA(), t.IsDATA(), t.IsNOPTRDATA(),
-                       t == sym.STYPE, t == sym.SBSS, t == sym.SNOPTRBSS, t == sym.STLSBSS:
+                       t == sym.STYPE, t == sym.SBSS, t == sym.SNOPTRBSS, t == sym.STLSBSS, t == sym.SMODULEDATA:
                        // ok
                default:
                        continue