diff options
author | Austin Clements <austin@google.com> | 2017-11-09 17:55:45 -0500 |
---|---|---|
committer | Austin Clements <austin@google.com> | 2017-11-13 21:43:44 +0000 |
commit | 032678e0fb0a5e0471a6555b758ca4d960249013 (patch) | |
tree | af8918e06402fd57b5bd53249b7ef06319d66638 /src/runtime/symtab.go | |
parent | e8905d2a66caf970d1f8e79d8101e6a670012447 (diff) | |
download | go-032678e0fb0a5e0471a6555b758ca4d960249013.tar.gz go-032678e0fb0a5e0471a6555b758ca4d960249013.zip |
runtime: don't elide wrapper functions that call panic or at TOS
CL 45412 started hiding autogenerated wrapper functions from call
stacks so that call stack semantics better matched language semantics.
This is based on the theory that the wrapper function will call the
"real" function and all the programmer knows about is the real
function.
However, this theory breaks down in two cases:
1. If the wrapper is at the top of the stack, then it didn't call
anything. This can happen, for example, if the "stack" was actually
synthesized by the user.
2. If the wrapper panics, for example by calling panicwrap or by
dereferencing a nil pointer, then it didn't call the wrapped
function and the user needs to see what panicked, even if we can't
attribute it nicely.
This commit modifies the traceback logic to include the wrapper
function in both of these cases.
Fixes #22231.
Change-Id: I6e4339a652f73038bd8331884320f0b8edd86eb1
Reviewed-on: https://go-review.googlesource.com/76770
Run-TryBot: Austin Clements <austin@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Keith Randall <khr@golang.org>
Diffstat (limited to 'src/runtime/symtab.go')
-rw-r--r-- | src/runtime/symtab.go | 12 |
1 files changed, 9 insertions, 3 deletions
diff --git a/src/runtime/symtab.go b/src/runtime/symtab.go index 135fc1a7ad..c6c2b89f69 100644 --- a/src/runtime/symtab.go +++ b/src/runtime/symtab.go @@ -19,6 +19,11 @@ type Frames struct { // stackExpander expands callers into a sequence of Frames, // tracking the necessary state across PCs. stackExpander stackExpander + + // elideWrapper indicates that, if the next frame is an + // autogenerated wrapper function, it should be elided from + // the stack. + elideWrapper bool } // Frame is the information returned by Frames for each call frame. @@ -112,11 +117,12 @@ func (se *stackExpander) init(callers []uintptr) []uintptr { // Next returns frame information for the next caller. // If more is false, there are no more callers (the Frame value is valid). func (ci *Frames) Next() (frame Frame, more bool) { - ci.callers, frame, more = ci.stackExpander.next(ci.callers) + ci.callers, frame, more = ci.stackExpander.next(ci.callers, ci.elideWrapper) + ci.elideWrapper = elideWrapperCalling(frame.Function) return } -func (se *stackExpander) next(callers []uintptr) (ncallers []uintptr, frame Frame, more bool) { +func (se *stackExpander) next(callers []uintptr, elideWrapper bool) (ncallers []uintptr, frame Frame, more bool) { ncallers = callers again: if !se.pcExpander.more { @@ -145,7 +151,7 @@ again: } frame = se.pcExpander.next() - if frame.File == "<autogenerated>" { + if elideWrapper && frame.File == "<autogenerated>" { // Ignore autogenerated functions such as pointer // method forwarding functions. These are an // implementation detail that doesn't reflect the |