]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/{compile,link}: relocate generation of DWARF for global vars
authorThan McIntosh <thanm@google.com>
Thu, 7 Jan 2021 21:25:41 +0000 (16:25 -0500)
committerThan McIntosh <thanm@google.com>
Tue, 23 Mar 2021 00:29:52 +0000 (00:29 +0000)
Move DWARF generation for global variables from the linker to the
compiler. This effectively parallelizes this part of DWARF generation,
speeds up the linker minutely, and gives us a slightly more rational
implementation (there was really no compelling reason to do DWARF gen
for globals in the linker).

Change-Id: I0c1c98d3a647258697e90eb91d1d8a9f6f7f376a
Reviewed-on: https://go-review.googlesource.com/c/go/+/295011
Trust: Than McIntosh <thanm@google.com>
Run-TryBot: Than McIntosh <thanm@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: David Chase <drchase@google.com>
Reviewed-by: Jeremy Faller <jeremy@golang.org>
src/cmd/compile/internal/gc/main.go
src/cmd/compile/internal/gc/obj.go
src/cmd/internal/dwarf/dwarf.go
src/cmd/internal/obj/dwarf.go
src/cmd/link/internal/ld/dwarf.go
src/cmd/link/internal/sym/compilation_unit.go

index 726a0685d57fff33053395c97eb176bd730e0267..c46989edb497e26c246a6429ca60117864036564 100644 (file)
@@ -105,7 +105,7 @@ func Main(archInit func(*ssagen.ArchInfo)) {
        // Record flags that affect the build result. (And don't
        // record flags that don't, since that would cause spurious
        // changes in the binary.)
-       dwarfgen.RecordFlags("B", "N", "l", "msan", "race", "shared", "dynlink", "dwarflocationlists", "dwarfbasentries", "smallframes", "spectre")
+       dwarfgen.RecordFlags("B", "N", "l", "msan", "race", "shared", "dynlink", "dwarf", "dwarflocationlists", "dwarfbasentries", "smallframes", "spectre")
 
        if !base.EnableTrace && base.Flag.LowerT {
                log.Fatalf("compiler not built with support for -t")
index 0472af74419e57975f3cabf26e9ed3acef776837..d18011a9e58b4a1edae013e0815bd9be5db59ace 100644 (file)
@@ -195,6 +195,7 @@ func dumpGlobal(n *ir.Name) {
        }
        types.CalcSize(n.Type())
        ggloblnod(n)
+       base.Ctxt.DwarfGlobal(base.Ctxt.Pkgpath, types.TypeSymName(n.Type()), n.Linksym())
 }
 
 func dumpGlobalConst(n ir.Node) {
index 70d792fec66c736dd2b72a85abec1e5d002558fd..c48e1723c8da558f7978d7b94b012239d3adf718 100644 (file)
@@ -1041,6 +1041,15 @@ func PutIntConst(ctxt Context, info, typ Sym, name string, val int64) {
        putattr(ctxt, info, DW_ABRV_INT_CONSTANT, DW_FORM_sdata, DW_CLS_CONSTANT, val, nil)
 }
 
+// PutGlobal writes a DIE for a global variable.
+func PutGlobal(ctxt Context, info, typ, gvar Sym, name string) {
+       Uleb128put(ctxt, info, DW_ABRV_VARIABLE)
+       putattr(ctxt, info, DW_ABRV_VARIABLE, DW_FORM_string, DW_CLS_STRING, int64(len(name)), name)
+       putattr(ctxt, info, DW_ABRV_VARIABLE, DW_FORM_block1, DW_CLS_ADDRESS, 0, gvar)
+       putattr(ctxt, info, DW_ABRV_VARIABLE, DW_FORM_ref_addr, DW_CLS_REFERENCE, 0, typ)
+       putattr(ctxt, info, DW_ABRV_VARIABLE, DW_FORM_flag, DW_CLS_FLAG, 1, nil)
+}
+
 // PutBasedRanges writes a range table to sym. All addresses in ranges are
 // relative to some base address, which must be arranged by the caller
 // (e.g., with a DW_AT_low_pc attribute, or in a BASE-prefixed range).
index 87c62e298165cb9ff640237013d1e929bdffb545..6dd53ffd1215e839b91d8657101e4a44ee9648c7 100644 (file)
@@ -402,6 +402,31 @@ func (ctxt *Link) DwarfIntConst(myimportpath, name, typename string, val int64)
        dwarf.PutIntConst(dwCtxt{ctxt}, s, ctxt.Lookup(dwarf.InfoPrefix+typename), myimportpath+"."+name, val)
 }
 
+// DwarfGlobal creates a link symbol containing a DWARF entry for
+// a global variable.
+func (ctxt *Link) DwarfGlobal(myimportpath, typename string, varSym *LSym) {
+       if myimportpath == "" || varSym.Local() {
+               return
+       }
+       var varname string
+       if varSym.Pkg == "_" {
+               // The frontend uses package "_" to mark symbols that should not
+               // be referenced by index, e.g. linkname'd symbols.
+               varname = varSym.Name
+       } else {
+               // Convert "".<name> into a fully qualified package.sym name.
+               varname = objabi.PathToPrefix(myimportpath) + varSym.Name[len(`""`):]
+       }
+       dieSymName := dwarf.InfoPrefix + varname
+       dieSym := ctxt.LookupInit(dieSymName, func(s *LSym) {
+               s.Type = objabi.SDWARFVAR
+               s.Set(AttrDuplicateOK, true) // needed for shared linkage
+               ctxt.Data = append(ctxt.Data, s)
+       })
+       typeSym := ctxt.Lookup(dwarf.InfoPrefix + typename)
+       dwarf.PutGlobal(dwCtxt{ctxt}, dieSym, typeSym, varSym, varname)
+}
+
 func (ctxt *Link) DwarfAbstractFunc(curfn interface{}, s *LSym, myimportpath string) {
        absfn := ctxt.DwFixups.AbsFuncDwarfSym(s)
        if absfn.Size != 0 {
index 561f6f1475994c6117d57a9772231a2eb494d443..3c3f0e5b856e9cd2617532771e78f14552513d12 100644 (file)
@@ -458,12 +458,6 @@ func newmemberoffsetattr(die *dwarf.DWDie, offs int32) {
        newattr(die, dwarf.DW_AT_data_member_location, dwarf.DW_CLS_CONSTANT, int64(offs), nil)
 }
 
-// GDB doesn't like FORM_addr for AT_location, so emit a
-// location expression that evals to a const.
-func (d *dwctxt) newabslocexprattr(die *dwarf.DWDie, addr int64, symIdx loader.Sym) {
-       newattr(die, dwarf.DW_AT_location, dwarf.DW_CLS_ADDRESS, addr, dwSym(symIdx))
-}
-
 func (d *dwctxt) lookupOrDiag(n string) loader.Sym {
        symIdx := d.ldr.Lookup(n, 0)
        if symIdx == 0 {
@@ -1020,25 +1014,6 @@ func (d *dwctxt) synthesizechantypes(ctxt *Link, die *dwarf.DWDie) {
        }
 }
 
-func (d *dwctxt) dwarfDefineGlobal(ctxt *Link, symIdx loader.Sym, str string, v int64, gotype loader.Sym) {
-       // Find a suitable CU DIE to include the global.
-       // One would think it's as simple as just looking at the unit, but that might
-       // not have any reachable code. So, we go to the runtime's CU if our unit
-       // isn't otherwise reachable.
-       unit := d.ldr.SymUnit(symIdx)
-       if unit == nil {
-               unit = ctxt.runtimeCU
-       }
-       ver := d.ldr.SymVersion(symIdx)
-       dv := d.newdie(unit.DWInfo, dwarf.DW_ABRV_VARIABLE, str, int(ver))
-       d.newabslocexprattr(dv, v, symIdx)
-       if d.ldr.SymVersion(symIdx) < sym.SymVerStatic {
-               newattr(dv, dwarf.DW_AT_external, dwarf.DW_CLS_FLAG, 1, 0)
-       }
-       dt := d.defgotype(gotype)
-       d.newrefattr(dv, dwarf.DW_AT_type, dt)
-}
-
 // createUnitLength creates the initial length field with value v and update
 // offset of unit_length if needed.
 func (d *dwctxt) createUnitLength(su *loader.SymbolBuilder, v uint64) {
@@ -1552,7 +1527,7 @@ func appendSyms(syms []loader.Sym, src []sym.LoaderSym) []loader.Sym {
 
 func (d *dwctxt) writeUnitInfo(u *sym.CompilationUnit, abbrevsym loader.Sym, infoEpilog loader.Sym) []loader.Sym {
        syms := []loader.Sym{}
-       if len(u.Textp) == 0 && u.DWInfo.Child == nil {
+       if len(u.Textp) == 0 && u.DWInfo.Child == nil && len(u.VarDIEs) == 0 {
                return syms
        }
 
@@ -1583,6 +1558,7 @@ func (d *dwctxt) writeUnitInfo(u *sym.CompilationUnit, abbrevsym loader.Sym, inf
        if u.Consts != 0 {
                cu = append(cu, loader.Sym(u.Consts))
        }
+       cu = appendSyms(cu, u.VarDIEs)
        var cusize int64
        for _, child := range cu {
                cusize += int64(len(d.ldr.Data(child)))
@@ -1907,10 +1883,11 @@ func dwarfGenerateDebugInfo(ctxt *Link) {
                checkStrictDups = 1
        }
 
-       // Create DIEs for global variables and the types they use.
-       // FIXME: ideally this should be done in the compiler, since
-       // for globals there isn't any abiguity about which package
-       // a global belongs to.
+       // Make a pass through all data symbols, looking for those
+       // corresponding to reachable, Go-generated, user-visible
+       // global variables. For each global of this sort, locate
+       // the corresponding compiler-generated DIE symbol and tack
+       // it onto the list associated with the unit.
        for idx := loader.Sym(1); idx < loader.Sym(d.ldr.NDef()); idx++ {
                if !d.ldr.AttrReachable(idx) ||
                        d.ldr.AttrNotInSymbolTable(idx) ||
@@ -1925,7 +1902,8 @@ func dwarfGenerateDebugInfo(ctxt *Link) {
                        continue
                }
                // Skip things with no type
-               if d.ldr.SymGoType(idx) == 0 {
+               gt := d.ldr.SymGoType(idx)
+               if gt == 0 {
                        continue
                }
                // Skip file local symbols (this includes static tmps, stack
@@ -1939,10 +1917,20 @@ func dwarfGenerateDebugInfo(ctxt *Link) {
                        continue
                }
 
-               // Create DIE for global.
-               sv := d.ldr.SymValue(idx)
-               gt := d.ldr.SymGoType(idx)
-               d.dwarfDefineGlobal(ctxt, idx, sn, sv, gt)
+               // Find compiler-generated DWARF info sym for global in question,
+               // and tack it onto the appropriate unit.  Note that there are
+               // circumstances under which we can't find the compiler-generated
+               // symbol-- this typically happens as a result of compiler options
+               // (e.g. compile package X with "-dwarf=0").
+
+               // FIXME: use an aux sym or a relocation here instead of a
+               // name lookup.
+               varDIE := d.ldr.Lookup(dwarf.InfoPrefix+sn, 0)
+               if varDIE != 0 {
+                       unit := d.ldr.SymUnit(idx)
+                       d.defgotype(gt)
+                       unit.VarDIEs = append(unit.VarDIEs, sym.LoaderSym(varDIE))
+               }
        }
 
        d.synthesizestringtypes(ctxt, dwtypes.Child)
index 5d7206db66e27b80ffe1c5a9944a9b954aaeeca4..926cbc3d20e8972bc9d12931bdb98ae64d7c0a71 100644 (file)
@@ -29,6 +29,7 @@ type CompilationUnit struct {
 
        Consts    LoaderSym   // Package constants DIEs
        FuncDIEs  []LoaderSym // Function DIE subtrees
+       VarDIEs   []LoaderSym // Global variable DIEs
        AbsFnDIEs []LoaderSym // Abstract function DIE subtrees
        RangeSyms []LoaderSym // Symbols for debug_range
        Textp     []LoaderSym // Text symbols in this CU