cmd/internal/goobj, cmd/link: remove funcdataoff

FUNCDATA is always a symbol reference with 0 offset. Assert the
offset is 0 and remove funcdataoff.

Change-Id: I326815365c9db5aeef6b869df5d78a9957bc16a6
Reviewed-on: https://go-review.googlesource.com/c/go/+/352894
Trust: Cherry Mui <cherryyz@google.com>
Reviewed-by: Than McIntosh <thanm@google.com>
This commit is contained in:
Cherry Mui 2021-09-28 17:07:01 -04:00
parent 587b3c1192
commit e180e2c27c
6 changed files with 62 additions and 102 deletions

View file

@ -21,11 +21,8 @@ type FuncInfo struct {
Locals uint32 Locals uint32
FuncID objabi.FuncID FuncID objabi.FuncID
FuncFlag objabi.FuncFlag FuncFlag objabi.FuncFlag
File []CUFileIndex
Funcdataoff []uint32 InlTree []InlTreeNode
File []CUFileIndex
InlTree []InlTreeNode
} }
func (a *FuncInfo) Write(w *bytes.Buffer) { func (a *FuncInfo) Write(w *bytes.Buffer) {
@ -45,10 +42,6 @@ func (a *FuncInfo) Write(w *bytes.Buffer) {
writeUint8(0) // pad to uint32 boundary writeUint8(0) // pad to uint32 boundary
writeUint8(0) writeUint8(0)
writeUint32(uint32(len(a.Funcdataoff)))
for _, x := range a.Funcdataoff {
writeUint32(x)
}
writeUint32(uint32(len(a.File))) writeUint32(uint32(len(a.File)))
for _, f := range a.File { for _, f := range a.File {
writeUint32(uint32(f)) writeUint32(uint32(f))
@ -65,25 +58,19 @@ func (a *FuncInfo) Write(w *bytes.Buffer) {
// corresponding "off" field stores the byte offset of the start of // corresponding "off" field stores the byte offset of the start of
// the items in question. // the items in question.
type FuncInfoLengths struct { type FuncInfoLengths struct {
NumFuncdataoff uint32 NumFile uint32
FuncdataoffOff uint32 FileOff uint32
NumFile uint32 NumInlTree uint32
FileOff uint32 InlTreeOff uint32
NumInlTree uint32 Initialized bool
InlTreeOff uint32
Initialized bool
} }
func (*FuncInfo) ReadFuncInfoLengths(b []byte) FuncInfoLengths { func (*FuncInfo) ReadFuncInfoLengths(b []byte) FuncInfoLengths {
var result FuncInfoLengths var result FuncInfoLengths
// Offset to the number of funcdataoff values. This value is determined by counting // Offset to the number of the file table. This value is determined by counting
// the number of bytes until we write funcdataoff to the file. // the number of bytes until we write funcdataoff to the file.
const numfuncdataoffOff = 12 const numfileOff = 12
result.NumFuncdataoff = binary.LittleEndian.Uint32(b[numfuncdataoffOff:])
result.FuncdataoffOff = numfuncdataoffOff + 4
numfileOff := result.FuncdataoffOff + 4*result.NumFuncdataoff
result.NumFile = binary.LittleEndian.Uint32(b[numfileOff:]) result.NumFile = binary.LittleEndian.Uint32(b[numfileOff:])
result.FileOff = numfileOff + 4 result.FileOff = numfileOff + 4
@ -104,10 +91,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) ReadFuncFlag(b []byte) objabi.FuncFlag { return objabi.FuncFlag(b[9]) }
func (*FuncInfo) ReadFuncdataoff(b []byte, funcdataofffoff uint32, k uint32) int64 {
return int64(binary.LittleEndian.Uint32(b[funcdataofffoff+4*k:]))
}
func (*FuncInfo) ReadFile(b []byte, filesoff uint32, k uint32) CUFileIndex { func (*FuncInfo) ReadFile(b []byte, filesoff uint32, k uint32) CUFileIndex {
return CUFileIndex(binary.LittleEndian.Uint32(b[filesoff+4*k:])) return CUFileIndex(binary.LittleEndian.Uint32(b[filesoff+4*k:]))
} }

View file

@ -830,15 +830,14 @@ func (*LSym) CanBeAnSSAAux() {}
type Pcln struct { type Pcln struct {
// Aux symbols for pcln // Aux symbols for pcln
Pcsp *LSym Pcsp *LSym
Pcfile *LSym Pcfile *LSym
Pcline *LSym Pcline *LSym
Pcinline *LSym Pcinline *LSym
Pcdata []*LSym Pcdata []*LSym
Funcdata []*LSym Funcdata []*LSym
Funcdataoff []int64 UsedFiles map[goobj.CUFileIndex]struct{} // file indices used while generating pcfile
UsedFiles map[goobj.CUFileIndex]struct{} // file indices used while generating pcfile InlTree InlTree // per-function inlining tree extracted from the global tree
InlTree InlTree // per-function inlining tree extracted from the global tree
} }
type Reloc struct { type Reloc struct {

View file

@ -671,10 +671,6 @@ func genFuncInfoSyms(ctxt *Link) {
FuncFlag: fn.FuncFlag, FuncFlag: fn.FuncFlag,
} }
pc := &fn.Pcln pc := &fn.Pcln
o.Funcdataoff = make([]uint32, len(pc.Funcdataoff))
for i, x := range pc.Funcdataoff {
o.Funcdataoff[i] = uint32(x)
}
i := 0 i := 0
o.File = make([]goobj.CUFileIndex, len(pc.UsedFiles)) o.File = make([]goobj.CUFileIndex, len(pc.UsedFiles))
for f := range pc.UsedFiles { for f := range pc.UsedFiles {

View file

@ -8,6 +8,7 @@ import (
"cmd/internal/goobj" "cmd/internal/goobj"
"cmd/internal/objabi" "cmd/internal/objabi"
"encoding/binary" "encoding/binary"
"fmt"
"log" "log"
) )
@ -280,8 +281,6 @@ func linkpcln(ctxt *Link, cursym *LSym) {
pcln.Pcdata = make([]*LSym, npcdata) pcln.Pcdata = make([]*LSym, npcdata)
pcln.Funcdata = make([]*LSym, nfuncdata) pcln.Funcdata = make([]*LSym, nfuncdata)
pcln.Funcdataoff = make([]int64, nfuncdata)
pcln.Funcdataoff = pcln.Funcdataoff[:nfuncdata]
pcln.Pcsp = funcpctab(ctxt, cursym, "pctospadj", pctospadj, nil) pcln.Pcsp = funcpctab(ctxt, cursym, "pctospadj", pctospadj, nil)
pcln.Pcfile = funcpctab(ctxt, cursym, "pctofile", pctofileline, pcln) pcln.Pcfile = funcpctab(ctxt, cursym, "pctofile", pctofileline, pcln)
@ -351,12 +350,10 @@ func linkpcln(ctxt *Link, cursym *LSym) {
continue continue
} }
i := int(p.From.Offset) i := int(p.From.Offset)
pcln.Funcdataoff[i] = p.To.Offset if p.To.Type != TYPE_MEM || p.To.Offset != 0 {
if p.To.Type != TYPE_CONST { panic(fmt.Sprintf("bad funcdata: %v", p))
// TODO: Dedup.
//funcdata_bytes += p->to.sym->size;
pcln.Funcdata[i] = p.To.Sym
} }
pcln.Funcdata[i] = p.To.Sym
} }
} }
} }

View file

@ -623,33 +623,24 @@ func (state *pclntab) generateFunctab(ctxt *Link, funcs []loader.Sym, inlSyms ma
} }
// funcData returns the funcdata and offsets for the FuncInfo. // funcData returns the funcdata and offsets for the FuncInfo.
// The funcdata and offsets are written into runtime.functab after each func // The funcdata are written into runtime.functab after each func
// object. This is a helper function to make querying the FuncInfo object // object. This is a helper function to make querying the FuncInfo object
// cleaner. // cleaner.
// //
// Note, the majority of fdOffsets are 0, meaning there is no offset between
// the compiler's generated symbol, and what the runtime needs. They are
// plumbed through for no loss of generality.
//
// NB: Preload must be called on the FuncInfo before calling. // NB: Preload must be called on the FuncInfo before calling.
// NB: fdSyms and fdOffs are used as scratch space. // NB: fdSyms is used as scratch space.
func funcData(fi loader.FuncInfo, inlSym loader.Sym, fdSyms []loader.Sym, fdOffs []int64) ([]loader.Sym, []int64) { func funcData(ldr *loader.Loader, s loader.Sym, fi loader.FuncInfo, inlSym loader.Sym, fdSyms []loader.Sym) []loader.Sym {
fdSyms, fdOffs = fdSyms[:0], fdOffs[:0] fdSyms = fdSyms[:0]
if fi.Valid() { if fi.Valid() {
numOffsets := int(fi.NumFuncdataoff()) fdSyms = ldr.Funcdata(s, fdSyms)
for i := 0; i < numOffsets; i++ {
fdOffs = append(fdOffs, fi.Funcdataoff(i))
}
fdSyms = fi.Funcdata(fdSyms)
if fi.NumInlTree() > 0 { if fi.NumInlTree() > 0 {
if len(fdSyms) < objabi.FUNCDATA_InlTree+1 { if len(fdSyms) < objabi.FUNCDATA_InlTree+1 {
fdSyms = append(fdSyms, make([]loader.Sym, objabi.FUNCDATA_InlTree+1-len(fdSyms))...) fdSyms = append(fdSyms, make([]loader.Sym, objabi.FUNCDATA_InlTree+1-len(fdSyms))...)
fdOffs = append(fdOffs, make([]int64, objabi.FUNCDATA_InlTree+1-len(fdOffs))...)
} }
fdSyms[objabi.FUNCDATA_InlTree] = inlSym fdSyms[objabi.FUNCDATA_InlTree] = inlSym
} }
} }
return fdSyms, fdOffs return fdSyms
} }
// calculateFunctabSize calculates the size of the pclntab, and the offsets in // calculateFunctabSize calculates the size of the pclntab, and the offsets in
@ -673,7 +664,7 @@ func (state pclntab) calculateFunctabSize(ctxt *Link, funcs []loader.Sym) (int64
size += int64(state.funcSize) size += int64(state.funcSize)
if fi.Valid() { if fi.Valid() {
fi.Preload() fi.Preload()
numFuncData := int(fi.NumFuncdataoff()) numFuncData := ldr.NumFuncdata(s)
if fi.NumInlTree() > 0 { if fi.NumInlTree() > 0 {
if numFuncData < objabi.FUNCDATA_InlTree+1 { if numFuncData < objabi.FUNCDATA_InlTree+1 {
numFuncData = objabi.FUNCDATA_InlTree + 1 numFuncData = objabi.FUNCDATA_InlTree + 1
@ -738,7 +729,7 @@ func writePCToFunc(ctxt *Link, sb *loader.SymbolBuilder, funcs []loader.Sym, sta
// generateFunctab. // generateFunctab.
func (state *pclntab) writeFuncData(ctxt *Link, sb *loader.SymbolBuilder, funcs []loader.Sym, inlSyms map[loader.Sym]loader.Sym, startLocations []uint32, setAddr pclnSetAddr, setUint pclnSetUint) { func (state *pclntab) writeFuncData(ctxt *Link, sb *loader.SymbolBuilder, funcs []loader.Sym, inlSyms map[loader.Sym]loader.Sym, startLocations []uint32, setAddr pclnSetAddr, setUint pclnSetUint) {
ldr := ctxt.loader ldr := ctxt.loader
funcdata, funcdataoff := []loader.Sym{}, []int64{} funcdata := []loader.Sym{}
for i, s := range funcs { for i, s := range funcs {
fi := ldr.FuncInfo(s) fi := ldr.FuncInfo(s)
if !fi.Valid() { if !fi.Valid() {
@ -748,18 +739,18 @@ func (state *pclntab) writeFuncData(ctxt *Link, sb *loader.SymbolBuilder, funcs
// funcdata, must be pointer-aligned and we're only int32-aligned. // funcdata, must be pointer-aligned and we're only int32-aligned.
// Missing funcdata will be 0 (nil pointer). // Missing funcdata will be 0 (nil pointer).
funcdata, funcdataoff := funcData(fi, inlSyms[s], funcdata, funcdataoff) funcdata = funcData(ldr, s, fi, inlSyms[s], funcdata)
if len(funcdata) > 0 { if len(funcdata) > 0 {
off := int64(startLocations[i] + state.funcSize + numPCData(ldr, s, fi)*4) off := int64(startLocations[i] + state.funcSize + numPCData(ldr, s, fi)*4)
off = Rnd(off, int64(ctxt.Arch.PtrSize)) off = Rnd(off, int64(ctxt.Arch.PtrSize))
for j := range funcdata { for j := range funcdata {
dataoff := off + int64(ctxt.Arch.PtrSize*j) dataoff := off + int64(ctxt.Arch.PtrSize*j)
if funcdata[j] == 0 { if funcdata[j] == 0 {
setUint(sb, ctxt.Arch, dataoff, uint64(funcdataoff[j])) setUint(sb, ctxt.Arch, dataoff, 0)
continue continue
} }
// TODO: Does this need deduping? // TODO: Does this need deduping?
setAddr(sb, ctxt.Arch, dataoff, funcdata[j], funcdataoff[j]) setAddr(sb, ctxt.Arch, dataoff, funcdata[j], 0)
} }
} }
} }
@ -769,7 +760,7 @@ func (state *pclntab) writeFuncData(ctxt *Link, sb *loader.SymbolBuilder, funcs
func writeFuncs(ctxt *Link, sb *loader.SymbolBuilder, funcs []loader.Sym, inlSyms map[loader.Sym]loader.Sym, startLocations, cuOffsets []uint32, nameOffsets map[loader.Sym]uint32) { func writeFuncs(ctxt *Link, sb *loader.SymbolBuilder, funcs []loader.Sym, inlSyms map[loader.Sym]loader.Sym, startLocations, cuOffsets []uint32, nameOffsets map[loader.Sym]uint32) {
ldr := ctxt.loader ldr := ctxt.loader
deferReturnSym := ldr.Lookup("runtime.deferreturn", abiInternalVer) deferReturnSym := ldr.Lookup("runtime.deferreturn", abiInternalVer)
funcdata, funcdataoff := []loader.Sym{}, []int64{} funcdata := []loader.Sym{}
var pcsp, pcfile, pcline, pcinline loader.Sym var pcsp, pcfile, pcline, pcinline loader.Sym
var pcdata []loader.Sym var pcdata []loader.Sym
@ -839,7 +830,7 @@ func writeFuncs(ctxt *Link, sb *loader.SymbolBuilder, funcs []loader.Sym, inlSym
off += 1 // pad off += 1 // pad
// nfuncdata must be the final entry. // nfuncdata must be the final entry.
funcdata, funcdataoff = funcData(fi, 0, funcdata, funcdataoff) funcdata = funcData(ldr, s, fi, 0, funcdata)
off = uint32(sb.SetUint8(ctxt.Arch, int64(off), uint8(len(funcdata)))) off = uint32(sb.SetUint8(ctxt.Arch, int64(off), uint8(len(funcdata))))
// Output the pcdata. // Output the pcdata.

View file

@ -1930,12 +1930,38 @@ func (l *Loader) NumPcdata(i Sym) int {
return n return n
} }
// Returns all funcdata symbols of symbol i.
// tmp is a scratch space.
func (l *Loader) Funcdata(i Sym, tmp []Sym) []Sym {
fd := tmp[:0]
r, auxs := l.auxs(i)
for j := range auxs {
a := &auxs[j]
if a.Type() == goobj.AuxFuncdata {
fd = append(fd, l.resolve(r, a.Sym()))
}
}
return fd
}
// Returns the number of funcdata for symbol i.
func (l *Loader) NumFuncdata(i Sym) int {
n := 0
_, auxs := l.auxs(i)
for j := range auxs {
a := &auxs[j]
if a.Type() == goobj.AuxFuncdata {
n++
}
}
return n
}
// FuncInfo provides hooks to access goobj.FuncInfo in the objects. // FuncInfo provides hooks to access goobj.FuncInfo in the objects.
type FuncInfo struct { type FuncInfo struct {
l *Loader l *Loader
r *oReader r *oReader
data []byte data []byte
auxs []goobj.Aux
lengths goobj.FuncInfoLengths lengths goobj.FuncInfoLengths
} }
@ -1963,38 +1989,6 @@ func (fi *FuncInfo) Preload() {
fi.lengths = (*goobj.FuncInfo)(nil).ReadFuncInfoLengths(fi.data) fi.lengths = (*goobj.FuncInfo)(nil).ReadFuncInfoLengths(fi.data)
} }
func (fi *FuncInfo) NumFuncdataoff() uint32 {
if !fi.lengths.Initialized {
panic("need to call Preload first")
}
return fi.lengths.NumFuncdataoff
}
func (fi *FuncInfo) Funcdataoff(k int) int64 {
if !fi.lengths.Initialized {
panic("need to call Preload first")
}
return (*goobj.FuncInfo)(nil).ReadFuncdataoff(fi.data, fi.lengths.FuncdataoffOff, uint32(k))
}
func (fi *FuncInfo) Funcdata(syms []Sym) []Sym {
if !fi.lengths.Initialized {
panic("need to call Preload first")
}
if int(fi.lengths.NumFuncdataoff) > cap(syms) {
syms = make([]Sym, 0, fi.lengths.NumFuncdataoff)
} else {
syms = syms[:0]
}
for j := range fi.auxs {
a := &fi.auxs[j]
if a.Type() == goobj.AuxFuncdata {
syms = append(syms, fi.l.resolve(fi.r, a.Sym()))
}
}
return syms
}
func (fi *FuncInfo) NumFile() uint32 { func (fi *FuncInfo) NumFile() uint32 {
if !fi.lengths.Initialized { if !fi.lengths.Initialized {
panic("need to call Preload first") panic("need to call Preload first")
@ -2051,7 +2045,7 @@ func (l *Loader) FuncInfo(i Sym) FuncInfo {
a := &auxs[j] a := &auxs[j]
if a.Type() == goobj.AuxFuncInfo { if a.Type() == goobj.AuxFuncInfo {
b := r.Data(a.Sym().SymIdx) b := r.Data(a.Sym().SymIdx)
return FuncInfo{l, r, b, auxs, goobj.FuncInfoLengths{}} return FuncInfo{l, r, b, goobj.FuncInfoLengths{}}
} }
} }
return FuncInfo{} return FuncInfo{}