1
0
mirror of https://github.com/golang/go synced 2024-11-17 03:04:44 -07:00

debug/gosym: refactor handling of funcdata

We do a bunch of manual offset calculations everywhere.
Add a bit of type safety and some helpers.
In addition to making the code clearer and providing a place
to hang some documentation, it also makes upcoming changes easier.

name                old time/op    new time/op    delta
115/NewLineTable-8    79.9ns ± 1%    90.2ns ±23%    ~     (p=0.234 n=9+10)
115/NewTable-8        72.0µs ± 1%    73.4µs ± 1%  +1.96%  (p=0.000 n=8+8)
115/LineToPC-8        53.3µs ± 1%    54.4µs ± 1%  +2.02%  (p=0.000 n=10+10)
115/PCToLine-8         249ns ± 0%     249ns ± 2%    ~     (p=0.147 n=9+10)

name                old alloc/op   new alloc/op   delta
115/NewLineTable-8      384B ± 0%      384B ± 0%    ~     (all equal)
115/NewTable-8         164kB ± 0%     164kB ± 0%    ~     (p=0.610 n=10+10)
115/LineToPC-8         0.00B          0.00B         ~     (all equal)
115/PCToLine-8         0.00B          0.00B         ~     (all equal)

name                old allocs/op  new allocs/op  delta
115/NewLineTable-8      3.00 ± 0%      3.00 ± 0%    ~     (all equal)
115/NewTable-8         1.04k ± 0%     1.04k ± 0%    ~     (all equal)
115/LineToPC-8          0.00           0.00         ~     (all equal)
115/PCToLine-8          0.00           0.00         ~     (all equal)

Change-Id: If357dce5ae4277e6ddc6d90ba6b5b83e470b9121
Reviewed-on: https://go-review.googlesource.com/c/go/+/352951
Trust: Josh Bleecher Snyder <josharian@gmail.com>
Trust: Brad Fitzpatrick <bradfitz@golang.org>
Run-TryBot: Josh Bleecher Snyder <josharian@gmail.com>
Reviewed-by: Cherry Mui <cherryyz@google.com>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
TryBot-Result: Go Bot <gobot@golang.org>
This commit is contained in:
Josh Bleecher Snyder 2021-09-23 13:11:04 -07:00
parent 40fa8c200c
commit ed57d7bb15

View File

@ -279,13 +279,13 @@ func (t *LineTable) go12Funcs() []Func {
f := &funcs[i]
f.Entry = t.uintptr(t.functab[2*i*int(t.ptrsize):])
f.End = t.uintptr(t.functab[(2*i+2)*int(t.ptrsize):])
info := t.funcdata[t.uintptr(t.functab[(2*i+1)*int(t.ptrsize):]):]
info := t.funcData(uint32(i))
f.LineTable = t
f.FrameSize = int(t.binary.Uint32(info[t.ptrsize+2*4:]))
f.FrameSize = int(info.deferreturn())
f.Sym = &Sym{
Value: f.Entry,
Type: 'T',
Name: t.funcName(t.binary.Uint32(info[t.ptrsize:])),
Name: t.funcName(info.nameoff()),
GoType: 0,
Func: f,
}
@ -293,10 +293,10 @@ func (t *LineTable) go12Funcs() []Func {
return funcs
}
// findFunc returns the func corresponding to the given program counter.
func (t *LineTable) findFunc(pc uint64) []byte {
// findFunc returns the funcData corresponding to the given program counter.
func (t *LineTable) findFunc(pc uint64) funcData {
if pc < t.uintptr(t.functab) || pc >= t.uintptr(t.functab[len(t.functab)-int(t.ptrsize):]) {
return nil
return funcData{}
}
// The function table is a list of 2*nfunctab+1 uintptrs,
@ -307,7 +307,8 @@ func (t *LineTable) findFunc(pc uint64) []byte {
m := nf / 2
fm := f[2*t.ptrsize*m:]
if t.uintptr(fm) <= pc && pc < t.uintptr(fm[2*t.ptrsize:]) {
return t.funcdata[t.uintptr(fm[t.ptrsize:]):]
data := t.funcdata[t.uintptr(fm[t.ptrsize:]):]
return funcData{t: t, data: data}
} else if pc < t.uintptr(fm) {
nf = m
} else {
@ -315,7 +316,7 @@ func (t *LineTable) findFunc(pc uint64) []byte {
nf -= m + 1
}
}
return nil
return funcData{}
}
// readvarint reads, removes, and returns a varint from *pp.
@ -361,6 +362,47 @@ func (t *LineTable) string(off uint32) string {
return t.stringFrom(t.funcdata, off)
}
// funcData is memory corresponding to an _func struct.
type funcData struct {
t *LineTable // LineTable this data is a part of
data []byte // raw memory for the function
}
// funcData returns the ith funcData in t.functab.
func (t *LineTable) funcData(i uint32) funcData {
data := t.funcdata[t.uintptr(t.functab[2*t.ptrsize*i+t.ptrsize:]):]
return funcData{t: t, data: data}
}
// IsZero reports whether f is the zero value.
func (f funcData) IsZero() bool {
return f.t == nil && f.data == nil
}
// entryPC returns the func's entry PC.
func (f funcData) entryPC() uint64 {
return f.t.uintptr(f.data)
}
func (f funcData) nameoff() uint32 { return f.field(1) }
func (f funcData) deferreturn() uint32 { return f.field(3) }
func (f funcData) pcfile() uint32 { return f.field(5) }
func (f funcData) pcln() uint32 { return f.field(6) }
func (f funcData) cuOffset() uint32 { return f.field(8) }
// field returns the nth field of the _func struct.
// It panics if n == 0 or n > 9; for n == 0, call f.entryPC.
// Most callers should use a named field accessor (just above).
func (f funcData) field(n uint32) uint32 {
if n == 0 || n > 9 {
panic("bad funcdata field")
}
sz0 := f.t.ptrsize
off := sz0 + (n-1)*4 // subsequent fields are 4 bytes each
data := f.data[off:]
return f.t.binary.Uint32(data)
}
// step advances to the next pc, value pair in the encoded table.
func (t *LineTable) step(p *[]byte, pc *uint64, val *int32, first bool) bool {
uvdelta := t.readvarint(p)
@ -451,11 +493,11 @@ func (t *LineTable) go12PCToLine(pc uint64) (line int) {
}()
f := t.findFunc(pc)
if f == nil {
if f.IsZero() {
return -1
}
entry := t.uintptr(f)
linetab := t.binary.Uint32(f[t.ptrsize+5*4:])
entry := f.entryPC()
linetab := f.pcln()
return int(t.pcvalue(linetab, entry, pc))
}
@ -468,11 +510,11 @@ func (t *LineTable) go12PCToFile(pc uint64) (file string) {
}()
f := t.findFunc(pc)
if f == nil {
if f.IsZero() {
return ""
}
entry := t.uintptr(f)
filetab := t.binary.Uint32(f[t.ptrsize+4*4:])
entry := f.entryPC()
filetab := f.pcfile()
fno := t.pcvalue(filetab, entry, pc)
if t.version == ver12 {
if fno <= 0 {
@ -484,7 +526,7 @@ func (t *LineTable) go12PCToFile(pc uint64) (file string) {
if fno < 0 { // 0 is valid for ≥ 1.16
return ""
}
cuoff := t.binary.Uint32(f[t.ptrsize+7*4:])
cuoff := f.cuOffset()
if fnoff := t.binary.Uint32(t.cutab[(cuoff+uint32(fno))*4:]); fnoff != ^uint32(0) {
return t.stringFrom(t.filetab, fnoff)
}
@ -510,13 +552,12 @@ func (t *LineTable) go12LineToPC(file string, line int) (pc uint64) {
// mapping file number to a list of functions with code from that file.
var cutab []byte
for i := uint32(0); i < t.nfunctab; i++ {
f := t.funcdata[t.uintptr(t.functab[2*t.ptrsize*i+t.ptrsize:]):]
entry := t.uintptr(f)
filetab := t.binary.Uint32(f[t.ptrsize+4*4:])
linetab := t.binary.Uint32(f[t.ptrsize+5*4:])
f := t.funcData(i)
entry := f.entryPC()
filetab := f.pcfile()
linetab := f.pcln()
if t.version == ver116 {
cuoff := t.binary.Uint32(f[t.ptrsize+7*4:]) * 4
cutab = t.cutab[cuoff:]
cutab = t.cutab[f.cuOffset()*4:]
}
pc := t.findFileLine(entry, filetab, linetab, int32(filenum), int32(line), cutab)
if pc != 0 {