cmd/link: generate DWARF for moduledata

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>
This commit is contained in:
Ian Lance Taylor
2025-12-06 15:06:11 -08:00
committed by Gopher Robot
parent 44a39c9dac
commit b5f6816cea
2 changed files with 93 additions and 1 deletions

View 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() {

View 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