Skip to content

Commit c819907

Browse files
committed
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>
1 parent 1c9e587 commit c819907

File tree

6 files changed

+60
-36
lines changed

6 files changed

+60
-36
lines changed

src/cmd/compile/internal/gc/main.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ func Main(archInit func(*ssagen.ArchInfo)) {
105105
// Record flags that affect the build result. (And don't
106106
// record flags that don't, since that would cause spurious
107107
// changes in the binary.)
108-
dwarfgen.RecordFlags("B", "N", "l", "msan", "race", "shared", "dynlink", "dwarflocationlists", "dwarfbasentries", "smallframes", "spectre")
108+
dwarfgen.RecordFlags("B", "N", "l", "msan", "race", "shared", "dynlink", "dwarf", "dwarflocationlists", "dwarfbasentries", "smallframes", "spectre")
109109

110110
if !base.EnableTrace && base.Flag.LowerT {
111111
log.Fatalf("compiler not built with support for -t")

src/cmd/compile/internal/gc/obj.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,7 @@ func dumpGlobal(n *ir.Name) {
195195
}
196196
types.CalcSize(n.Type())
197197
ggloblnod(n)
198+
base.Ctxt.DwarfGlobal(base.Ctxt.Pkgpath, types.TypeSymName(n.Type()), n.Linksym())
198199
}
199200

200201
func dumpGlobalConst(n ir.Node) {

src/cmd/internal/dwarf/dwarf.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1041,6 +1041,15 @@ func PutIntConst(ctxt Context, info, typ Sym, name string, val int64) {
10411041
putattr(ctxt, info, DW_ABRV_INT_CONSTANT, DW_FORM_sdata, DW_CLS_CONSTANT, val, nil)
10421042
}
10431043

1044+
// PutGlobal writes a DIE for a global variable.
1045+
func PutGlobal(ctxt Context, info, typ, gvar Sym, name string) {
1046+
Uleb128put(ctxt, info, DW_ABRV_VARIABLE)
1047+
putattr(ctxt, info, DW_ABRV_VARIABLE, DW_FORM_string, DW_CLS_STRING, int64(len(name)), name)
1048+
putattr(ctxt, info, DW_ABRV_VARIABLE, DW_FORM_block1, DW_CLS_ADDRESS, 0, gvar)
1049+
putattr(ctxt, info, DW_ABRV_VARIABLE, DW_FORM_ref_addr, DW_CLS_REFERENCE, 0, typ)
1050+
putattr(ctxt, info, DW_ABRV_VARIABLE, DW_FORM_flag, DW_CLS_FLAG, 1, nil)
1051+
}
1052+
10441053
// PutBasedRanges writes a range table to sym. All addresses in ranges are
10451054
// relative to some base address, which must be arranged by the caller
10461055
// (e.g., with a DW_AT_low_pc attribute, or in a BASE-prefixed range).

src/cmd/internal/obj/dwarf.go

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -402,6 +402,31 @@ func (ctxt *Link) DwarfIntConst(myimportpath, name, typename string, val int64)
402402
dwarf.PutIntConst(dwCtxt{ctxt}, s, ctxt.Lookup(dwarf.InfoPrefix+typename), myimportpath+"."+name, val)
403403
}
404404

405+
// DwarfGlobal creates a link symbol containing a DWARF entry for
406+
// a global variable.
407+
func (ctxt *Link) DwarfGlobal(myimportpath, typename string, varSym *LSym) {
408+
if myimportpath == "" || varSym.Local() {
409+
return
410+
}
411+
var varname string
412+
if varSym.Pkg == "_" {
413+
// The frontend uses package "_" to mark symbols that should not
414+
// be referenced by index, e.g. linkname'd symbols.
415+
varname = varSym.Name
416+
} else {
417+
// Convert "".<name> into a fully qualified package.sym name.
418+
varname = objabi.PathToPrefix(myimportpath) + varSym.Name[len(`""`):]
419+
}
420+
dieSymName := dwarf.InfoPrefix + varname
421+
dieSym := ctxt.LookupInit(dieSymName, func(s *LSym) {
422+
s.Type = objabi.SDWARFVAR
423+
s.Set(AttrDuplicateOK, true) // needed for shared linkage
424+
ctxt.Data = append(ctxt.Data, s)
425+
})
426+
typeSym := ctxt.Lookup(dwarf.InfoPrefix + typename)
427+
dwarf.PutGlobal(dwCtxt{ctxt}, dieSym, typeSym, varSym, varname)
428+
}
429+
405430
func (ctxt *Link) DwarfAbstractFunc(curfn interface{}, s *LSym, myimportpath string) {
406431
absfn := ctxt.DwFixups.AbsFuncDwarfSym(s)
407432
if absfn.Size != 0 {

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

Lines changed: 23 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -458,12 +458,6 @@ func newmemberoffsetattr(die *dwarf.DWDie, offs int32) {
458458
newattr(die, dwarf.DW_AT_data_member_location, dwarf.DW_CLS_CONSTANT, int64(offs), nil)
459459
}
460460

461-
// GDB doesn't like FORM_addr for AT_location, so emit a
462-
// location expression that evals to a const.
463-
func (d *dwctxt) newabslocexprattr(die *dwarf.DWDie, addr int64, symIdx loader.Sym) {
464-
newattr(die, dwarf.DW_AT_location, dwarf.DW_CLS_ADDRESS, addr, dwSym(symIdx))
465-
}
466-
467461
func (d *dwctxt) lookupOrDiag(n string) loader.Sym {
468462
symIdx := d.ldr.Lookup(n, 0)
469463
if symIdx == 0 {
@@ -1020,25 +1014,6 @@ func (d *dwctxt) synthesizechantypes(ctxt *Link, die *dwarf.DWDie) {
10201014
}
10211015
}
10221016

1023-
func (d *dwctxt) dwarfDefineGlobal(ctxt *Link, symIdx loader.Sym, str string, v int64, gotype loader.Sym) {
1024-
// Find a suitable CU DIE to include the global.
1025-
// One would think it's as simple as just looking at the unit, but that might
1026-
// not have any reachable code. So, we go to the runtime's CU if our unit
1027-
// isn't otherwise reachable.
1028-
unit := d.ldr.SymUnit(symIdx)
1029-
if unit == nil {
1030-
unit = ctxt.runtimeCU
1031-
}
1032-
ver := d.ldr.SymVersion(symIdx)
1033-
dv := d.newdie(unit.DWInfo, dwarf.DW_ABRV_VARIABLE, str, int(ver))
1034-
d.newabslocexprattr(dv, v, symIdx)
1035-
if d.ldr.SymVersion(symIdx) < sym.SymVerStatic {
1036-
newattr(dv, dwarf.DW_AT_external, dwarf.DW_CLS_FLAG, 1, 0)
1037-
}
1038-
dt := d.defgotype(gotype)
1039-
d.newrefattr(dv, dwarf.DW_AT_type, dt)
1040-
}
1041-
10421017
// createUnitLength creates the initial length field with value v and update
10431018
// offset of unit_length if needed.
10441019
func (d *dwctxt) createUnitLength(su *loader.SymbolBuilder, v uint64) {
@@ -1552,7 +1527,7 @@ func appendSyms(syms []loader.Sym, src []sym.LoaderSym) []loader.Sym {
15521527

15531528
func (d *dwctxt) writeUnitInfo(u *sym.CompilationUnit, abbrevsym loader.Sym, infoEpilog loader.Sym) []loader.Sym {
15541529
syms := []loader.Sym{}
1555-
if len(u.Textp) == 0 && u.DWInfo.Child == nil {
1530+
if len(u.Textp) == 0 && u.DWInfo.Child == nil && len(u.VarDIEs) == 0 {
15561531
return syms
15571532
}
15581533

@@ -1583,6 +1558,7 @@ func (d *dwctxt) writeUnitInfo(u *sym.CompilationUnit, abbrevsym loader.Sym, inf
15831558
if u.Consts != 0 {
15841559
cu = append(cu, loader.Sym(u.Consts))
15851560
}
1561+
cu = appendSyms(cu, u.VarDIEs)
15861562
var cusize int64
15871563
for _, child := range cu {
15881564
cusize += int64(len(d.ldr.Data(child)))
@@ -1907,10 +1883,11 @@ func dwarfGenerateDebugInfo(ctxt *Link) {
19071883
checkStrictDups = 1
19081884
}
19091885

1910-
// Create DIEs for global variables and the types they use.
1911-
// FIXME: ideally this should be done in the compiler, since
1912-
// for globals there isn't any abiguity about which package
1913-
// a global belongs to.
1886+
// Make a pass through all data symbols, looking for those
1887+
// corresponding to reachable, Go-generated, user-visible
1888+
// global variables. For each global of this sort, locate
1889+
// the corresponding compiler-generated DIE symbol and tack
1890+
// it onto the list associated with the unit.
19141891
for idx := loader.Sym(1); idx < loader.Sym(d.ldr.NDef()); idx++ {
19151892
if !d.ldr.AttrReachable(idx) ||
19161893
d.ldr.AttrNotInSymbolTable(idx) ||
@@ -1925,7 +1902,8 @@ func dwarfGenerateDebugInfo(ctxt *Link) {
19251902
continue
19261903
}
19271904
// Skip things with no type
1928-
if d.ldr.SymGoType(idx) == 0 {
1905+
gt := d.ldr.SymGoType(idx)
1906+
if gt == 0 {
19291907
continue
19301908
}
19311909
// Skip file local symbols (this includes static tmps, stack
@@ -1939,10 +1917,20 @@ func dwarfGenerateDebugInfo(ctxt *Link) {
19391917
continue
19401918
}
19411919

1942-
// Create DIE for global.
1943-
sv := d.ldr.SymValue(idx)
1944-
gt := d.ldr.SymGoType(idx)
1945-
d.dwarfDefineGlobal(ctxt, idx, sn, sv, gt)
1920+
// Find compiler-generated DWARF info sym for global in question,
1921+
// and tack it onto the appropriate unit. Note that there are
1922+
// circumstances under which we can't find the compiler-generated
1923+
// symbol-- this typically happens as a result of compiler options
1924+
// (e.g. compile package X with "-dwarf=0").
1925+
1926+
// FIXME: use an aux sym or a relocation here instead of a
1927+
// name lookup.
1928+
varDIE := d.ldr.Lookup(dwarf.InfoPrefix+sn, 0)
1929+
if varDIE != 0 {
1930+
unit := d.ldr.SymUnit(idx)
1931+
d.defgotype(gt)
1932+
unit.VarDIEs = append(unit.VarDIEs, sym.LoaderSym(varDIE))
1933+
}
19461934
}
19471935

19481936
d.synthesizestringtypes(ctxt, dwtypes.Child)

src/cmd/link/internal/sym/compilation_unit.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ type CompilationUnit struct {
2929

3030
Consts LoaderSym // Package constants DIEs
3131
FuncDIEs []LoaderSym // Function DIE subtrees
32+
VarDIEs []LoaderSym // Global variable DIEs
3233
AbsFnDIEs []LoaderSym // Abstract function DIE subtrees
3334
RangeSyms []LoaderSym // Symbols for debug_range
3435
Textp []LoaderSym // Text symbols in this CU

0 commit comments

Comments
 (0)