From: Cherry Mui Date: Tue, 28 Sep 2021 20:20:29 +0000 (-0400) Subject: cmd/link: access pcdata via aux symbols X-Git-Tag: go1.18beta1~1135 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=587b3c1192397393afb0ec5acd608e3dfe9f2116;p=gostls13.git cmd/link: access pcdata via aux symbols Pcdata are now separate aux symbols. Read them from aux, instead of using funcinfo. Now we can remove pcdata fields from funcinfo. Change-Id: Ie65e3962edecc0f39127a5f6963dc59d1f141e67 Reviewed-on: https://go-review.googlesource.com/c/go/+/352893 Trust: Cherry Mui Run-TryBot: Cherry Mui TryBot-Result: Go Bot Reviewed-by: Than McIntosh --- diff --git a/src/cmd/internal/goobj/funcinfo.go b/src/cmd/internal/goobj/funcinfo.go index 6d33a10a51..6e7970fb74 100644 --- a/src/cmd/internal/goobj/funcinfo.go +++ b/src/cmd/internal/goobj/funcinfo.go @@ -16,19 +16,12 @@ type CUFileIndex uint32 // FuncInfo is serialized as a symbol (aux symbol). The symbol data is // the binary encoding of the struct below. -// -// TODO: make each pcdata a separate symbol? type FuncInfo struct { Args uint32 Locals uint32 FuncID objabi.FuncID FuncFlag objabi.FuncFlag - Pcsp SymRef - Pcfile SymRef - Pcline SymRef - Pcinline SymRef - Pcdata []SymRef Funcdataoff []uint32 File []CUFileIndex @@ -44,10 +37,6 @@ func (a *FuncInfo) Write(w *bytes.Buffer) { binary.LittleEndian.PutUint32(b[:], x) w.Write(b[:]) } - writeSymRef := func(s SymRef) { - writeUint32(s.PkgIdx) - writeUint32(s.SymIdx) - } writeUint32(a.Args) writeUint32(a.Locals) @@ -55,14 +44,6 @@ func (a *FuncInfo) Write(w *bytes.Buffer) { writeUint8(uint8(a.FuncFlag)) writeUint8(0) // pad to uint32 boundary writeUint8(0) - writeSymRef(a.Pcsp) - writeSymRef(a.Pcfile) - writeSymRef(a.Pcline) - writeSymRef(a.Pcinline) - writeUint32(uint32(len(a.Pcdata))) - for _, sym := range a.Pcdata { - writeSymRef(sym) - } writeUint32(uint32(len(a.Funcdataoff))) for _, x := range a.Funcdataoff { @@ -84,8 +65,6 @@ func (a *FuncInfo) Write(w *bytes.Buffer) { // corresponding "off" field stores the byte offset of the start of // the items in question. type FuncInfoLengths struct { - NumPcdata uint32 - PcdataOff uint32 NumFuncdataoff uint32 FuncdataoffOff uint32 NumFile uint32 @@ -98,13 +77,9 @@ type FuncInfoLengths struct { func (*FuncInfo) ReadFuncInfoLengths(b []byte) FuncInfoLengths { var result FuncInfoLengths - // Offset to the number of pcdata values. This value is determined by counting - // the number of bytes until we write pcdata to the file. - const numpcdataOff = 44 - result.NumPcdata = binary.LittleEndian.Uint32(b[numpcdataOff:]) - result.PcdataOff = numpcdataOff + 4 - - numfuncdataoffOff := result.PcdataOff + 8*result.NumPcdata + // Offset to the number of funcdataoff values. This value is determined by counting + // the number of bytes until we write funcdataoff to the file. + const numfuncdataoffOff = 12 result.NumFuncdataoff = binary.LittleEndian.Uint32(b[numfuncdataoffOff:]) result.FuncdataoffOff = numfuncdataoffOff + 4 @@ -129,30 +104,6 @@ func (*FuncInfo) ReadFuncID(b []byte) objabi.FuncID { return objabi.FuncID(b[8]) func (*FuncInfo) ReadFuncFlag(b []byte) objabi.FuncFlag { return objabi.FuncFlag(b[9]) } -func (*FuncInfo) ReadPcsp(b []byte) SymRef { - return SymRef{binary.LittleEndian.Uint32(b[12:]), binary.LittleEndian.Uint32(b[16:])} -} - -func (*FuncInfo) ReadPcfile(b []byte) SymRef { - return SymRef{binary.LittleEndian.Uint32(b[20:]), binary.LittleEndian.Uint32(b[24:])} -} - -func (*FuncInfo) ReadPcline(b []byte) SymRef { - return SymRef{binary.LittleEndian.Uint32(b[28:]), binary.LittleEndian.Uint32(b[32:])} -} - -func (*FuncInfo) ReadPcinline(b []byte) SymRef { - return SymRef{binary.LittleEndian.Uint32(b[36:]), binary.LittleEndian.Uint32(b[40:])} -} - -func (*FuncInfo) ReadPcdata(b []byte) []SymRef { - syms := make([]SymRef, binary.LittleEndian.Uint32(b[44:])) - for i := range syms { - syms[i] = SymRef{binary.LittleEndian.Uint32(b[48+i*8:]), binary.LittleEndian.Uint32(b[52+i*8:])} - } - return syms -} - func (*FuncInfo) ReadFuncdataoff(b []byte, funcdataofffoff uint32, k uint32) int64 { return int64(binary.LittleEndian.Uint32(b[funcdataofffoff+4*k:])) } diff --git a/src/cmd/internal/obj/objfile.go b/src/cmd/internal/obj/objfile.go index 030a02b499..bed32198d7 100644 --- a/src/cmd/internal/obj/objfile.go +++ b/src/cmd/internal/obj/objfile.go @@ -671,14 +671,6 @@ func genFuncInfoSyms(ctxt *Link) { FuncFlag: fn.FuncFlag, } pc := &fn.Pcln - o.Pcsp = makeSymRef(pc.Pcsp) - o.Pcfile = makeSymRef(pc.Pcfile) - o.Pcline = makeSymRef(pc.Pcline) - o.Pcinline = makeSymRef(pc.Pcinline) - o.Pcdata = make([]goobj.SymRef, len(pc.Pcdata)) - for i, pcSym := range pc.Pcdata { - o.Pcdata[i] = makeSymRef(pcSym) - } o.Funcdataoff = make([]uint32, len(pc.Funcdataoff)) for i, x := range pc.Funcdataoff { o.Funcdataoff[i] = uint32(x) diff --git a/src/cmd/link/internal/ld/dwarf.go b/src/cmd/link/internal/ld/dwarf.go index d72846a691..47b4921cd8 100644 --- a/src/cmd/link/internal/ld/dwarf.go +++ b/src/cmd/link/internal/ld/dwarf.go @@ -1417,7 +1417,7 @@ func (d *dwctxt) writeframes(fs loader.Sym) dwarfSecInfo { if !fi.Valid() { continue } - fpcsp := fi.Pcsp() + fpcsp := d.ldr.Pcsp(s) // Emit a FDE, Section 6.4.1. // First build the section contents into a byte buffer. diff --git a/src/cmd/link/internal/ld/lib.go b/src/cmd/link/internal/ld/lib.go index feff16d0c0..5af20b4d18 100644 --- a/src/cmd/link/internal/ld/lib.go +++ b/src/cmd/link/internal/ld/lib.go @@ -2310,7 +2310,7 @@ func (sc *stkChk) check(up *chain, depth int) int { var ch1 chain pcsp := obj.NewPCIter(uint32(ctxt.Arch.MinLC)) ri := 0 - for pcsp.Init(ldr.Data(info.Pcsp())); !pcsp.Done; pcsp.Next() { + for pcsp.Init(ldr.Data(ldr.Pcsp(s))); !pcsp.Done; pcsp.Next() { // pcsp.value is in effect for [pcsp.pc, pcsp.nextpc). // Check stack size in effect for this span. diff --git a/src/cmd/link/internal/ld/pcln.go b/src/cmd/link/internal/ld/pcln.go index fede00586b..c8cd7bf09e 100644 --- a/src/cmd/link/internal/ld/pcln.go +++ b/src/cmd/link/internal/ld/pcln.go @@ -485,22 +485,25 @@ func (state *pclntab) generatePctab(ctxt *Link, funcs []loader.Sym) { seen[pcSym] = struct{}{} } } + var pcsp, pcline, pcfile, pcinline loader.Sym + var pcdata []loader.Sym for _, s := range funcs { fi := ldr.FuncInfo(s) if !fi.Valid() { continue } fi.Preload() + pcsp, pcfile, pcline, pcinline, pcdata = ldr.PcdataAuxs(s, pcdata) - pcSyms := []loader.Sym{fi.Pcsp(), fi.Pcfile(), fi.Pcline()} + pcSyms := []loader.Sym{pcsp, pcfile, pcline} for _, pcSym := range pcSyms { saveOffset(pcSym) } - for _, pcSym := range fi.Pcdata() { + for _, pcSym := range pcdata { saveOffset(pcSym) } if fi.NumInlTree() > 0 { - saveOffset(fi.Pcinline()) + saveOffset(pcinline) } } @@ -521,11 +524,11 @@ func (state *pclntab) generatePctab(ctxt *Link, funcs []loader.Sym) { // numPCData returns the number of PCData syms for the FuncInfo. // NB: Preload must be called on valid FuncInfos before calling this function. -func numPCData(fi loader.FuncInfo) uint32 { +func numPCData(ldr *loader.Loader, s loader.Sym, fi loader.FuncInfo) uint32 { if !fi.Valid() { return 0 } - numPCData := uint32(len(fi.Pcdata())) + numPCData := uint32(ldr.NumPcdata(s)) if fi.NumInlTree() > 0 { if numPCData < objabi.PCDATA_InlTreeIndex+1 { numPCData = objabi.PCDATA_InlTreeIndex + 1 @@ -676,7 +679,7 @@ func (state pclntab) calculateFunctabSize(ctxt *Link, funcs []loader.Sym) (int64 numFuncData = objabi.FUNCDATA_InlTree + 1 } } - size += int64(numPCData(fi) * 4) + size += int64(numPCData(ldr, s, fi) * 4) if numFuncData > 0 { // Func data is aligned. size = Rnd(size, int64(ctxt.Arch.PtrSize)) } @@ -747,7 +750,7 @@ func (state *pclntab) writeFuncData(ctxt *Link, sb *loader.SymbolBuilder, funcs // Missing funcdata will be 0 (nil pointer). funcdata, funcdataoff := funcData(fi, inlSyms[s], funcdata, funcdataoff) if len(funcdata) > 0 { - off := int64(startLocations[i] + state.funcSize + numPCData(fi)*4) + off := int64(startLocations[i] + state.funcSize + numPCData(ldr, s, fi)*4) off = Rnd(off, int64(ctxt.Arch.PtrSize)) for j := range funcdata { dataoff := off + int64(ctxt.Arch.PtrSize*j) @@ -767,12 +770,15 @@ func writeFuncs(ctxt *Link, sb *loader.SymbolBuilder, funcs []loader.Sym, inlSym ldr := ctxt.loader deferReturnSym := ldr.Lookup("runtime.deferreturn", abiInternalVer) funcdata, funcdataoff := []loader.Sym{}, []int64{} + var pcsp, pcfile, pcline, pcinline loader.Sym + var pcdata []loader.Sym // Write the individual func objects. for i, s := range funcs { fi := ldr.FuncInfo(s) if fi.Valid() { fi.Preload() + pcsp, pcfile, pcline, pcinline, pcdata = ldr.PcdataAuxs(s, pcdata) } // Note we skip the space for the entry value -- that's handled in @@ -801,13 +807,13 @@ func writeFuncs(ctxt *Link, sb *loader.SymbolBuilder, funcs []loader.Sym, inlSym // pcdata if fi.Valid() { - off = uint32(sb.SetUint32(ctxt.Arch, int64(off), uint32(ldr.SymValue(fi.Pcsp())))) - off = uint32(sb.SetUint32(ctxt.Arch, int64(off), uint32(ldr.SymValue(fi.Pcfile())))) - off = uint32(sb.SetUint32(ctxt.Arch, int64(off), uint32(ldr.SymValue(fi.Pcline())))) + off = uint32(sb.SetUint32(ctxt.Arch, int64(off), uint32(ldr.SymValue(pcsp)))) + off = uint32(sb.SetUint32(ctxt.Arch, int64(off), uint32(ldr.SymValue(pcfile)))) + off = uint32(sb.SetUint32(ctxt.Arch, int64(off), uint32(ldr.SymValue(pcline)))) } else { off += 12 } - off = uint32(sb.SetUint32(ctxt.Arch, int64(off), uint32(numPCData(fi)))) + off = uint32(sb.SetUint32(ctxt.Arch, int64(off), uint32(numPCData(ldr, s, fi)))) // Store the offset to compilation unit's file table. cuIdx := ^uint32(0) @@ -838,11 +844,11 @@ func writeFuncs(ctxt *Link, sb *loader.SymbolBuilder, funcs []loader.Sym, inlSym // Output the pcdata. if fi.Valid() { - for j, pcSym := range fi.Pcdata() { + for j, pcSym := range pcdata { sb.SetUint32(ctxt.Arch, int64(off+uint32(j*4)), uint32(ldr.SymValue(pcSym))) } if fi.NumInlTree() > 0 { - sb.SetUint32(ctxt.Arch, int64(off+objabi.PCDATA_InlTreeIndex*4), uint32(ldr.SymValue(fi.Pcinline()))) + sb.SetUint32(ctxt.Arch, int64(off+objabi.PCDATA_InlTreeIndex*4), uint32(ldr.SymValue(pcinline))) } } } diff --git a/src/cmd/link/internal/loader/loader.go b/src/cmd/link/internal/loader/loader.go index 4bf5475a32..ec145da26d 100644 --- a/src/cmd/link/internal/loader/loader.go +++ b/src/cmd/link/internal/loader/loader.go @@ -1532,27 +1532,7 @@ func (l *Loader) DynidSyms() []Sym { // approach would be to check for gotype during preload and copy the // results in to a map (might want to try this at some point and see // if it helps speed things up). -func (l *Loader) SymGoType(i Sym) Sym { - var r *oReader - var auxs []goobj.Aux - if l.IsExternal(i) { - pp := l.getPayload(i) - r = l.objs[pp.objidx].r - auxs = pp.auxs - } else { - var li uint32 - r, li = l.toLocal(i) - auxs = r.Auxs(li) - } - for j := range auxs { - a := &auxs[j] - switch a.Type() { - case goobj.AuxGotype: - return l.resolve(r, a.Sym()) - } - } - return 0 -} +func (l *Loader) SymGoType(i Sym) Sym { return l.aux1(i, goobj.AuxGotype) } // SymUnit returns the compilation unit for a given symbol (which will // typically be nil for external or linker-manufactured symbols). @@ -1890,6 +1870,66 @@ func (l *Loader) relocs(r *oReader, li uint32) Relocs { } } +func (l *Loader) auxs(i Sym) (*oReader, []goobj.Aux) { + if l.IsExternal(i) { + pp := l.getPayload(i) + return l.objs[pp.objidx].r, pp.auxs + } else { + r, li := l.toLocal(i) + return r, r.Auxs(li) + } +} + +// Returns a specific aux symbol of type t for symbol i. +func (l *Loader) aux1(i Sym, t uint8) Sym { + r, auxs := l.auxs(i) + for j := range auxs { + a := &auxs[j] + if a.Type() == t { + return l.resolve(r, a.Sym()) + } + } + return 0 +} + +func (l *Loader) Pcsp(i Sym) Sym { return l.aux1(i, goobj.AuxPcsp) } + +// Returns all aux symbols of per-PC data for symbol i. +// tmp is a scratch space for the pcdata slice. +func (l *Loader) PcdataAuxs(i Sym, tmp []Sym) (pcsp, pcfile, pcline, pcinline Sym, pcdata []Sym) { + pcdata = tmp[:0] + r, auxs := l.auxs(i) + for j := range auxs { + a := &auxs[j] + switch a.Type() { + case goobj.AuxPcsp: + pcsp = l.resolve(r, a.Sym()) + case goobj.AuxPcline: + pcline = l.resolve(r, a.Sym()) + case goobj.AuxPcfile: + pcfile = l.resolve(r, a.Sym()) + case goobj.AuxPcinline: + pcinline = l.resolve(r, a.Sym()) + case goobj.AuxPcdata: + pcdata = append(pcdata, l.resolve(r, a.Sym())) + } + } + return +} + +// Returns the number of pcdata for symbol i. +func (l *Loader) NumPcdata(i Sym) int { + n := 0 + _, auxs := l.auxs(i) + for j := range auxs { + a := &auxs[j] + if a.Type() == goobj.AuxPcdata { + n++ + } + } + return n +} + // FuncInfo provides hooks to access goobj.FuncInfo in the objects. type FuncInfo struct { l *Loader @@ -1917,44 +1957,12 @@ func (fi *FuncInfo) FuncFlag() objabi.FuncFlag { return (*goobj.FuncInfo)(nil).ReadFuncFlag(fi.data) } -func (fi *FuncInfo) Pcsp() Sym { - sym := (*goobj.FuncInfo)(nil).ReadPcsp(fi.data) - return fi.l.resolve(fi.r, sym) -} - -func (fi *FuncInfo) Pcfile() Sym { - sym := (*goobj.FuncInfo)(nil).ReadPcfile(fi.data) - return fi.l.resolve(fi.r, sym) -} - -func (fi *FuncInfo) Pcline() Sym { - sym := (*goobj.FuncInfo)(nil).ReadPcline(fi.data) - return fi.l.resolve(fi.r, sym) -} - -func (fi *FuncInfo) Pcinline() Sym { - sym := (*goobj.FuncInfo)(nil).ReadPcinline(fi.data) - return fi.l.resolve(fi.r, sym) -} - // Preload has to be called prior to invoking the various methods // below related to pcdata, funcdataoff, files, and inltree nodes. func (fi *FuncInfo) Preload() { fi.lengths = (*goobj.FuncInfo)(nil).ReadFuncInfoLengths(fi.data) } -func (fi *FuncInfo) Pcdata() []Sym { - if !fi.lengths.Initialized { - panic("need to call Preload first") - } - syms := (*goobj.FuncInfo)(nil).ReadPcdata(fi.data) - ret := make([]Sym, len(syms)) - for i := range ret { - ret[i] = fi.l.resolve(fi.r, syms[i]) - } - return ret -} - func (fi *FuncInfo) NumFuncdataoff() uint32 { if !fi.lengths.Initialized { panic("need to call Preload first") @@ -2038,20 +2046,7 @@ func (fi *FuncInfo) InlTree(k int) InlTreeNode { } func (l *Loader) FuncInfo(i Sym) FuncInfo { - var r *oReader - var auxs []goobj.Aux - if l.IsExternal(i) { - pp := l.getPayload(i) - if pp.objidx == 0 { - return FuncInfo{} - } - r = l.objs[pp.objidx].r - auxs = pp.auxs - } else { - var li uint32 - r, li = l.toLocal(i) - auxs = r.Auxs(li) - } + r, auxs := l.auxs(i) for j := range auxs { a := &auxs[j] if a.Type() == goobj.AuxFuncInfo {