]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/link: generate PC ranges for compilation unit DIEs
authorAustin Clements <austin@google.com>
Tue, 10 Oct 2017 20:19:49 +0000 (16:19 -0400)
committerAustin Clements <austin@google.com>
Thu, 12 Oct 2017 18:56:26 +0000 (18:56 +0000)
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 <austin@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Than McIntosh <thanm@google.com>
src/cmd/internal/dwarf/dwarf.go
src/cmd/link/internal/ld/dwarf.go

index c95fa92e2feb70d5f8d0edb6d32de41e726a4ee2..f840828b6217160130385681027fe8d03ecb26bc 100644 (file)
@@ -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)
index c7c32ca41f99cd81d137e363235a1508c366c4f6..41f20e27ee1f5b55e77f5b87d57904231d6ee67a 100644 (file)
@@ -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
 }