mirror of
https://github.com/golang/go
synced 2024-09-15 22:20:06 +00:00
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 <cherryyz@google.com> Run-TryBot: Cherry Mui <cherryyz@google.com> TryBot-Result: Go Bot <gobot@golang.org> Reviewed-by: Than McIntosh <thanm@google.com>
This commit is contained in:
parent
435718edd9
commit
587b3c1192
|
@ -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:]))
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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)))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
Loading…
Reference in a new issue