aboutsummaryrefslogtreecommitdiff
path: root/src/debug
diff options
context:
space:
mode:
authorJosh Bleecher Snyder <josharian@gmail.com>2021-10-04 14:49:42 -0700
committerJosh Bleecher Snyder <josharian@gmail.com>2021-10-04 22:59:44 +0000
commit78c2529d73fbd2e2213c9f03862bcf2aaa86d78b (patch)
treebd035f705dbeaf35236d2ba0320069a88dc38438 /src/debug
parent199ec4235000a51518802ce822447df5901c7df5 (diff)
downloadgo-78c2529d73fbd2e2213c9f03862bcf2aaa86d78b.tar.gz
go-78c2529d73fbd2e2213c9f03862bcf2aaa86d78b.zip
debug/gosym: add funcTab abstraction
This clarifies the existing code and makes modifications easier. name old time/op new time/op delta 115/LineToPC-8 58.6µs ± 3% 56.4µs ± 3% -3.80% (p=0.000 n=15+15) 115/PCToLine-8 194ns ± 2% 188ns ± 2% -3.31% (p=0.000 n=15+15) Change-Id: Iafdf57af93d5e3c145965c32e0227e37c69ab017 Reviewed-on: https://go-review.googlesource.com/c/go/+/353880 Trust: Josh Bleecher Snyder <josharian@gmail.com> Run-TryBot: Josh Bleecher Snyder <josharian@gmail.com> TryBot-Result: Go Bot <gobot@golang.org> Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
Diffstat (limited to 'src/debug')
-rw-r--r--src/debug/gosym/pclntab.go64
1 files changed, 51 insertions, 13 deletions
diff --git a/src/debug/gosym/pclntab.go b/src/debug/gosym/pclntab.go
index 4d312d22f1..8fe45decd6 100644
--- a/src/debug/gosym/pclntab.go
+++ b/src/debug/gosym/pclntab.go
@@ -232,6 +232,7 @@ func (t *LineTable) parsePclnTab() {
default:
return
}
+ t.version = possibleVersion
// quantum and ptrSize are the same between 1.2, 1.16, and 1.18
t.quantum = uint32(t.Data[6])
@@ -255,7 +256,7 @@ func (t *LineTable) parsePclnTab() {
t.pctab = data(6)
t.funcdata = data(7)
t.functab = data(7)
- functabsize := t.nfunctab*2*t.ptrsize + t.ptrsize
+ functabsize := (int(t.nfunctab)*2 + 1) * t.functabFieldSize()
t.functab = t.functab[:functabsize]
case ver116:
t.nfunctab = uint32(offset(0))
@@ -266,7 +267,7 @@ func (t *LineTable) parsePclnTab() {
t.pctab = data(5)
t.funcdata = data(6)
t.functab = data(6)
- functabsize := t.nfunctab*2*t.ptrsize + t.ptrsize
+ functabsize := (int(t.nfunctab)*2 + 1) * t.functabFieldSize()
t.functab = t.functab[:functabsize]
case ver12:
t.nfunctab = uint32(t.uintptr(t.Data[8:]))
@@ -274,7 +275,7 @@ func (t *LineTable) parsePclnTab() {
t.funcnametab = t.Data
t.functab = t.Data[8+t.ptrsize:]
t.pctab = t.Data
- functabsize := t.nfunctab*2*t.ptrsize + t.ptrsize
+ functabsize := (int(t.nfunctab)*2 + 1) * t.functabFieldSize()
fileoff := t.binary.Uint32(t.functab[functabsize:])
t.functab = t.functab[:functabsize]
t.filetab = t.Data[fileoff:]
@@ -283,7 +284,6 @@ func (t *LineTable) parsePclnTab() {
default:
panic("unreachable")
}
- t.version = possibleVersion
}
// go12Funcs returns a slice of Funcs derived from the Go 1.2+ pcln table.
@@ -295,12 +295,12 @@ func (t *LineTable) go12Funcs() []Func {
}()
}
- n := len(t.functab) / int(t.ptrsize) / 2
- funcs := make([]Func, n)
+ ft := t.funcTab()
+ funcs := make([]Func, ft.Count())
for i := range funcs {
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):])
+ f.Entry = ft.pc(i)
+ f.End = ft.pc(i + 1)
info := t.funcData(uint32(i))
f.LineTable = t
f.FrameSize = int(info.deferreturn())
@@ -317,13 +317,12 @@ func (t *LineTable) go12Funcs() []Func {
// 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):]) {
+ ft := t.funcTab()
+ if pc < ft.pc(0) || pc >= ft.pc(ft.Count()) {
return funcData{}
}
- // The function table is a list of 2*nfunctab+1 uintptrs,
- // alternating program counters and offsets to func structures.
idx := sort.Search(int(t.nfunctab), func(i int) bool {
- return t.uintptr(t.functab[2*i*int(t.ptrsize):]) > pc
+ return ft.pc(i) > pc
})
idx--
return t.funcData(uint32(idx))
@@ -372,6 +371,45 @@ func (t *LineTable) string(off uint32) string {
return t.stringFrom(t.funcdata, off)
}
+// functabFieldSize returns the size in bytes of a single functab field.
+func (t *LineTable) functabFieldSize() int {
+ return int(t.ptrsize)
+}
+
+// funcTab returns t's funcTab.
+func (t *LineTable) funcTab() funcTab {
+ return funcTab{t}
+}
+
+// funcTab is memory corresponding to a slice of functab structs, followed by an invalid PC.
+// A functab struct is a PC and a func offset.
+type funcTab struct {
+ *LineTable
+}
+
+// Count returns the number of func entries in f.
+func (f funcTab) Count() int {
+ return int(f.nfunctab)
+}
+
+// pc returns the PC of the i'th func in f.
+func (f funcTab) pc(i int) uint64 {
+ return f.uint(f.functab[2*i*f.functabFieldSize():])
+}
+
+// funcOff returns the funcdata offset of the i'th func in f.
+func (f funcTab) funcOff(i int) uint64 {
+ return f.uint(f.functab[(2*i+1)*f.functabFieldSize():])
+}
+
+// uint returns the uint stored at b.
+func (f funcTab) uint(b []byte) uint64 {
+ if f.functabFieldSize() == 4 {
+ return uint64(f.binary.Uint32(b))
+ }
+ return f.binary.Uint64(b)
+}
+
// funcData is memory corresponding to an _func struct.
type funcData struct {
t *LineTable // LineTable this data is a part of
@@ -380,7 +418,7 @@ type funcData struct {
// 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:]):]
+ data := t.funcdata[t.funcTab().funcOff(int(i)):]
return funcData{t: t, data: data}
}