Locals uint32
FuncID objabi.FuncID
FuncFlag objabi.FuncFlag
-
- Funcdataoff []uint32
- File []CUFileIndex
-
- InlTree []InlTreeNode
+ File []CUFileIndex
+ InlTree []InlTreeNode
}
func (a *FuncInfo) Write(w *bytes.Buffer) {
writeUint8(0) // pad to uint32 boundary
writeUint8(0)
- writeUint32(uint32(len(a.Funcdataoff)))
- for _, x := range a.Funcdataoff {
- writeUint32(x)
- }
writeUint32(uint32(len(a.File)))
for _, f := range a.File {
writeUint32(uint32(f))
// corresponding "off" field stores the byte offset of the start of
// the items in question.
type FuncInfoLengths struct {
- NumFuncdataoff uint32
- FuncdataoffOff uint32
- NumFile uint32
- FileOff uint32
- NumInlTree uint32
- InlTreeOff uint32
- Initialized bool
+ NumFile uint32
+ FileOff uint32
+ NumInlTree uint32
+ InlTreeOff uint32
+ Initialized bool
}
func (*FuncInfo) ReadFuncInfoLengths(b []byte) 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.
- const numfuncdataoffOff = 12
- result.NumFuncdataoff = binary.LittleEndian.Uint32(b[numfuncdataoffOff:])
- result.FuncdataoffOff = numfuncdataoffOff + 4
-
- numfileOff := result.FuncdataoffOff + 4*result.NumFuncdataoff
+ const numfileOff = 12
result.NumFile = binary.LittleEndian.Uint32(b[numfileOff:])
result.FileOff = numfileOff + 4
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 {
return CUFileIndex(binary.LittleEndian.Uint32(b[filesoff+4*k:]))
}
type Pcln struct {
// Aux symbols for pcln
- Pcsp *LSym
- Pcfile *LSym
- Pcline *LSym
- Pcinline *LSym
- Pcdata []*LSym
- Funcdata []*LSym
- Funcdataoff []int64
- UsedFiles map[goobj.CUFileIndex]struct{} // file indices used while generating pcfile
- InlTree InlTree // per-function inlining tree extracted from the global tree
+ Pcsp *LSym
+ Pcfile *LSym
+ Pcline *LSym
+ Pcinline *LSym
+ Pcdata []*LSym
+ Funcdata []*LSym
+ UsedFiles map[goobj.CUFileIndex]struct{} // file indices used while generating pcfile
+ InlTree InlTree // per-function inlining tree extracted from the global tree
}
type Reloc struct {
FuncFlag: fn.FuncFlag,
}
pc := &fn.Pcln
- o.Funcdataoff = make([]uint32, len(pc.Funcdataoff))
- for i, x := range pc.Funcdataoff {
- o.Funcdataoff[i] = uint32(x)
- }
i := 0
o.File = make([]goobj.CUFileIndex, len(pc.UsedFiles))
for f := range pc.UsedFiles {
"cmd/internal/goobj"
"cmd/internal/objabi"
"encoding/binary"
+ "fmt"
"log"
)
pcln.Pcdata = make([]*LSym, npcdata)
pcln.Funcdata = make([]*LSym, nfuncdata)
- pcln.Funcdataoff = make([]int64, nfuncdata)
- pcln.Funcdataoff = pcln.Funcdataoff[:nfuncdata]
pcln.Pcsp = funcpctab(ctxt, cursym, "pctospadj", pctospadj, nil)
pcln.Pcfile = funcpctab(ctxt, cursym, "pctofile", pctofileline, pcln)
continue
}
i := int(p.From.Offset)
- pcln.Funcdataoff[i] = p.To.Offset
- if p.To.Type != TYPE_CONST {
- // TODO: Dedup.
- //funcdata_bytes += p->to.sym->size;
- pcln.Funcdata[i] = p.To.Sym
+ if p.To.Type != TYPE_MEM || p.To.Offset != 0 {
+ panic(fmt.Sprintf("bad funcdata: %v", p))
}
+ pcln.Funcdata[i] = p.To.Sym
}
}
}
}
// 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
// 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: fdSyms and fdOffs are used as scratch space.
-func funcData(fi loader.FuncInfo, inlSym loader.Sym, fdSyms []loader.Sym, fdOffs []int64) ([]loader.Sym, []int64) {
- fdSyms, fdOffs = fdSyms[:0], fdOffs[:0]
+// NB: fdSyms is used as scratch space.
+func funcData(ldr *loader.Loader, s loader.Sym, fi loader.FuncInfo, inlSym loader.Sym, fdSyms []loader.Sym) []loader.Sym {
+ fdSyms = fdSyms[:0]
if fi.Valid() {
- numOffsets := int(fi.NumFuncdataoff())
- for i := 0; i < numOffsets; i++ {
- fdOffs = append(fdOffs, fi.Funcdataoff(i))
- }
- fdSyms = fi.Funcdata(fdSyms)
+ fdSyms = ldr.Funcdata(s, fdSyms)
if fi.NumInlTree() > 0 {
if len(fdSyms) < objabi.FUNCDATA_InlTree+1 {
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
}
}
- return fdSyms, fdOffs
+ return fdSyms
}
// calculateFunctabSize calculates the size of the pclntab, and the offsets in
size += int64(state.funcSize)
if fi.Valid() {
fi.Preload()
- numFuncData := int(fi.NumFuncdataoff())
+ numFuncData := ldr.NumFuncdata(s)
if fi.NumInlTree() > 0 {
if numFuncData < objabi.FUNCDATA_InlTree+1 {
numFuncData = objabi.FUNCDATA_InlTree + 1
// 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) {
ldr := ctxt.loader
- funcdata, funcdataoff := []loader.Sym{}, []int64{}
+ funcdata := []loader.Sym{}
for i, s := range funcs {
fi := ldr.FuncInfo(s)
if !fi.Valid() {
// funcdata, must be pointer-aligned and we're only int32-aligned.
// 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 {
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)
if funcdata[j] == 0 {
- setUint(sb, ctxt.Arch, dataoff, uint64(funcdataoff[j]))
+ setUint(sb, ctxt.Arch, dataoff, 0)
continue
}
// TODO: Does this need deduping?
- setAddr(sb, ctxt.Arch, dataoff, funcdata[j], funcdataoff[j])
+ setAddr(sb, ctxt.Arch, dataoff, funcdata[j], 0)
}
}
}
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
deferReturnSym := ldr.Lookup("runtime.deferreturn", abiInternalVer)
- funcdata, funcdataoff := []loader.Sym{}, []int64{}
+ funcdata := []loader.Sym{}
var pcsp, pcfile, pcline, pcinline loader.Sym
var pcdata []loader.Sym
off += 1 // pad
// 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))))
// Output the pcdata.
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.
type FuncInfo struct {
l *Loader
r *oReader
data []byte
- auxs []goobj.Aux
lengths goobj.FuncInfoLengths
}
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 {
if !fi.lengths.Initialized {
panic("need to call Preload first")
a := &auxs[j]
if a.Type() == goobj.AuxFuncInfo {
b := r.Data(a.Sym().SymIdx)
- return FuncInfo{l, r, b, auxs, goobj.FuncInfoLengths{}}
+ return FuncInfo{l, r, b, goobj.FuncInfoLengths{}}
}
}
return FuncInfo{}