mirror of
https://github.com/golang/go
synced 2024-11-17 15:14:42 -07:00
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 <alessandro.arzilli@gmail.com> TryBot-Result: Go Bot <gobot@golang.org> Reviewed-by: Dan Scales <danscales@google.com> Reviewed-by: Than McIntosh <thanm@google.com> Trust: Dan Scales <danscales@google.com> Trust: David Chase <drchase@google.com>
This commit is contained in:
parent
6acac8b685
commit
6268468e02
@ -1479,6 +1479,7 @@ func markTypeUsed(t *types.Type, lsym *obj.LSym) {
|
|||||||
} else {
|
} else {
|
||||||
// TODO: This is somewhat overkill, we really only need it
|
// TODO: This is somewhat overkill, we really only need it
|
||||||
// for types that are put into interfaces.
|
// for types that are put into interfaces.
|
||||||
|
// Note: this relocation is also used in cmd/link/internal/ld/dwarf.go
|
||||||
reflectdata.MarkTypeUsedInInterface(t, lsym)
|
reflectdata.MarkTypeUsedInInterface(t, lsym)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -304,6 +304,7 @@ const (
|
|||||||
const (
|
const (
|
||||||
SymFlagUsedInIface = 1 << iota
|
SymFlagUsedInIface = 1 << iota
|
||||||
SymFlagItab
|
SymFlagItab
|
||||||
|
SymFlagDict
|
||||||
)
|
)
|
||||||
|
|
||||||
// Returns the length of the name of the symbol.
|
// Returns the length of the name of the symbol.
|
||||||
@ -333,6 +334,7 @@ func (s *Sym) ReflectMethod() bool { return s.Flag()&SymFlagReflectMethod != 0 }
|
|||||||
func (s *Sym) IsGoType() bool { return s.Flag()&SymFlagGoType != 0 }
|
func (s *Sym) IsGoType() bool { return s.Flag()&SymFlagGoType != 0 }
|
||||||
func (s *Sym) UsedInIface() bool { return s.Flag2()&SymFlagUsedInIface != 0 }
|
func (s *Sym) UsedInIface() bool { return s.Flag2()&SymFlagUsedInIface != 0 }
|
||||||
func (s *Sym) IsItab() bool { return s.Flag2()&SymFlagItab != 0 }
|
func (s *Sym) IsItab() bool { return s.Flag2()&SymFlagItab != 0 }
|
||||||
|
func (s *Sym) IsDict() bool { return s.Flag2()&SymFlagDict != 0 }
|
||||||
|
|
||||||
func (s *Sym) SetName(x string, w *Writer) {
|
func (s *Sym) SetName(x string, w *Writer) {
|
||||||
binary.LittleEndian.PutUint32(s[:], uint32(len(x)))
|
binary.LittleEndian.PutUint32(s[:], uint32(len(x)))
|
||||||
|
@ -340,6 +340,9 @@ func (w *writer) Sym(s *LSym) {
|
|||||||
if strings.HasPrefix(s.Name, "go.itab.") && s.Type == objabi.SRODATA {
|
if strings.HasPrefix(s.Name, "go.itab.") && s.Type == objabi.SRODATA {
|
||||||
flag2 |= goobj.SymFlagItab
|
flag2 |= goobj.SymFlagItab
|
||||||
}
|
}
|
||||||
|
if strings.HasPrefix(s.Name, w.ctxt.Pkgpath) && strings.HasPrefix(s.Name[len(w.ctxt.Pkgpath):], "..dict") {
|
||||||
|
flag2 |= goobj.SymFlagDict
|
||||||
|
}
|
||||||
name := s.Name
|
name := s.Name
|
||||||
if strings.HasPrefix(name, "gofile..") {
|
if strings.HasPrefix(name, "gofile..") {
|
||||||
name = filepath.ToSlash(name)
|
name = filepath.ToSlash(name)
|
||||||
|
@ -1890,6 +1890,8 @@ func dwarfGenerateDebugInfo(ctxt *Link) {
|
|||||||
// global variables. For each global of this sort, locate
|
// global variables. For each global of this sort, locate
|
||||||
// the corresponding compiler-generated DIE symbol and tack
|
// the corresponding compiler-generated DIE symbol and tack
|
||||||
// it onto the list associated with the unit.
|
// it onto the list associated with the unit.
|
||||||
|
// Also looks for dictionary symbols and generates DIE symbols for each
|
||||||
|
// type they reference.
|
||||||
for idx := loader.Sym(1); idx < loader.Sym(d.ldr.NDef()); idx++ {
|
for idx := loader.Sym(1); idx < loader.Sym(d.ldr.NDef()); idx++ {
|
||||||
if !d.ldr.AttrReachable(idx) ||
|
if !d.ldr.AttrReachable(idx) ||
|
||||||
d.ldr.AttrNotInSymbolTable(idx) ||
|
d.ldr.AttrNotInSymbolTable(idx) ||
|
||||||
@ -1903,9 +1905,21 @@ func dwarfGenerateDebugInfo(ctxt *Link) {
|
|||||||
default:
|
default:
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
// Skip things with no type
|
// Skip things with no type, unless it's a dictionary
|
||||||
gt := d.ldr.SymGoType(idx)
|
gt := d.ldr.SymGoType(idx)
|
||||||
if gt == 0 {
|
if gt == 0 {
|
||||||
|
if t == sym.SRODATA {
|
||||||
|
if d.ldr.IsDict(idx) {
|
||||||
|
// This is a dictionary, make sure that all types referenced by this dictionary are reachable
|
||||||
|
relocs := d.ldr.Relocs(idx)
|
||||||
|
for i := 0; i < relocs.Count(); i++ {
|
||||||
|
reloc := relocs.At(i)
|
||||||
|
if reloc.Type() == objabi.R_USEIFACE {
|
||||||
|
d.defgotype(reloc.Sym())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
// Skip file local symbols (this includes static tmps, stack
|
// Skip file local symbols (this includes static tmps, stack
|
||||||
|
@ -1749,7 +1749,9 @@ func main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestDictIndex(t *testing.T) {
|
func TestDictIndex(t *testing.T) {
|
||||||
// Check that variables with a parametric type have a dictionary index attribute
|
// Check that variables with a parametric type have a dictionary index
|
||||||
|
// attribute and that types that are only referenced through dictionaries
|
||||||
|
// have DIEs.
|
||||||
testenv.MustHaveGoBuild(t)
|
testenv.MustHaveGoBuild(t)
|
||||||
|
|
||||||
if runtime.GOOS == "plan9" {
|
if runtime.GOOS == "plan9" {
|
||||||
@ -1765,6 +1767,8 @@ package main
|
|||||||
|
|
||||||
import "fmt"
|
import "fmt"
|
||||||
|
|
||||||
|
type CustomInt int
|
||||||
|
|
||||||
func testfn[T any](arg T) {
|
func testfn[T any](arg T) {
|
||||||
var mapvar = make(map[int]T)
|
var mapvar = make(map[int]T)
|
||||||
mapvar[0] = arg
|
mapvar[0] = arg
|
||||||
@ -1772,7 +1776,7 @@ func testfn[T any](arg T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
testfn("test")
|
testfn(CustomInt(3))
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
|
|
||||||
@ -1829,4 +1833,19 @@ func main() {
|
|||||||
t.Errorf("could not find DW_AT_go_dict_index attribute offset %#x (%T)", off, entry.Val(intdwarf.DW_AT_go_dict_index))
|
t.Errorf("could not find DW_AT_go_dict_index attribute offset %#x (%T)", off, entry.Val(intdwarf.DW_AT_go_dict_index))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rdr.Seek(0)
|
||||||
|
ex := examiner{}
|
||||||
|
if err := ex.populate(rdr); err != nil {
|
||||||
|
t.Fatalf("error reading DWARF: %v", err)
|
||||||
|
}
|
||||||
|
for _, typeName := range []string{"main.CustomInt", "map[int]main.CustomInt"} {
|
||||||
|
dies := ex.Named(typeName)
|
||||||
|
if len(dies) != 1 {
|
||||||
|
t.Errorf("wanted 1 DIE named %s, found %v", typeName, len(dies))
|
||||||
|
}
|
||||||
|
if dies[0].Val(intdwarf.DW_AT_go_runtime_type).(uint64) == 0 {
|
||||||
|
t.Errorf("type %s does not have DW_AT_go_runtime_type", typeName)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1209,6 +1209,15 @@ func (l *Loader) IsItab(i Sym) bool {
|
|||||||
return r.Sym(li).IsItab()
|
return r.Sym(li).IsItab()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Returns whether this symbol is a dictionary symbol.
|
||||||
|
func (l *Loader) IsDict(i Sym) bool {
|
||||||
|
if l.IsExternal(i) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
r, li := l.toLocal(i)
|
||||||
|
return r.Sym(li).IsDict()
|
||||||
|
}
|
||||||
|
|
||||||
// Return whether this is a trampoline of a deferreturn call.
|
// Return whether this is a trampoline of a deferreturn call.
|
||||||
func (l *Loader) IsDeferReturnTramp(i Sym) bool {
|
func (l *Loader) IsDeferReturnTramp(i Sym) bool {
|
||||||
return l.deferReturnTramp[i]
|
return l.deferReturnTramp[i]
|
||||||
|
Loading…
Reference in New Issue
Block a user