aboutsummaryrefslogtreecommitdiff
path: root/src/runtime/symtab.go
diff options
context:
space:
mode:
authorAustin Clements <austin@google.com>2023-02-05 21:37:07 -0500
committerAustin Clements <austin@google.com>2023-03-10 17:18:34 +0000
commit166e5ee4f2b5f170663c25b56d4929919c13debf (patch)
treebba7627dc6de2e8e1e4a9516ff37e81f0e260fb3 /src/runtime/symtab.go
parent59d0de16e4f003e69403eeee969f0b4a96dd6dcb (diff)
downloadgo-166e5ee4f2b5f170663c25b56d4929919c13debf.tar.xz
runtime: use inlineUnwinder
This converts all places in the runtime that perform inline expansion to use the new inlineUnwinder abstraction. For #54466. Change-Id: I48d996fb6263ed5225bd21d30914a27ae434528d Reviewed-on: https://go-review.googlesource.com/c/go/+/466099 Run-TryBot: Austin Clements <austin@google.com> TryBot-Result: Gopher Robot <gobot@golang.org> Reviewed-by: Michael Pratt <mpratt@google.com>
Diffstat (limited to 'src/runtime/symtab.go')
-rw-r--r--src/runtime/symtab.go112
1 files changed, 40 insertions, 72 deletions
diff --git a/src/runtime/symtab.go b/src/runtime/symtab.go
index c3329568b7..67648a4ebc 100644
--- a/src/runtime/symtab.go
+++ b/src/runtime/symtab.go
@@ -116,28 +116,21 @@ func (ci *Frames) Next() (frame Frame, more bool) {
// work correctly for entries in the result of runtime.Callers.
pc--
}
- name := funcname(funcInfo)
- startLine := f.startLine()
- if inldata := funcdata(funcInfo, _FUNCDATA_InlTree); inldata != nil {
- inltree := (*[1 << 20]inlinedCall)(inldata)
- // Non-strict as cgoTraceback may have added bogus PCs
- // with a valid funcInfo but invalid PCDATA.
- ix := pcdatavalue1(funcInfo, _PCDATA_InlTreeIndex, pc, nil, false)
- if ix >= 0 {
- // Note: entry is not modified. It always refers to a real frame, not an inlined one.
- f = nil
- ic := inltree[ix]
- name = funcnameFromNameOff(funcInfo, ic.nameOff)
- startLine = ic.startLine
- // File/line from funcline1 below are already correct.
- }
+ // It's important that interpret pc non-strictly as cgoTraceback may
+ // have added bogus PCs with a valid funcInfo but invalid PCDATA.
+ u, uf := newInlineUnwinder(funcInfo, pc, nil)
+ sf := u.srcFunc(uf)
+ if u.isInlined(uf) {
+ // Note: entry is not modified. It always refers to a real frame, not an inlined one.
+ // File/line from funcline1 below are already correct.
+ f = nil
}
ci.frames = append(ci.frames, Frame{
PC: pc,
Func: f,
- Function: name,
+ Function: sf.name(),
Entry: entry,
- startLine: int(startLine),
+ startLine: int(sf.startLine),
funcInfo: funcInfo,
// Note: File,Line set below
})
@@ -182,6 +175,8 @@ func runtime_FrameStartLine(f *Frame) int {
//
//go:linkname runtime_expandFinalInlineFrame runtime/pprof.runtime_expandFinalInlineFrame
func runtime_expandFinalInlineFrame(stk []uintptr) []uintptr {
+ // TODO: It would be more efficient to report only physical PCs to pprof and
+ // just expand the whole stack.
if len(stk) == 0 {
return stk
}
@@ -194,46 +189,29 @@ func runtime_expandFinalInlineFrame(stk []uintptr) []uintptr {
return stk
}
- inldata := funcdata(f, _FUNCDATA_InlTree)
- if inldata == nil {
- // Nothing inline in f.
+ var cache pcvalueCache
+ u, uf := newInlineUnwinder(f, tracepc, &cache)
+ if !u.isInlined(uf) {
+ // Nothing inline at tracepc.
return stk
}
// Treat the previous func as normal. We haven't actually checked, but
// since this pc was included in the stack, we know it shouldn't be
// elided.
- lastFuncID := funcID_normal
+ calleeID := funcID_normal
// Remove pc from stk; we'll re-add it below.
stk = stk[:len(stk)-1]
- // See inline expansion in gentraceback.
- var cache pcvalueCache
- inltree := (*[1 << 20]inlinedCall)(inldata)
- for {
- // Non-strict as cgoTraceback may have added bogus PCs
- // with a valid funcInfo but invalid PCDATA.
- ix := pcdatavalue1(f, _PCDATA_InlTreeIndex, tracepc, &cache, false)
- if ix < 0 {
- break
- }
- if inltree[ix].funcID == funcID_wrapper && elideWrapperCalling(lastFuncID) {
+ for ; uf.valid(); uf = u.next(uf) {
+ funcID := u.srcFunc(uf).funcID
+ if funcID == funcID_wrapper && elideWrapperCalling(calleeID) {
// ignore wrappers
} else {
- stk = append(stk, pc)
+ stk = append(stk, uf.pc+1)
}
- lastFuncID = inltree[ix].funcID
- // Back up to an instruction in the "caller".
- tracepc = f.entry() + uintptr(inltree[ix].parentPc)
- pc = tracepc + 1
- }
-
- // N.B. we want to keep the last parentPC which is not inline.
- if f.funcID == funcID_wrapper && elideWrapperCalling(lastFuncID) {
- // Ignore wrapper functions (except when they trigger panics).
- } else {
- stk = append(stk, pc)
+ calleeID = funcID
}
return stk
@@ -752,28 +730,25 @@ func FuncForPC(pc uintptr) *Func {
if !f.valid() {
return nil
}
- if inldata := funcdata(f, _FUNCDATA_InlTree); inldata != nil {
- // Note: strict=false so bad PCs (those between functions) don't crash the runtime.
- // We just report the preceding function in that situation. See issue 29735.
- // TODO: Perhaps we should report no function at all in that case.
- // The runtime currently doesn't have function end info, alas.
- if ix := pcdatavalue1(f, _PCDATA_InlTreeIndex, pc, nil, false); ix >= 0 {
- inltree := (*[1 << 20]inlinedCall)(inldata)
- ic := inltree[ix]
- name := funcnameFromNameOff(f, ic.nameOff)
- file, line := funcline(f, pc)
- fi := &funcinl{
- ones: ^uint32(0),
- entry: f.entry(), // entry of the real (the outermost) function.
- name: name,
- file: file,
- line: line,
- startLine: ic.startLine,
- }
- return (*Func)(unsafe.Pointer(fi))
- }
+ // This must interpret PC non-strictly so bad PCs (those between functions) don't crash the runtime.
+ // We just report the preceding function in that situation. See issue 29735.
+ // TODO: Perhaps we should report no function at all in that case.
+ // The runtime currently doesn't have function end info, alas.
+ u, uf := newInlineUnwinder(f, pc, nil)
+ if !u.isInlined(uf) {
+ return f._Func()
}
- return f._Func()
+ sf := u.srcFunc(uf)
+ file, line := u.fileLine(uf)
+ fi := &funcinl{
+ ones: ^uint32(0),
+ entry: f.entry(), // entry of the real (the outermost) function.
+ name: sf.name(),
+ file: file,
+ line: int32(line),
+ startLine: sf.startLine,
+ }
+ return (*Func)(unsafe.Pointer(fi))
}
// Name returns the name of the function.
@@ -1059,13 +1034,6 @@ func funcpkgpath(f funcInfo) string {
return name[:i]
}
-func funcnameFromNameOff(f funcInfo, nameOff int32) string {
- if !f.valid() {
- return ""
- }
- return f.datap.funcName(nameOff)
-}
-
func funcfile(f funcInfo, fileno int32) string {
datap := f.datap
if !f.valid() {