Skip to content

Commit 6268468

Browse files
aarzillithanm
authored andcommitted
cmd/link: generate DIE for types referenced only through dictionaries
Generate debug_info entries for types that are only referenced through dictionaries. Change-Id: Ic36c2e6d9588ec6746793bb213c2dc0e17a8a850 Reviewed-on: https://go-review.googlesource.com/c/go/+/350532 Run-TryBot: Alessandro Arzilli <[email protected]> TryBot-Result: Go Bot <[email protected]> Reviewed-by: Dan Scales <[email protected]> Reviewed-by: Than McIntosh <[email protected]> Trust: Dan Scales <[email protected]> Trust: David Chase <[email protected]>
1 parent 6acac8b commit 6268468

File tree

6 files changed

+51
-3
lines changed

6 files changed

+51
-3
lines changed

src/cmd/compile/internal/noder/stencil.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1479,6 +1479,7 @@ func markTypeUsed(t *types.Type, lsym *obj.LSym) {
14791479
} else {
14801480
// TODO: This is somewhat overkill, we really only need it
14811481
// for types that are put into interfaces.
1482+
// Note: this relocation is also used in cmd/link/internal/ld/dwarf.go
14821483
reflectdata.MarkTypeUsedInInterface(t, lsym)
14831484
}
14841485
}

src/cmd/internal/goobj/objfile.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -304,6 +304,7 @@ const (
304304
const (
305305
SymFlagUsedInIface = 1 << iota
306306
SymFlagItab
307+
SymFlagDict
307308
)
308309

309310
// Returns the length of the name of the symbol.
@@ -333,6 +334,7 @@ func (s *Sym) ReflectMethod() bool { return s.Flag()&SymFlagReflectMethod != 0 }
333334
func (s *Sym) IsGoType() bool { return s.Flag()&SymFlagGoType != 0 }
334335
func (s *Sym) UsedInIface() bool { return s.Flag2()&SymFlagUsedInIface != 0 }
335336
func (s *Sym) IsItab() bool { return s.Flag2()&SymFlagItab != 0 }
337+
func (s *Sym) IsDict() bool { return s.Flag2()&SymFlagDict != 0 }
336338

337339
func (s *Sym) SetName(x string, w *Writer) {
338340
binary.LittleEndian.PutUint32(s[:], uint32(len(x)))

src/cmd/internal/obj/objfile.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -340,6 +340,9 @@ func (w *writer) Sym(s *LSym) {
340340
if strings.HasPrefix(s.Name, "go.itab.") && s.Type == objabi.SRODATA {
341341
flag2 |= goobj.SymFlagItab
342342
}
343+
if strings.HasPrefix(s.Name, w.ctxt.Pkgpath) && strings.HasPrefix(s.Name[len(w.ctxt.Pkgpath):], "..dict") {
344+
flag2 |= goobj.SymFlagDict
345+
}
343346
name := s.Name
344347
if strings.HasPrefix(name, "gofile..") {
345348
name = filepath.ToSlash(name)

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

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1890,6 +1890,8 @@ func dwarfGenerateDebugInfo(ctxt *Link) {
18901890
// global variables. For each global of this sort, locate
18911891
// the corresponding compiler-generated DIE symbol and tack
18921892
// it onto the list associated with the unit.
1893+
// Also looks for dictionary symbols and generates DIE symbols for each
1894+
// type they reference.
18931895
for idx := loader.Sym(1); idx < loader.Sym(d.ldr.NDef()); idx++ {
18941896
if !d.ldr.AttrReachable(idx) ||
18951897
d.ldr.AttrNotInSymbolTable(idx) ||
@@ -1903,9 +1905,21 @@ func dwarfGenerateDebugInfo(ctxt *Link) {
19031905
default:
19041906
continue
19051907
}
1906-
// Skip things with no type
1908+
// Skip things with no type, unless it's a dictionary
19071909
gt := d.ldr.SymGoType(idx)
19081910
if gt == 0 {
1911+
if t == sym.SRODATA {
1912+
if d.ldr.IsDict(idx) {
1913+
// This is a dictionary, make sure that all types referenced by this dictionary are reachable
1914+
relocs := d.ldr.Relocs(idx)
1915+
for i := 0; i < relocs.Count(); i++ {
1916+
reloc := relocs.At(i)
1917+
if reloc.Type() == objabi.R_USEIFACE {
1918+
d.defgotype(reloc.Sym())
1919+
}
1920+
}
1921+
}
1922+
}
19091923
continue
19101924
}
19111925
// Skip file local symbols (this includes static tmps, stack

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

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1749,7 +1749,9 @@ func main() {
17491749
}
17501750

17511751
func TestDictIndex(t *testing.T) {
1752-
// Check that variables with a parametric type have a dictionary index attribute
1752+
// Check that variables with a parametric type have a dictionary index
1753+
// attribute and that types that are only referenced through dictionaries
1754+
// have DIEs.
17531755
testenv.MustHaveGoBuild(t)
17541756

17551757
if runtime.GOOS == "plan9" {
@@ -1765,14 +1767,16 @@ package main
17651767
17661768
import "fmt"
17671769
1770+
type CustomInt int
1771+
17681772
func testfn[T any](arg T) {
17691773
var mapvar = make(map[int]T)
17701774
mapvar[0] = arg
17711775
fmt.Println(arg, mapvar)
17721776
}
17731777
17741778
func main() {
1775-
testfn("test")
1779+
testfn(CustomInt(3))
17761780
}
17771781
`
17781782

@@ -1829,4 +1833,19 @@ func main() {
18291833
t.Errorf("could not find DW_AT_go_dict_index attribute offset %#x (%T)", off, entry.Val(intdwarf.DW_AT_go_dict_index))
18301834
}
18311835
}
1836+
1837+
rdr.Seek(0)
1838+
ex := examiner{}
1839+
if err := ex.populate(rdr); err != nil {
1840+
t.Fatalf("error reading DWARF: %v", err)
1841+
}
1842+
for _, typeName := range []string{"main.CustomInt", "map[int]main.CustomInt"} {
1843+
dies := ex.Named(typeName)
1844+
if len(dies) != 1 {
1845+
t.Errorf("wanted 1 DIE named %s, found %v", typeName, len(dies))
1846+
}
1847+
if dies[0].Val(intdwarf.DW_AT_go_runtime_type).(uint64) == 0 {
1848+
t.Errorf("type %s does not have DW_AT_go_runtime_type", typeName)
1849+
}
1850+
}
18321851
}

src/cmd/link/internal/loader/loader.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1209,6 +1209,15 @@ func (l *Loader) IsItab(i Sym) bool {
12091209
return r.Sym(li).IsItab()
12101210
}
12111211

1212+
// Returns whether this symbol is a dictionary symbol.
1213+
func (l *Loader) IsDict(i Sym) bool {
1214+
if l.IsExternal(i) {
1215+
return false
1216+
}
1217+
r, li := l.toLocal(i)
1218+
return r.Sym(li).IsDict()
1219+
}
1220+
12121221
// Return whether this is a trampoline of a deferreturn call.
12131222
func (l *Loader) IsDeferReturnTramp(i Sym) bool {
12141223
return l.deferReturnTramp[i]

0 commit comments

Comments
 (0)