]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/link: access pcdata via aux symbols
authorCherry Mui <cherryyz@google.com>
Tue, 28 Sep 2021 20:20:29 +0000 (16:20 -0400)
committerCherry Mui <cherryyz@google.com>
Wed, 29 Sep 2021 13:53:07 +0000 (13:53 +0000)
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 <cherryyz@google.com>
Run-TryBot: Cherry Mui <cherryyz@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Than McIntosh <thanm@google.com>
src/cmd/internal/goobj/funcinfo.go
src/cmd/internal/obj/objfile.go
src/cmd/link/internal/ld/dwarf.go
src/cmd/link/internal/ld/lib.go
src/cmd/link/internal/ld/pcln.go
src/cmd/link/internal/loader/loader.go

index 6d33a10a51cda4cde69a36aaf281f6c61a520a1c..6e7970fb740786c23ae8f49bfd8e370b8db811cb 100644 (file)
@@ -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:]))
 }
index 030a02b4992db68053bfb28e8bc8404bba3880a3..bed32198d7870c5d9acff4c37e5e00c8d73fb31c 100644 (file)
@@ -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)
index d72846a6918f9e2f049b40fda6ebcfe35acac73c..47b4921cd8fe6f58290330cf9769e93151951455 100644 (file)
@@ -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.
index feff16d0c0701ae29056dfff720035ef52ae2bdd..5af20b4d18aef1ddb72d00a93da34082898b7e29 100644 (file)
@@ -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.
index fede00586be6c87083da1d15c76ff2dcc62c88c0..c8cd7bf09e5b0b00f1d7683b1fc87ca5924a116d 100644 (file)
@@ -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)))
                        }
                }
        }
index 4bf5475a32a9ab408bf1fdb6765095f7de9746a9..ec145da26dc884dbd2628d14b59f63da5a454051 100644 (file)
@@ -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 {