Skip to content

Commit 4d8a37a

Browse files
aarzilliheschi
authored andcommitted
cmd/link: fix contents of debug_pubnames/debug_pubtypes
The contents of debug_pubnames and debug_pubtypes have been wrong since Go 1.12. CL golang.org/cl/137235 moved global variables DIE to their respective compilation unit, unfortunately writepub can't emit correct sections for anything but the first compilation unit. This commit moves the code generating debug_pubnames and debug_pubtypes inside writeinfo and fixes it. Gets rid of a number of unnecessary relocations as well as a hack that writeinfo used to communicate to writepub the size of each compilation unit. Fixes #30573 Change-Id: Ibdaa80c02746ae81661c2cfe1d218092c5ae9236 Reviewed-on: https://go-review.googlesource.com/c/go/+/165337 Run-TryBot: Alessandro Arzilli <[email protected]> TryBot-Result: Gobot Gobot <[email protected]> Reviewed-by: Heschi Kreinick <[email protected]>
1 parent 1a6c0c6 commit 4d8a37a

File tree

1 file changed

+80
-57
lines changed

1 file changed

+80
-57
lines changed

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

Lines changed: 80 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -264,15 +264,6 @@ func newrefattr(die *dwarf.DWDie, attr uint16, ref *sym.Symbol) *dwarf.DWAttr {
264264
return newattr(die, attr, dwarf.DW_CLS_REFERENCE, 0, ref)
265265
}
266266

267-
func putdies(linkctxt *Link, ctxt dwarf.Context, syms []*sym.Symbol, die *dwarf.DWDie) []*sym.Symbol {
268-
for ; die != nil; die = die.Link {
269-
syms = putdie(linkctxt, ctxt, syms, die)
270-
}
271-
syms[len(syms)-1].AddUint8(0)
272-
273-
return syms
274-
}
275-
276267
func dtolsym(s dwarf.Sym) *sym.Symbol {
277268
if s == nil {
278269
return nil
@@ -294,7 +285,10 @@ func putdie(linkctxt *Link, ctxt dwarf.Context, syms []*sym.Symbol, die *dwarf.D
294285
dwarf.Uleb128put(ctxt, s, int64(die.Abbrev))
295286
dwarf.PutAttrs(ctxt, s, die.Abbrev, die.Attr)
296287
if dwarf.HasChildren(die) {
297-
return putdies(linkctxt, ctxt, syms, die.Child)
288+
for die := die.Child; die != nil; die = die.Link {
289+
syms = putdie(linkctxt, ctxt, syms, die)
290+
}
291+
syms[len(syms)-1].AddUint8(0)
298292
}
299293
return syms
300294
}
@@ -1517,7 +1511,7 @@ const (
15171511
COMPUNITHEADERSIZE = 4 + 2 + 4 + 1
15181512
)
15191513

1520-
func writeinfo(ctxt *Link, syms []*sym.Symbol, units []*compilationUnit, abbrevsym *sym.Symbol) []*sym.Symbol {
1514+
func writeinfo(ctxt *Link, syms []*sym.Symbol, units []*compilationUnit, abbrevsym *sym.Symbol, pubNames, pubTypes *pubWriter) []*sym.Symbol {
15211515
infosec := ctxt.Syms.Lookup(".debug_info", 0)
15221516
infosec.Type = sym.SDWARFINFO
15231517
infosec.Attr |= sym.AttrReachable
@@ -1533,6 +1527,9 @@ func writeinfo(ctxt *Link, syms []*sym.Symbol, units []*compilationUnit, abbrevs
15331527
continue
15341528
}
15351529

1530+
pubNames.beginCompUnit(compunit)
1531+
pubTypes.beginCompUnit(compunit)
1532+
15361533
// Write .debug_info Compilation Unit Header (sec 7.5.1)
15371534
// Fields marked with (*) must be changed for 64-bit dwarf
15381535
// This must match COMPUNITHEADERSIZE above.
@@ -1553,11 +1550,32 @@ func writeinfo(ctxt *Link, syms []*sym.Symbol, units []*compilationUnit, abbrevs
15531550
if u.consts != nil {
15541551
cu = append(cu, u.consts)
15551552
}
1556-
cu = putdies(ctxt, dwarfctxt, cu, compunit.Child)
15571553
var cusize int64
15581554
for _, child := range cu {
15591555
cusize += child.Size
15601556
}
1557+
1558+
for die := compunit.Child; die != nil; die = die.Link {
1559+
l := len(cu)
1560+
lastSymSz := cu[l-1].Size
1561+
cu = putdie(ctxt, dwarfctxt, cu, die)
1562+
if ispubname(die) {
1563+
pubNames.add(die, cusize)
1564+
}
1565+
if ispubtype(die) {
1566+
pubTypes.add(die, cusize)
1567+
}
1568+
if lastSymSz != cu[l-1].Size {
1569+
// putdie will sometimes append directly to the last symbol of the list
1570+
cusize = cusize - lastSymSz + cu[l-1].Size
1571+
}
1572+
for _, child := range cu[l:] {
1573+
cusize += child.Size
1574+
}
1575+
}
1576+
cu[len(cu)-1].AddUint8(0) // closes compilation unit DIE
1577+
cusize++
1578+
15611579
// Save size for AIX symbol table.
15621580
if ctxt.HeadType == objabi.Haix {
15631581
saveDwsectCUSize(".debug_info", getPkgFromCUSym(s), uint64(cusize))
@@ -1569,9 +1587,8 @@ func writeinfo(ctxt *Link, syms []*sym.Symbol, units []*compilationUnit, abbrevs
15691587
cusize -= 4 // exclude the length field.
15701588
s.SetUint32(ctxt.Arch, 0, uint32(cusize))
15711589
}
1572-
// Leave a breadcrumb for writepub. This does not
1573-
// appear in the DWARF output.
1574-
newattr(compunit, dwarf.DW_AT_byte_size, dwarf.DW_CLS_CONSTANT, cusize, 0)
1590+
pubNames.endCompUnit(compunit, uint32(cusize)+4)
1591+
pubTypes.endCompUnit(compunit, uint32(cusize)+4)
15751592
syms = append(syms, cu...)
15761593
}
15771594
return syms
@@ -1595,52 +1612,57 @@ func ispubtype(die *dwarf.DWDie) bool {
15951612
return die.Abbrev >= dwarf.DW_ABRV_NULLTYPE
15961613
}
15971614

1598-
func writepub(ctxt *Link, sname string, ispub func(*dwarf.DWDie) bool, syms []*sym.Symbol) []*sym.Symbol {
1615+
type pubWriter struct {
1616+
ctxt *Link
1617+
s *sym.Symbol
1618+
sname string
1619+
1620+
sectionstart int64
1621+
culengthOff int64
1622+
}
1623+
1624+
func newPubWriter(ctxt *Link, sname string) *pubWriter {
15991625
s := ctxt.Syms.Lookup(sname, 0)
16001626
s.Type = sym.SDWARFSECT
1601-
syms = append(syms, s)
1602-
1603-
for _, u := range ctxt.compUnits {
1604-
if len(u.lib.Textp) == 0 && u.dwinfo.Child == nil {
1605-
continue
1606-
}
1607-
compunit := u.dwinfo
1608-
sectionstart := s.Size
1609-
culength := uint32(getattr(compunit, dwarf.DW_AT_byte_size).Value) + 4
1627+
return &pubWriter{ctxt: ctxt, s: s, sname: sname}
1628+
}
16101629

1611-
// Write .debug_pubnames/types Header (sec 6.1.1)
1612-
createUnitLength(ctxt, s, 0) // unit_length (*), will be filled in later.
1613-
s.AddUint16(ctxt.Arch, 2) // dwarf version (appendix F)
1614-
addDwarfAddrRef(ctxt, s, dtolsym(compunit.Sym)) // debug_info_offset (of the Comp unit Header)
1615-
addDwarfAddrField(ctxt, s, uint64(culength)) // debug_info_length
1630+
func (pw *pubWriter) beginCompUnit(compunit *dwarf.DWDie) {
1631+
pw.sectionstart = pw.s.Size
16161632

1617-
for die := compunit.Child; die != nil; die = die.Link {
1618-
if !ispub(die) {
1619-
continue
1620-
}
1621-
dwa := getattr(die, dwarf.DW_AT_name)
1622-
name := dwa.Data.(string)
1623-
if die.Sym == nil {
1624-
fmt.Println("Missing sym for ", name)
1625-
}
1626-
addDwarfAddrRef(ctxt, s, dtolsym(die.Sym))
1627-
Addstring(s, name)
1628-
}
1633+
// Write .debug_pubnames/types Header (sec 6.1.1)
1634+
createUnitLength(pw.ctxt, pw.s, 0) // unit_length (*), will be filled in later.
1635+
pw.s.AddUint16(pw.ctxt.Arch, 2) // dwarf version (appendix F)
1636+
addDwarfAddrRef(pw.ctxt, pw.s, dtolsym(compunit.Sym)) // debug_info_offset (of the Comp unit Header)
1637+
pw.culengthOff = pw.s.Size
1638+
addDwarfAddrField(pw.ctxt, pw.s, uint64(0)) // debug_info_length, will be filled in later.
16291639

1630-
addDwarfAddrField(ctxt, s, 0) // Null offset
1640+
}
16311641

1632-
// On AIX, save the current size of this compilation unit.
1633-
if ctxt.HeadType == objabi.Haix {
1634-
saveDwsectCUSize(sname, getPkgFromCUSym(dtolsym(compunit.Sym)), uint64(s.Size-sectionstart))
1635-
}
1636-
if isDwarf64(ctxt) {
1637-
s.SetUint(ctxt.Arch, sectionstart+4, uint64(s.Size-sectionstart)-12) // exclude the length field.
1638-
} else {
1639-
s.SetUint32(ctxt.Arch, sectionstart, uint32(s.Size-sectionstart)-4) // exclude the length field.
1640-
}
1642+
func (pw *pubWriter) add(die *dwarf.DWDie, offset int64) {
1643+
dwa := getattr(die, dwarf.DW_AT_name)
1644+
name := dwa.Data.(string)
1645+
if die.Sym == nil {
1646+
fmt.Println("Missing sym for ", name)
16411647
}
1648+
addDwarfAddrField(pw.ctxt, pw.s, uint64(offset))
1649+
Addstring(pw.s, name)
1650+
}
16421651

1643-
return syms
1652+
func (pw *pubWriter) endCompUnit(compunit *dwarf.DWDie, culength uint32) {
1653+
addDwarfAddrField(pw.ctxt, pw.s, 0) // Null offset
1654+
1655+
// On AIX, save the current size of this compilation unit.
1656+
if pw.ctxt.HeadType == objabi.Haix {
1657+
saveDwsectCUSize(pw.sname, getPkgFromCUSym(dtolsym(compunit.Sym)), uint64(pw.s.Size-pw.sectionstart))
1658+
}
1659+
if isDwarf64(pw.ctxt) {
1660+
pw.s.SetUint(pw.ctxt.Arch, pw.sectionstart+4, uint64(pw.s.Size-pw.sectionstart)-12) // exclude the length field.
1661+
pw.s.SetUint(pw.ctxt.Arch, pw.culengthOff, uint64(culength))
1662+
} else {
1663+
pw.s.SetUint32(pw.ctxt.Arch, pw.sectionstart, uint32(pw.s.Size-pw.sectionstart)-4) // exclude the length field.
1664+
pw.s.SetUint32(pw.ctxt.Arch, pw.culengthOff, culength)
1665+
}
16441666
}
16451667

16461668
func writegdbscript(ctxt *Link, syms []*sym.Symbol) []*sym.Symbol {
@@ -1878,13 +1900,14 @@ func dwarfGenerateDebugSyms(ctxt *Link) {
18781900
reversetree(&dwtypes.Child)
18791901
movetomodule(ctxt, &dwtypes)
18801902

1903+
pubNames := newPubWriter(ctxt, ".debug_pubnames")
1904+
pubTypes := newPubWriter(ctxt, ".debug_pubtypes")
1905+
18811906
// Need to reorder symbols so sym.SDWARFINFO is after all sym.SDWARFSECT
1882-
// (but we need to generate dies before writepub)
1883-
infosyms := writeinfo(ctxt, nil, ctxt.compUnits, abbrev)
1907+
infosyms := writeinfo(ctxt, nil, ctxt.compUnits, abbrev, pubNames, pubTypes)
18841908

18851909
syms = writeframes(ctxt, syms)
1886-
syms = writepub(ctxt, ".debug_pubnames", ispubname, syms)
1887-
syms = writepub(ctxt, ".debug_pubtypes", ispubtype, syms)
1910+
syms = append(syms, pubNames.s, pubTypes.s)
18881911
syms = writegdbscript(ctxt, syms)
18891912
// Now we're done writing SDWARFSECT symbols, so we can write
18901913
// other SDWARF* symbols.

0 commit comments

Comments
 (0)