aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThan McIntosh <thanm@google.com>2021-01-07 16:25:41 -0500
committerThan McIntosh <thanm@google.com>2021-03-23 00:29:52 +0000
commitc819907754a30229da197546a36eb4a160e5908f (patch)
treef07153fbc70bd20bed4a1b9a6dfbe51bc1b3004d
parent1c9e587b90172e7654db897d8c938ffc665e1673 (diff)
downloadgo-c819907754a30229da197546a36eb4a160e5908f.tar.gz
go-c819907754a30229da197546a36eb4a160e5908f.zip
cmd/{compile,link}: relocate generation of DWARF for global vars
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>
-rw-r--r--src/cmd/compile/internal/gc/main.go2
-rw-r--r--src/cmd/compile/internal/gc/obj.go1
-rw-r--r--src/cmd/internal/dwarf/dwarf.go9
-rw-r--r--src/cmd/internal/obj/dwarf.go25
-rw-r--r--src/cmd/link/internal/ld/dwarf.go58
-rw-r--r--src/cmd/link/internal/sym/compilation_unit.go1
6 files changed, 60 insertions, 36 deletions
diff --git a/src/cmd/compile/internal/gc/main.go b/src/cmd/compile/internal/gc/main.go
index 726a0685d5..c46989edb4 100644
--- a/src/cmd/compile/internal/gc/main.go
+++ b/src/cmd/compile/internal/gc/main.go
@@ -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")
diff --git a/src/cmd/compile/internal/gc/obj.go b/src/cmd/compile/internal/gc/obj.go
index 0472af7441..d18011a9e5 100644
--- a/src/cmd/compile/internal/gc/obj.go
+++ b/src/cmd/compile/internal/gc/obj.go
@@ -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) {
diff --git a/src/cmd/internal/dwarf/dwarf.go b/src/cmd/internal/dwarf/dwarf.go
index 70d792fec6..c48e1723c8 100644
--- a/src/cmd/internal/dwarf/dwarf.go
+++ b/src/cmd/internal/dwarf/dwarf.go
@@ -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).
diff --git a/src/cmd/internal/obj/dwarf.go b/src/cmd/internal/obj/dwarf.go
index 87c62e2981..6dd53ffd12 100644
--- a/src/cmd/internal/obj/dwarf.go
+++ b/src/cmd/internal/obj/dwarf.go
@@ -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 {
diff --git a/src/cmd/link/internal/ld/dwarf.go b/src/cmd/link/internal/ld/dwarf.go
index 561f6f1475..3c3f0e5b85 100644
--- a/src/cmd/link/internal/ld/dwarf.go
+++ b/src/cmd/link/internal/ld/dwarf.go
@@ -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)
diff --git a/src/cmd/link/internal/sym/compilation_unit.go b/src/cmd/link/internal/sym/compilation_unit.go
index 5d7206db66..926cbc3d20 100644
--- a/src/cmd/link/internal/sym/compilation_unit.go
+++ b/src/cmd/link/internal/sym/compilation_unit.go
@@ -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