From: Austin Clements Date: Tue, 10 Oct 2017 20:19:49 +0000 (-0400) Subject: cmd/link: generate PC ranges for compilation unit DIEs X-Git-Tag: go1.10beta1~741 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=97920373fa07d4dbc24cbb587399586cf1e22961;p=gostls13.git cmd/link: generate PC ranges for compilation unit DIEs When we split separate packages into separate compilation units, we lost PC range information because it was no longer contiguous. This brings it back by constructing proper per-package PC range tables. Change-Id: Id0ab5187e08ac5d13b3d3794977bfc857a56224f Reviewed-on: https://go-review.googlesource.com/69974 Run-TryBot: Austin Clements TryBot-Result: Gobot Gobot Reviewed-by: Than McIntosh --- diff --git a/src/cmd/internal/dwarf/dwarf.go b/src/cmd/internal/dwarf/dwarf.go index c95fa92e2f..f840828b62 100644 --- a/src/cmd/internal/dwarf/dwarf.go +++ b/src/cmd/internal/dwarf/dwarf.go @@ -282,6 +282,8 @@ var abbrevs = [DW_NABRV]dwAbbrev{ {DW_AT_name, DW_FORM_string}, {DW_AT_language, DW_FORM_data1}, {DW_AT_stmt_list, DW_FORM_sec_offset}, + {DW_AT_low_pc, DW_FORM_addr}, + {DW_AT_ranges, DW_FORM_sec_offset}, {DW_AT_comp_dir, DW_FORM_string}, {DW_AT_producer, DW_FORM_string}, }, @@ -755,6 +757,28 @@ 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) } +// PutRanges writes a range table to sym. All addresses in ranges are +// relative to some base address. If base is not nil, then they're +// relative to the start of base. If base is nil, then the caller must +// arrange a base address some other way (such as a DW_AT_low_pc +// attribute). +func PutRanges(ctxt Context, sym Sym, base Sym, ranges []Range) { + ps := ctxt.PtrSize() + // Write base address entry. + if base != nil { + ctxt.AddInt(sym, ps, -1) + ctxt.AddAddress(sym, base, 0) + } + // Write ranges. + for _, r := range ranges { + ctxt.AddInt(sym, ps, r.Start) + ctxt.AddInt(sym, ps, r.End) + } + // Write trailer. + ctxt.AddInt(sym, ps, 0) + ctxt.AddInt(sym, ps, 0) +} + // PutFunc writes a DIE for a function to s. // It also writes child DIEs for each variable in vars. func PutFunc(ctxt Context, info, loc, ranges Sym, name string, external bool, startPC Sym, size int64, scopes []Scope) error { @@ -798,14 +822,7 @@ func putscope(ctxt Context, info, loc, ranges, startPC Sym, curscope int32, scop Uleb128put(ctxt, info, DW_ABRV_LEXICAL_BLOCK_RANGES) putattr(ctxt, info, DW_ABRV_LEXICAL_BLOCK_RANGES, DW_FORM_sec_offset, DW_CLS_PTR, ranges.Len(), ranges) - ctxt.AddAddress(ranges, nil, -1) - ctxt.AddAddress(ranges, startPC, 0) - for _, r := range scope.Ranges { - ctxt.AddAddress(ranges, nil, r.Start) - ctxt.AddAddress(ranges, nil, r.End) - } - ctxt.AddAddress(ranges, nil, 0) - ctxt.AddAddress(ranges, nil, 0) + PutRanges(ctxt, ranges, startPC, scope.Ranges) } curscope = putscope(ctxt, info, loc, ranges, startPC, curscope, scopes, encbuf) diff --git a/src/cmd/link/internal/ld/dwarf.go b/src/cmd/link/internal/ld/dwarf.go index c7c32ca41f..41f20e27ee 100644 --- a/src/cmd/link/internal/ld/dwarf.go +++ b/src/cmd/link/internal/ld/dwarf.go @@ -842,6 +842,7 @@ type compilationUnit struct { lib *sym.Library textp []*sym.Symbol // Function symbols in this package consts *sym.Symbol // Package constants DIEs + pcs []dwarf.Range // PC ranges, relative to textp[0] dwinfo *dwarf.DWDie // CU root DIE funcDIEs []*sym.Symbol // Function DIE subtrees } @@ -850,6 +851,7 @@ type compilationUnit struct { func getCompilationUnits(ctxt *Link) []*compilationUnit { units := []*compilationUnit{} index := make(map[*sym.Library]*compilationUnit) + var prevUnit *compilationUnit for _, s := range ctxt.Textp { if s.FuncInfo == nil { continue @@ -865,6 +867,19 @@ func getCompilationUnits(ctxt *Link) []*compilationUnit { index[s.Lib] = unit } unit.textp = append(unit.textp, s) + + // Update PC ranges. + // + // We don't simply compare the end of the previous + // symbol with the start of the next because there's + // often a little padding between them. Instead, we + // only create boundaries between symbols from + // different units. + if prevUnit != unit { + unit.pcs = append(unit.pcs, dwarf.Range{Start: s.Value - unit.textp[0].Value}) + prevUnit = unit + } + unit.pcs[len(unit.pcs)-1].End = s.Value - unit.textp[0].Value + s.Size } return units } @@ -1035,8 +1050,6 @@ func writelines(ctxt *Link, lib *sym.Library, textp []*sym.Symbol, ls *sym.Symbo lang := dwarf.DW_LANG_Go - // TODO: Generate DW_AT_ranges for dwinfo. - dwinfo = newdie(ctxt, &dwroot, dwarf.DW_ABRV_COMPUNIT, lib.Pkg, 0) newattr(dwinfo, dwarf.DW_AT_language, dwarf.DW_CLS_CONSTANT, int64(lang), 0) newattr(dwinfo, dwarf.DW_AT_stmt_list, dwarf.DW_CLS_PTR, ls.Size, ls) @@ -1164,6 +1177,16 @@ func writelines(ctxt *Link, lib *sym.Library, textp []*sym.Symbol, ls *sym.Symbo return dwinfo, funcs } +// writepcranges generates the DW_AT_ranges table for compilation unit cu. +func writepcranges(ctxt *Link, cu *dwarf.DWDie, base *sym.Symbol, pcs []dwarf.Range, ranges *sym.Symbol) { + var dwarfctxt dwarf.Context = dwctxt{ctxt} + + // Create PC ranges for this CU. + newattr(cu, dwarf.DW_AT_ranges, dwarf.DW_CLS_PTR, ranges.Size, ranges) + newattr(cu, dwarf.DW_AT_low_pc, dwarf.DW_CLS_ADDRESS, base.Value, base) + dwarf.PutRanges(dwarfctxt, ranges, nil, pcs) +} + /* * Emit .debug_frame */ @@ -1304,7 +1327,6 @@ func writeframes(ctxt *Link, syms []*sym.Symbol) []*sym.Symbol { } func writeranges(ctxt *Link, syms []*sym.Symbol) []*sym.Symbol { - empty := true for _, s := range ctxt.Textp { rangeSym := ctxt.Syms.ROLookup(dwarf.RangePrefix+s.Name, int(s.Version)) if rangeSym == nil || rangeSym.Size == 0 { @@ -1313,15 +1335,6 @@ func writeranges(ctxt *Link, syms []*sym.Symbol) []*sym.Symbol { rangeSym.Attr |= sym.AttrReachable | sym.AttrNotInSymbolTable rangeSym.Type = sym.SDWARFRANGE syms = append(syms, rangeSym) - empty = false - } - if !empty { - // PE does not like empty sections - rangesec := ctxt.Syms.Lookup(".debug_ranges", 0) - rangesec.Type = sym.SDWARFRANGE - rangesec.Attr |= sym.AttrReachable - - syms = append(syms, rangesec) } return syms } @@ -1545,12 +1558,16 @@ func dwarfgeneratedebugsyms(ctxt *Link) { units := getCompilationUnits(ctxt) - // Write per-package line tables and start their CU DIEs. + // Write per-package line and range tables and start their CU DIEs. debugLine := ctxt.Syms.Lookup(".debug_line", 0) debugLine.Type = sym.SDWARFSECT + debugRanges := ctxt.Syms.Lookup(".debug_ranges", 0) + debugRanges.Type = sym.SDWARFRANGE + debugRanges.Attr |= sym.AttrReachable syms = append(syms, debugLine) for _, u := range units { u.dwinfo, u.funcDIEs = writelines(ctxt, u.lib, u.textp, debugLine) + writepcranges(ctxt, u.dwinfo, u.textp[0], u.pcs, debugRanges) } synthesizestringtypes(ctxt, dwtypes.Child) @@ -1576,8 +1593,11 @@ func dwarfgeneratedebugsyms(ctxt *Link) { syms = writepub(ctxt, ".debug_pubnames", ispubname, syms) syms = writepub(ctxt, ".debug_pubtypes", ispubtype, syms) syms = writegdbscript(ctxt, syms) + // Now we're done writing SDWARFSECT symbols, so we can write + // other SDWARF* symbols. syms = append(syms, infosyms...) syms = collectlocs(ctxt, syms, units) + syms = append(syms, debugRanges) syms = writeranges(ctxt, syms) dwarfp = syms }