1
0
mirror of https://github.com/golang/go synced 2024-11-07 08:56:15 -07:00

[dev.link] cmd/internal/obj, cmd/link: use aux symbol for DWARF symbols

Use the auxiliary symbol mechanism to connect the text symbol and
its associated DWARF symbols. This way, the linker can track the
DWARF symbols from the text symbol, without looking up special
names.

Currently, in the linker this is only used in the deadcode pass
to track which DWARF symbols are used and need to load. Later
passes still use name lookup for now.

Change-Id: I2fe49f3b1f0ecc1472ae8aa93907cff740022d8d
Reviewed-on: https://go-review.googlesource.com/c/go/+/199801
Run-TryBot: Cherry Zhang <cherryyz@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Than McIntosh <thanm@google.com>
This commit is contained in:
Cherry Zhang 2019-10-07 21:10:41 -04:00
parent cab29ebd84
commit 27111e5fec
5 changed files with 74 additions and 13 deletions

View File

@ -125,6 +125,8 @@ func (r *objReader) readNew() {
isym = int(a.Sym.SymIdx) isym = int(a.Sym.SymIdx)
case goobj2.AuxFuncdata: case goobj2.AuxFuncdata:
funcdata = append(funcdata, a.Sym) funcdata = append(funcdata, a.Sym)
case goobj2.AuxDwarfInfo, goobj2.AuxDwarfLoc, goobj2.AuxDwarfRanges, goobj2.AuxDwarfLines:
// nothing to do
default: default:
panic("unknown aux type") panic("unknown aux type")
} }

View File

@ -280,8 +280,12 @@ const (
AuxGotype = iota AuxGotype = iota
AuxFuncInfo AuxFuncInfo
AuxFuncdata AuxFuncdata
AuxDwarfInfo
AuxDwarfLoc
AuxDwarfRanges
AuxDwarfLines
// TODO: more. DWARF? Pcdata? // TODO: more. Pcdata?
) )
func (a *Aux) Write(w *Writer) { func (a *Aux) Write(w *Writer) {

View File

@ -95,13 +95,7 @@ func WriteObjFile2(ctxt *Link, b *bio.Writer, pkgpath string) {
for _, list := range lists { for _, list := range lists {
for _, s := range list { for _, s := range list {
w.Uint32(naux) w.Uint32(naux)
if s.Gotype != nil { naux += uint32(nAuxSym(s))
naux++
}
if s.Func != nil {
// FuncInfo is an aux symbol, each Funcdata is an aux symbol
naux += 1 + uint32(len(s.Func.Pcln.Funcdata))
}
} }
} }
w.Uint32(naux) w.Uint32(naux)
@ -301,9 +295,63 @@ func (w *writer) Aux(s *LSym) {
} }
o.Write(w.Writer) o.Write(w.Writer)
} }
if s.Func.dwarfInfoSym != nil {
o := goobj2.Aux{
Type: goobj2.AuxDwarfInfo,
Sym: makeSymRef(s.Func.dwarfInfoSym),
}
o.Write(w.Writer)
}
if s.Func.dwarfLocSym != nil {
o := goobj2.Aux{
Type: goobj2.AuxDwarfLoc,
Sym: makeSymRef(s.Func.dwarfLocSym),
}
o.Write(w.Writer)
}
if s.Func.dwarfRangesSym != nil {
o := goobj2.Aux{
Type: goobj2.AuxDwarfRanges,
Sym: makeSymRef(s.Func.dwarfRangesSym),
}
o.Write(w.Writer)
}
if s.Func.dwarfDebugLinesSym != nil {
o := goobj2.Aux{
Type: goobj2.AuxDwarfLines,
Sym: makeSymRef(s.Func.dwarfDebugLinesSym),
}
o.Write(w.Writer)
}
} }
} }
// return the number of aux symbols s have.
func nAuxSym(s *LSym) int {
n := 0
if s.Gotype != nil {
n++
}
if s.Func != nil {
// FuncInfo is an aux symbol, each Funcdata is an aux symbol
n += 1 + len(s.Func.Pcln.Funcdata)
if s.Func.dwarfInfoSym != nil {
n++
}
if s.Func.dwarfLocSym != nil {
n++
}
if s.Func.dwarfRangesSym != nil {
n++
}
if s.Func.dwarfDebugLinesSym != nil {
n++
}
}
return n
}
// generate symbols for FuncInfo. // generate symbols for FuncInfo.
func genFuncInfoSyms(ctxt *Link) { func genFuncInfoSyms(ctxt *Link) {
infosyms := make([]*LSym, 0, len(ctxt.Text)) infosyms := make([]*LSym, 0, len(ctxt.Text))

View File

@ -126,6 +126,12 @@ func (d *deadcodePass2) flood() {
i += 2 i += 2
continue continue
} }
if r.Type == objabi.R_USETYPE {
// type symbol used for DWARF. we need to load the symbol but it may not
// be otherwise reachable in the program.
// do nothing for now as we still load all type symbols.
continue
}
d.mark(r.Sym) d.mark(r.Sym)
} }
naux := d.loader.NAux(symIdx) naux := d.loader.NAux(symIdx)

View File

@ -462,10 +462,10 @@ func LoadFull(l *Loader, arch *sys.Arch, syms *sym.Symbols) {
// external symbols // external symbols
for i := l.extStart; i <= l.max; i++ { for i := l.extStart; i <= l.max; i++ {
nv := l.extSyms[i-l.extStart] nv := l.extSyms[i-l.extStart]
if l.Reachable.Has(i) || strings.HasPrefix(nv.name, "go.info.") || strings.HasPrefix(nv.name, "gofile..") { // XXX some go.info and file symbols are used but not marked if l.Reachable.Has(i) || strings.HasPrefix(nv.name, "gofile..") { // XXX file symbols are used but not marked
s := syms.Newsym(nv.name, nv.v) s := syms.Newsym(nv.name, nv.v)
preprocess(arch, s) preprocess(arch, s)
s.Attr.Set(sym.AttrReachable, true) s.Attr.Set(sym.AttrReachable, l.Reachable.Has(i))
l.Syms[i] = s l.Syms[i] = s
} }
} }
@ -499,10 +499,9 @@ func loadObjSyms(l *Loader, syms *sym.Symbols, r *oReader) {
if t == 0 { if t == 0 {
log.Fatalf("missing type for %s in %s", name, lib) log.Fatalf("missing type for %s in %s", name, lib)
} }
if !l.Reachable.Has(istart+Sym(i)) && (t < sym.SDWARFSECT || t > sym.SDWARFLINES) && !(t == sym.SRODATA && strings.HasPrefix(name, "type.")) && name != "runtime.addmoduledata" && name != "runtime.lastmoduledatap" { if !l.Reachable.Has(istart+Sym(i)) && !(t == sym.SRODATA && strings.HasPrefix(name, "type.")) && name != "runtime.addmoduledata" && name != "runtime.lastmoduledatap" {
// No need to load unreachable symbols. // No need to load unreachable symbols.
// XXX DWARF symbols may be used but are not marked reachable. // XXX some type symbol's content may be needed in DWARF code, but they are not marked.
// XXX type symbol's content may be needed in DWARF code, but they are not marked.
// XXX reference to runtime.addmoduledata may be generated later by the linker in plugin mode. // XXX reference to runtime.addmoduledata may be generated later by the linker in plugin mode.
continue continue
} }
@ -612,6 +611,8 @@ func loadObjFull(l *Loader, r *oReader) {
panic("funcinfo symbol not defined in current package") panic("funcinfo symbol not defined in current package")
} }
isym = int(a.Sym.SymIdx) isym = int(a.Sym.SymIdx)
case goobj2.AuxDwarfInfo, goobj2.AuxDwarfLoc, goobj2.AuxDwarfRanges, goobj2.AuxDwarfLines:
// ignored for now
default: default:
panic("unknown aux type") panic("unknown aux type")
} }