Commit 4d8a37a6 authored by Alessandro Arzilli's avatar Alessandro Arzilli Committed by Heschi Kreinick

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 <alessandro.arzilli@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: default avatarHeschi Kreinick <heschi@google.com>
parent 1a6c0c6b
...@@ -264,15 +264,6 @@ func newrefattr(die *dwarf.DWDie, attr uint16, ref *sym.Symbol) *dwarf.DWAttr { ...@@ -264,15 +264,6 @@ func newrefattr(die *dwarf.DWDie, attr uint16, ref *sym.Symbol) *dwarf.DWAttr {
return newattr(die, attr, dwarf.DW_CLS_REFERENCE, 0, ref) return newattr(die, attr, dwarf.DW_CLS_REFERENCE, 0, ref)
} }
func putdies(linkctxt *Link, ctxt dwarf.Context, syms []*sym.Symbol, die *dwarf.DWDie) []*sym.Symbol {
for ; die != nil; die = die.Link {
syms = putdie(linkctxt, ctxt, syms, die)
}
syms[len(syms)-1].AddUint8(0)
return syms
}
func dtolsym(s dwarf.Sym) *sym.Symbol { func dtolsym(s dwarf.Sym) *sym.Symbol {
if s == nil { if s == nil {
return nil return nil
...@@ -294,7 +285,10 @@ func putdie(linkctxt *Link, ctxt dwarf.Context, syms []*sym.Symbol, die *dwarf.D ...@@ -294,7 +285,10 @@ func putdie(linkctxt *Link, ctxt dwarf.Context, syms []*sym.Symbol, die *dwarf.D
dwarf.Uleb128put(ctxt, s, int64(die.Abbrev)) dwarf.Uleb128put(ctxt, s, int64(die.Abbrev))
dwarf.PutAttrs(ctxt, s, die.Abbrev, die.Attr) dwarf.PutAttrs(ctxt, s, die.Abbrev, die.Attr)
if dwarf.HasChildren(die) { if dwarf.HasChildren(die) {
return putdies(linkctxt, ctxt, syms, die.Child) for die := die.Child; die != nil; die = die.Link {
syms = putdie(linkctxt, ctxt, syms, die)
}
syms[len(syms)-1].AddUint8(0)
} }
return syms return syms
} }
...@@ -1517,7 +1511,7 @@ const ( ...@@ -1517,7 +1511,7 @@ const (
COMPUNITHEADERSIZE = 4 + 2 + 4 + 1 COMPUNITHEADERSIZE = 4 + 2 + 4 + 1
) )
func writeinfo(ctxt *Link, syms []*sym.Symbol, units []*compilationUnit, abbrevsym *sym.Symbol) []*sym.Symbol { func writeinfo(ctxt *Link, syms []*sym.Symbol, units []*compilationUnit, abbrevsym *sym.Symbol, pubNames, pubTypes *pubWriter) []*sym.Symbol {
infosec := ctxt.Syms.Lookup(".debug_info", 0) infosec := ctxt.Syms.Lookup(".debug_info", 0)
infosec.Type = sym.SDWARFINFO infosec.Type = sym.SDWARFINFO
infosec.Attr |= sym.AttrReachable infosec.Attr |= sym.AttrReachable
...@@ -1533,6 +1527,9 @@ func writeinfo(ctxt *Link, syms []*sym.Symbol, units []*compilationUnit, abbrevs ...@@ -1533,6 +1527,9 @@ func writeinfo(ctxt *Link, syms []*sym.Symbol, units []*compilationUnit, abbrevs
continue continue
} }
pubNames.beginCompUnit(compunit)
pubTypes.beginCompUnit(compunit)
// Write .debug_info Compilation Unit Header (sec 7.5.1) // Write .debug_info Compilation Unit Header (sec 7.5.1)
// Fields marked with (*) must be changed for 64-bit dwarf // Fields marked with (*) must be changed for 64-bit dwarf
// This must match COMPUNITHEADERSIZE above. // This must match COMPUNITHEADERSIZE above.
...@@ -1553,11 +1550,32 @@ func writeinfo(ctxt *Link, syms []*sym.Symbol, units []*compilationUnit, abbrevs ...@@ -1553,11 +1550,32 @@ func writeinfo(ctxt *Link, syms []*sym.Symbol, units []*compilationUnit, abbrevs
if u.consts != nil { if u.consts != nil {
cu = append(cu, u.consts) cu = append(cu, u.consts)
} }
cu = putdies(ctxt, dwarfctxt, cu, compunit.Child)
var cusize int64 var cusize int64
for _, child := range cu { for _, child := range cu {
cusize += child.Size cusize += child.Size
} }
for die := compunit.Child; die != nil; die = die.Link {
l := len(cu)
lastSymSz := cu[l-1].Size
cu = putdie(ctxt, dwarfctxt, cu, die)
if ispubname(die) {
pubNames.add(die, cusize)
}
if ispubtype(die) {
pubTypes.add(die, cusize)
}
if lastSymSz != cu[l-1].Size {
// putdie will sometimes append directly to the last symbol of the list
cusize = cusize - lastSymSz + cu[l-1].Size
}
for _, child := range cu[l:] {
cusize += child.Size
}
}
cu[len(cu)-1].AddUint8(0) // closes compilation unit DIE
cusize++
// Save size for AIX symbol table. // Save size for AIX symbol table.
if ctxt.HeadType == objabi.Haix { if ctxt.HeadType == objabi.Haix {
saveDwsectCUSize(".debug_info", getPkgFromCUSym(s), uint64(cusize)) saveDwsectCUSize(".debug_info", getPkgFromCUSym(s), uint64(cusize))
...@@ -1569,9 +1587,8 @@ func writeinfo(ctxt *Link, syms []*sym.Symbol, units []*compilationUnit, abbrevs ...@@ -1569,9 +1587,8 @@ func writeinfo(ctxt *Link, syms []*sym.Symbol, units []*compilationUnit, abbrevs
cusize -= 4 // exclude the length field. cusize -= 4 // exclude the length field.
s.SetUint32(ctxt.Arch, 0, uint32(cusize)) s.SetUint32(ctxt.Arch, 0, uint32(cusize))
} }
// Leave a breadcrumb for writepub. This does not pubNames.endCompUnit(compunit, uint32(cusize)+4)
// appear in the DWARF output. pubTypes.endCompUnit(compunit, uint32(cusize)+4)
newattr(compunit, dwarf.DW_AT_byte_size, dwarf.DW_CLS_CONSTANT, cusize, 0)
syms = append(syms, cu...) syms = append(syms, cu...)
} }
return syms return syms
...@@ -1595,52 +1612,57 @@ func ispubtype(die *dwarf.DWDie) bool { ...@@ -1595,52 +1612,57 @@ func ispubtype(die *dwarf.DWDie) bool {
return die.Abbrev >= dwarf.DW_ABRV_NULLTYPE return die.Abbrev >= dwarf.DW_ABRV_NULLTYPE
} }
func writepub(ctxt *Link, sname string, ispub func(*dwarf.DWDie) bool, syms []*sym.Symbol) []*sym.Symbol { type pubWriter struct {
ctxt *Link
s *sym.Symbol
sname string
sectionstart int64
culengthOff int64
}
func newPubWriter(ctxt *Link, sname string) *pubWriter {
s := ctxt.Syms.Lookup(sname, 0) s := ctxt.Syms.Lookup(sname, 0)
s.Type = sym.SDWARFSECT s.Type = sym.SDWARFSECT
syms = append(syms, s) return &pubWriter{ctxt: ctxt, s: s, sname: sname}
}
for _, u := range ctxt.compUnits { func (pw *pubWriter) beginCompUnit(compunit *dwarf.DWDie) {
if len(u.lib.Textp) == 0 && u.dwinfo.Child == nil { pw.sectionstart = pw.s.Size
continue
}
compunit := u.dwinfo
sectionstart := s.Size
culength := uint32(getattr(compunit, dwarf.DW_AT_byte_size).Value) + 4
// Write .debug_pubnames/types Header (sec 6.1.1) // Write .debug_pubnames/types Header (sec 6.1.1)
createUnitLength(ctxt, s, 0) // unit_length (*), will be filled in later. createUnitLength(pw.ctxt, pw.s, 0) // unit_length (*), will be filled in later.
s.AddUint16(ctxt.Arch, 2) // dwarf version (appendix F) pw.s.AddUint16(pw.ctxt.Arch, 2) // dwarf version (appendix F)
addDwarfAddrRef(ctxt, s, dtolsym(compunit.Sym)) // debug_info_offset (of the Comp unit Header) addDwarfAddrRef(pw.ctxt, pw.s, dtolsym(compunit.Sym)) // debug_info_offset (of the Comp unit Header)
addDwarfAddrField(ctxt, s, uint64(culength)) // debug_info_length pw.culengthOff = pw.s.Size
addDwarfAddrField(pw.ctxt, pw.s, uint64(0)) // debug_info_length, will be filled in later.
for die := compunit.Child; die != nil; die = die.Link { }
if !ispub(die) {
continue func (pw *pubWriter) add(die *dwarf.DWDie, offset int64) {
}
dwa := getattr(die, dwarf.DW_AT_name) dwa := getattr(die, dwarf.DW_AT_name)
name := dwa.Data.(string) name := dwa.Data.(string)
if die.Sym == nil { if die.Sym == nil {
fmt.Println("Missing sym for ", name) fmt.Println("Missing sym for ", name)
} }
addDwarfAddrRef(ctxt, s, dtolsym(die.Sym)) addDwarfAddrField(pw.ctxt, pw.s, uint64(offset))
Addstring(s, name) Addstring(pw.s, name)
} }
addDwarfAddrField(ctxt, s, 0) // Null offset func (pw *pubWriter) endCompUnit(compunit *dwarf.DWDie, culength uint32) {
addDwarfAddrField(pw.ctxt, pw.s, 0) // Null offset
// On AIX, save the current size of this compilation unit. // On AIX, save the current size of this compilation unit.
if ctxt.HeadType == objabi.Haix { if pw.ctxt.HeadType == objabi.Haix {
saveDwsectCUSize(sname, getPkgFromCUSym(dtolsym(compunit.Sym)), uint64(s.Size-sectionstart)) saveDwsectCUSize(pw.sname, getPkgFromCUSym(dtolsym(compunit.Sym)), uint64(pw.s.Size-pw.sectionstart))
} }
if isDwarf64(ctxt) { if isDwarf64(pw.ctxt) {
s.SetUint(ctxt.Arch, sectionstart+4, uint64(s.Size-sectionstart)-12) // exclude the length field. pw.s.SetUint(pw.ctxt.Arch, pw.sectionstart+4, uint64(pw.s.Size-pw.sectionstart)-12) // exclude the length field.
pw.s.SetUint(pw.ctxt.Arch, pw.culengthOff, uint64(culength))
} else { } else {
s.SetUint32(ctxt.Arch, sectionstart, uint32(s.Size-sectionstart)-4) // exclude the length field. pw.s.SetUint32(pw.ctxt.Arch, pw.sectionstart, uint32(pw.s.Size-pw.sectionstart)-4) // exclude the length field.
} pw.s.SetUint32(pw.ctxt.Arch, pw.culengthOff, culength)
} }
return syms
} }
func writegdbscript(ctxt *Link, syms []*sym.Symbol) []*sym.Symbol { func writegdbscript(ctxt *Link, syms []*sym.Symbol) []*sym.Symbol {
...@@ -1878,13 +1900,14 @@ func dwarfGenerateDebugSyms(ctxt *Link) { ...@@ -1878,13 +1900,14 @@ func dwarfGenerateDebugSyms(ctxt *Link) {
reversetree(&dwtypes.Child) reversetree(&dwtypes.Child)
movetomodule(ctxt, &dwtypes) movetomodule(ctxt, &dwtypes)
pubNames := newPubWriter(ctxt, ".debug_pubnames")
pubTypes := newPubWriter(ctxt, ".debug_pubtypes")
// Need to reorder symbols so sym.SDWARFINFO is after all sym.SDWARFSECT // Need to reorder symbols so sym.SDWARFINFO is after all sym.SDWARFSECT
// (but we need to generate dies before writepub) infosyms := writeinfo(ctxt, nil, ctxt.compUnits, abbrev, pubNames, pubTypes)
infosyms := writeinfo(ctxt, nil, ctxt.compUnits, abbrev)
syms = writeframes(ctxt, syms) syms = writeframes(ctxt, syms)
syms = writepub(ctxt, ".debug_pubnames", ispubname, syms) syms = append(syms, pubNames.s, pubTypes.s)
syms = writepub(ctxt, ".debug_pubtypes", ispubtype, syms)
syms = writegdbscript(ctxt, syms) syms = writegdbscript(ctxt, syms)
// Now we're done writing SDWARFSECT symbols, so we can write // Now we're done writing SDWARFSECT symbols, so we can write
// other SDWARF* symbols. // other SDWARF* symbols.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment