]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/link: fix contents of debug_pubnames/debug_pubtypes
authorAlessandro Arzilli <alessandro.arzilli@gmail.com>
Tue, 5 Mar 2019 08:58:58 +0000 (09:58 +0100)
committerHeschi Kreinick <heschi@google.com>
Wed, 6 Mar 2019 23:18:15 +0000 (23:18 +0000)
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: Heschi Kreinick <heschi@google.com>
src/cmd/link/internal/ld/dwarf.go

index 0b17985da5b56a020f9b867d99820b72ec5e2781..995a7e77b9ff9af715bd6ac28d22206a37640628 100644 (file)
@@ -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)
 }
 
-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 {
        if s == nil {
                return nil
@@ -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.PutAttrs(ctxt, s, die.Abbrev, die.Attr)
        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
 }
@@ -1517,7 +1511,7 @@ const (
        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.Type = sym.SDWARFINFO
        infosec.Attr |= sym.AttrReachable
@@ -1533,6 +1527,9 @@ func writeinfo(ctxt *Link, syms []*sym.Symbol, units []*compilationUnit, abbrevs
                        continue
                }
 
+               pubNames.beginCompUnit(compunit)
+               pubTypes.beginCompUnit(compunit)
+
                // Write .debug_info Compilation Unit Header (sec 7.5.1)
                // Fields marked with (*) must be changed for 64-bit dwarf
                // This must match COMPUNITHEADERSIZE above.
@@ -1553,11 +1550,32 @@ func writeinfo(ctxt *Link, syms []*sym.Symbol, units []*compilationUnit, abbrevs
                if u.consts != nil {
                        cu = append(cu, u.consts)
                }
-               cu = putdies(ctxt, dwarfctxt, cu, compunit.Child)
                var cusize int64
                for _, child := range cu {
                        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.
                if ctxt.HeadType == objabi.Haix {
                        saveDwsectCUSize(".debug_info", getPkgFromCUSym(s), uint64(cusize))
@@ -1569,9 +1587,8 @@ func writeinfo(ctxt *Link, syms []*sym.Symbol, units []*compilationUnit, abbrevs
                        cusize -= 4 // exclude the length field.
                        s.SetUint32(ctxt.Arch, 0, uint32(cusize))
                }
-               // Leave a breadcrumb for writepub. This does not
-               // appear in the DWARF output.
-               newattr(compunit, dwarf.DW_AT_byte_size, dwarf.DW_CLS_CONSTANT, cusize, 0)
+               pubNames.endCompUnit(compunit, uint32(cusize)+4)
+               pubTypes.endCompUnit(compunit, uint32(cusize)+4)
                syms = append(syms, cu...)
        }
        return syms
@@ -1595,52 +1612,57 @@ func ispubtype(die *dwarf.DWDie) bool {
        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.Type = sym.SDWARFSECT
-       syms = append(syms, s)
-
-       for _, u := range ctxt.compUnits {
-               if len(u.lib.Textp) == 0 && u.dwinfo.Child == nil {
-                       continue
-               }
-               compunit := u.dwinfo
-               sectionstart := s.Size
-               culength := uint32(getattr(compunit, dwarf.DW_AT_byte_size).Value) + 4
+       return &pubWriter{ctxt: ctxt, s: s, sname: sname}
+}
 
-               // Write .debug_pubnames/types  Header (sec 6.1.1)
-               createUnitLength(ctxt, s, 0)                    // unit_length (*), will be filled in later.
-               s.AddUint16(ctxt.Arch, 2)                       // dwarf version (appendix F)
-               addDwarfAddrRef(ctxt, s, dtolsym(compunit.Sym)) // debug_info_offset (of the Comp unit Header)
-               addDwarfAddrField(ctxt, s, uint64(culength))    // debug_info_length
+func (pw *pubWriter) beginCompUnit(compunit *dwarf.DWDie) {
+       pw.sectionstart = pw.s.Size
 
-               for die := compunit.Child; die != nil; die = die.Link {
-                       if !ispub(die) {
-                               continue
-                       }
-                       dwa := getattr(die, dwarf.DW_AT_name)
-                       name := dwa.Data.(string)
-                       if die.Sym == nil {
-                               fmt.Println("Missing sym for ", name)
-                       }
-                       addDwarfAddrRef(ctxt, s, dtolsym(die.Sym))
-                       Addstring(s, name)
-               }
+       // Write .debug_pubnames/types  Header (sec 6.1.1)
+       createUnitLength(pw.ctxt, pw.s, 0)                    // unit_length (*), will be filled in later.
+       pw.s.AddUint16(pw.ctxt.Arch, 2)                       // dwarf version (appendix F)
+       addDwarfAddrRef(pw.ctxt, pw.s, dtolsym(compunit.Sym)) // debug_info_offset (of the Comp unit Header)
+       pw.culengthOff = pw.s.Size
+       addDwarfAddrField(pw.ctxt, pw.s, uint64(0)) // debug_info_length, will be filled in later.
 
-               addDwarfAddrField(ctxt, s, 0) // Null offset
+}
 
-               // On AIX, save the current size of this compilation unit.
-               if ctxt.HeadType == objabi.Haix {
-                       saveDwsectCUSize(sname, getPkgFromCUSym(dtolsym(compunit.Sym)), uint64(s.Size-sectionstart))
-               }
-               if isDwarf64(ctxt) {
-                       s.SetUint(ctxt.Arch, sectionstart+4, uint64(s.Size-sectionstart)-12) // exclude the length field.
-               } else {
-                       s.SetUint32(ctxt.Arch, sectionstart, uint32(s.Size-sectionstart)-4) // exclude the length field.
-               }
+func (pw *pubWriter) add(die *dwarf.DWDie, offset int64) {
+       dwa := getattr(die, dwarf.DW_AT_name)
+       name := dwa.Data.(string)
+       if die.Sym == nil {
+               fmt.Println("Missing sym for ", name)
        }
+       addDwarfAddrField(pw.ctxt, pw.s, uint64(offset))
+       Addstring(pw.s, name)
+}
 
-       return syms
+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.
+       if pw.ctxt.HeadType == objabi.Haix {
+               saveDwsectCUSize(pw.sname, getPkgFromCUSym(dtolsym(compunit.Sym)), uint64(pw.s.Size-pw.sectionstart))
+       }
+       if isDwarf64(pw.ctxt) {
+               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 {
+               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)
+       }
 }
 
 func writegdbscript(ctxt *Link, syms []*sym.Symbol) []*sym.Symbol {
@@ -1878,13 +1900,14 @@ func dwarfGenerateDebugSyms(ctxt *Link) {
        reversetree(&dwtypes.Child)
        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
-       // (but we need to generate dies before writepub)
-       infosyms := writeinfo(ctxt, nil, ctxt.compUnits, abbrev)
+       infosyms := writeinfo(ctxt, nil, ctxt.compUnits, abbrev, pubNames, pubTypes)
 
        syms = writeframes(ctxt, syms)
-       syms = writepub(ctxt, ".debug_pubnames", ispubname, syms)
-       syms = writepub(ctxt, ".debug_pubtypes", ispubtype, syms)
+       syms = append(syms, pubNames.s, pubTypes.s)
        syms = writegdbscript(ctxt, syms)
        // Now we're done writing SDWARFSECT symbols, so we can write
        // other SDWARF* symbols.