Add InlTree to the FuncInfo aux symbol in new object files.
In the linker, change InlinedCall.Func from a Symbol to a string,
as we only use its Name. (There was a use of Func.File, but that
use is not correct anyway.) So we don't need to create a Symbol
if not necessary.
Change-Id: I38ce568ae0934cd9cb6d0b30599f1c8d75444fc9
Reviewed-on: https://go-review.googlesource.com/c/go/+/200098
Run-TryBot: Cherry Zhang <cherryyz@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Than McIntosh <thanm@google.com>
PCData: make([]Data, len(info.Pcdata)-1), // -1 as we appended one above
FuncData: make([]FuncData, len(info.Funcdataoff)),
File: make([]string, len(info.File)),
+ InlTree: make([]InlinedCall, len(info.InlTree)),
}
sym.Func = f
for k := range f.PCData {
symID := resolveSymRef(info.File[k])
f.File[k] = symID.Name
}
+ for k := range f.InlTree {
+ inl := &info.InlTree[k]
+ f.InlTree[k] = InlinedCall{
+ Parent: int64(inl.Parent),
+ File: resolveSymRef(inl.File).Name,
+ Line: int64(inl.Line),
+ Func: resolveSymRef(inl.Func),
+ ParentPC: int64(inl.ParentPC),
+ }
+ }
}
}
Funcdataoff []uint32
File []SymRef // TODO: just use string?
- // TODO: InlTree
+ InlTree []InlTreeNode
}
func (a *FuncInfo) Write(w *bytes.Buffer) {
writeUint32(f.PkgIdx)
writeUint32(f.SymIdx)
}
-
- // TODO: InlTree
+ writeUint32(uint32(len(a.InlTree)))
+ for i := range a.InlTree {
+ a.InlTree[i].Write(w)
+ }
}
func (a *FuncInfo) Read(b []byte) {
for i := range a.File {
a.File[i] = SymRef{readUint32(), readUint32()}
}
+ inltreelen := readUint32()
+ a.InlTree = make([]InlTreeNode, inltreelen)
+ for i := range a.InlTree {
+ b = a.InlTree[i].Read(b)
+ }
+}
+
+// InlTreeNode is the serialized form of FileInfo.InlTree.
+type InlTreeNode struct {
+ Parent int32
+ File SymRef
+ Line int32
+ Func SymRef
+ ParentPC int32
+}
+
+func (inl *InlTreeNode) Write(w *bytes.Buffer) {
+ var b [4]byte
+ writeUint32 := func(x uint32) {
+ binary.LittleEndian.PutUint32(b[:], x)
+ w.Write(b[:])
+ }
+ writeUint32(uint32(inl.Parent))
+ writeUint32(inl.File.PkgIdx)
+ writeUint32(inl.File.SymIdx)
+ writeUint32(uint32(inl.Line))
+ writeUint32(inl.Func.PkgIdx)
+ writeUint32(inl.Func.SymIdx)
+ writeUint32(uint32(inl.ParentPC))
+}
- // TODO: InlTree
+// Read an InlTreeNode from b, return the remaining bytes.
+func (inl *InlTreeNode) Read(b []byte) []byte {
+ readUint32 := func() uint32 {
+ x := binary.LittleEndian.Uint32(b)
+ b = b[4:]
+ return x
+ }
+ inl.Parent = int32(readUint32())
+ inl.File = SymRef{readUint32(), readUint32()}
+ inl.Line = int32(readUint32())
+ inl.Func = SymRef{readUint32(), readUint32()}
+ inl.ParentPC = int32(readUint32())
+ return b
}
fsym := ctxt.Lookup(f)
o.File[i] = makeSymRef(fsym)
}
+ o.InlTree = make([]goobj2.InlTreeNode, len(pc.InlTree.nodes))
+ for i, inl := range pc.InlTree.nodes {
+ f, l := linkgetlineFromPos(ctxt, inl.Pos)
+ fsym := ctxt.Lookup(f)
+ o.InlTree[i] = goobj2.InlTreeNode{
+ Parent: int32(inl.Parent),
+ File: makeSymRef(fsym),
+ Line: l,
+ Func: makeSymRef(inl.Func),
+ ParentPC: inl.ParentPC,
+ }
+ }
o.Write(&b)
isym := &LSym{
if call.Func != nil {
fn(call.Func)
}
+ f, _ := linkgetlineFromPos(ctxt, call.Pos)
+ if fsym := ctxt.Lookup(f); fsym != nil {
+ fn(fsym)
+ }
}
}
}
// appears in the Pcfile table. In that case, this assigns
// the outer file a number.
numberfile(ctxt, call.File)
- nameoff := nameToOffset(call.Func.Name)
+ nameoff := nameToOffset(call.Func)
inlTreeSym.SetUint16(ctxt.Arch, int64(i*20+0), uint16(call.Parent))
- inlTreeSym.SetUint8(ctxt.Arch, int64(i*20+2), uint8(objabi.GetFuncID(call.Func.Name, call.Func.File)))
+ inlTreeSym.SetUint8(ctxt.Arch, int64(i*20+2), uint8(objabi.GetFuncID(call.Func, "")))
// byte 3 is unused
inlTreeSym.SetUint32(ctxt.Arch, int64(i*20+4), uint32(call.File.Value))
inlTreeSym.SetUint32(ctxt.Arch, int64(i*20+8), uint32(call.Line))
pc.InlTree[i].Parent = r.readInt32()
pc.InlTree[i].File = r.readSymIndex()
pc.InlTree[i].Line = r.readInt32()
- pc.InlTree[i].Func = r.readSymIndex()
+ pc.InlTree[i].Func = r.readSymIndex().Name
pc.InlTree[i].ParentPC = r.readInt32()
}
pc.Pcdata = make([]sym.Pcdata, len(info.Pcdata)-1) // -1 as we appended one above
pc.Funcdataoff = make([]int64, len(info.Funcdataoff))
pc.File = make([]*sym.Symbol, len(info.File))
+ pc.InlTree = make([]sym.InlinedCall, len(info.InlTree))
pc.Pcsp.P = r.BytesAt(pcdataBase+info.Pcsp, int(info.Pcfile-info.Pcsp))
pc.Pcfile.P = r.BytesAt(pcdataBase+info.Pcfile, int(info.Pcline-info.Pcfile))
pc.Pcline.P = r.BytesAt(pcdataBase+info.Pcline, int(info.Pcinline-info.Pcline))
for k := range pc.File {
pc.File[k] = resolveSymRef(info.File[k])
}
+ for k := range pc.InlTree {
+ inl := &info.InlTree[k]
+ pc.InlTree[k] = sym.InlinedCall{
+ Parent: inl.Parent,
+ File: resolveSymRef(inl.File),
+ Line: inl.Line,
+ Func: l.SymName(l.Resolve(r, inl.Func)),
+ ParentPC: inl.ParentPC,
+ }
+ }
if !dupok {
if s.Attr.OnList() {
Parent int32 // index of parent in InlTree
File *Symbol // file of the inlined call
Line int32 // line number of the inlined call
- Func *Symbol // function that was inlined
+ Func string // name of the function that was inlined
ParentPC int32 // PC of the instruction just before the inlined body (offset from function start)
}