]> Cypherpunks repositories - gostls13.git/commitdiff
debug/gosym: refactor handling of funcdata
authorJosh Bleecher Snyder <josharian@gmail.com>
Thu, 23 Sep 2021 20:11:04 +0000 (13:11 -0700)
committerJosh Bleecher Snyder <josharian@gmail.com>
Wed, 29 Sep 2021 22:11:50 +0000 (22:11 +0000)
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>

src/debug/gosym/pclntab.go

index 5d18410a78ee51661ef1208a217978ba31b29aa7..bf97976b3c37b5003ab712b761fd29febaeeb64a 100644 (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 {