diff options
-rw-r--r-- | src/cmd/compile/internal/gc/main.go | 2 | ||||
-rw-r--r-- | src/cmd/compile/internal/gc/obj.go | 1 | ||||
-rw-r--r-- | src/cmd/internal/dwarf/dwarf.go | 9 | ||||
-rw-r--r-- | src/cmd/internal/obj/dwarf.go | 25 | ||||
-rw-r--r-- | src/cmd/link/internal/ld/dwarf.go | 58 | ||||
-rw-r--r-- | src/cmd/link/internal/sym/compilation_unit.go | 1 |
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 |