diff options
author | Than McIntosh <thanm@google.com> | 2020-04-08 11:56:43 -0400 |
---|---|---|
committer | Than McIntosh <thanm@google.com> | 2020-04-10 12:33:04 +0000 |
commit | 30b0c819d13692cc63852f4bfbf5979bffc13acc (patch) | |
tree | 24189c5a994c4bb7e19d010bf56e43190769408b /src/cmd/link/internal/loader/loader.go | |
parent | 37cc5cd76941f2b42f8b1403dde362439c8a9e69 (diff) | |
download | go-30b0c819d13692cc63852f4bfbf5979bffc13acc.tar.gz go-30b0c819d13692cc63852f4bfbf5979bffc13acc.zip |
[dev.link] cmd/link/internal/loader: expand methods for FuncInfo
Expand the methods for the FuncInfo helper, to support reading the
contents of an object file FuncInfo aux symbol using the new style
(that is to say, incrementally and without allocating slices to hold
the various bits).
Change-Id: I953d72c4a53f98c840e6b25b08fd33dc4a833dd5
Reviewed-on: https://go-review.googlesource.com/c/go/+/227585
Reviewed-by: Cherry Zhang <cherryyz@google.com>
Diffstat (limited to 'src/cmd/link/internal/loader/loader.go')
-rw-r--r-- | src/cmd/link/internal/loader/loader.go | 130 |
1 files changed, 125 insertions, 5 deletions
diff --git a/src/cmd/link/internal/loader/loader.go b/src/cmd/link/internal/loader/loader.go index cd5971c2e1..390eb1af24 100644 --- a/src/cmd/link/internal/loader/loader.go +++ b/src/cmd/link/internal/loader/loader.go @@ -1529,13 +1529,18 @@ func (x RelocByOff) Less(i, j int) bool { return x[i].Off < x[j].Off } // FuncInfo provides hooks to access goobj2.FuncInfo in the objects. type FuncInfo struct { - l *Loader - r *oReader - data []byte + l *Loader + r *oReader + data []byte + lengths goobj2.FuncInfoLengths } func (fi *FuncInfo) Valid() bool { return fi.r != nil } +func (fi *FuncInfo) Args() int { + return int((*goobj2.FuncInfo)(nil).ReadArgs(fi.data)) +} + func (fi *FuncInfo) Locals() int { return int((*goobj2.FuncInfo)(nil).ReadLocals(fi.data)) } @@ -1545,7 +1550,122 @@ func (fi *FuncInfo) Pcsp() []byte { return fi.r.BytesAt(fi.r.PcdataBase()+pcsp, int(end-pcsp)) } -// TODO: more accessors. +func (fi *FuncInfo) Pcfile() []byte { + pcf, end := (*goobj2.FuncInfo)(nil).ReadPcfile(fi.data) + return fi.r.BytesAt(fi.r.PcdataBase()+pcf, int(end-pcf)) +} + +func (fi *FuncInfo) Pcline() []byte { + pcln, end := (*goobj2.FuncInfo)(nil).ReadPcline(fi.data) + return fi.r.BytesAt(fi.r.PcdataBase()+pcln, int(end-pcln)) +} + +// 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 = (*goobj2.FuncInfo)(nil).ReadFuncInfoLengths(fi.data) +} + +func (fi *FuncInfo) Pcinline() []byte { + if !fi.lengths.Initialized { + panic("need to call Preload first") + } + pcinl, end := (*goobj2.FuncInfo)(nil).ReadPcinline(fi.data, fi.lengths.PcdataOff) + return fi.r.BytesAt(fi.r.PcdataBase()+pcinl, int(end-pcinl)) +} + +func (fi *FuncInfo) NumPcdata() uint32 { + if !fi.lengths.Initialized { + panic("need to call Preload first") + } + return fi.lengths.NumPcdata +} + +func (fi *FuncInfo) Pcdata(k int) []byte { + if !fi.lengths.Initialized { + panic("need to call Preload first") + } + pcdat, end := (*goobj2.FuncInfo)(nil).ReadPcdata(fi.data, fi.lengths.PcdataOff, uint32(k)) + return fi.r.BytesAt(fi.r.PcdataBase()+pcdat, int(end-pcdat)) +} + +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 (*goobj2.FuncInfo)(nil).ReadFuncdataoff(fi.data, fi.lengths.FuncdataoffOff, uint32(k)) +} + +func (fi *FuncInfo) Funcdata(fnsym Sym, 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] + } + r, li := fi.l.toLocal(fnsym) + auxs := r.Auxs2(li) + for j := range auxs { + a := &auxs[j] + if a.Type() == goobj2.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") + } + return fi.lengths.NumFile +} + +func (fi *FuncInfo) File(k int) Sym { + if !fi.lengths.Initialized { + panic("need to call Preload first") + } + sr := (*goobj2.FuncInfo)(nil).ReadFile(fi.data, fi.lengths.FileOff, uint32(k)) + return fi.l.resolve(fi.r, sr) +} + +type InlTreeNode struct { + Parent int32 + File Sym + Line int32 + Func Sym + ParentPC int32 +} + +func (fi *FuncInfo) NumInlTree() uint32 { + if !fi.lengths.Initialized { + panic("need to call Preload first") + } + return fi.lengths.NumInlTree +} + +func (fi *FuncInfo) InlTree(k int) InlTreeNode { + if !fi.lengths.Initialized { + panic("need to call Preload first") + } + node := (*goobj2.FuncInfo)(nil).ReadInlTree(fi.data, fi.lengths.InlTreeOff, uint32(k)) + return InlTreeNode{ + Parent: node.Parent, + File: fi.l.resolve(fi.r, node.File), + Line: node.Line, + Func: fi.l.resolve(fi.r, node.Func), + ParentPC: node.ParentPC, + } +} func (l *Loader) FuncInfo(i Sym) FuncInfo { var r *oReader @@ -1566,7 +1686,7 @@ func (l *Loader) FuncInfo(i Sym) FuncInfo { a := &auxs[j] if a.Type() == goobj2.AuxFuncInfo { b := r.Data(int(a.Sym().SymIdx)) - return FuncInfo{l, r, b} + return FuncInfo{l, r, b, goobj2.FuncInfoLengths{}} } } return FuncInfo{} |