aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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