mirror of
https://github.com/golang/go
synced 2024-11-26 04:58:00 -07:00
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>
This commit is contained in:
parent
1c9e587b90
commit
c819907754
@ -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")
|
||||
|
@ -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) {
|
||||
|
@ -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).
|
||||
|
@ -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 {
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user