aboutsummaryrefslogtreecommitdiff
path: root/src/runtime/panic.go
diff options
context:
space:
mode:
authorAustin Clements <austin@google.com>2018-01-31 17:34:22 -0500
committerAustin Clements <austin@google.com>2018-02-13 21:01:25 +0000
commit615d44c287a9c8a5f1062dd24ba341d806abc944 (patch)
tree23cb45d41b62fcd1c539ae067b33aadb05606031 /src/runtime/panic.go
parentb1679e4d03268a6792e6b8d573ac31080d9d9baf (diff)
downloadgo-615d44c287a9c8a5f1062dd24ba341d806abc944.tar.xz
runtime: refactor test for pushing sigpanic frame
This logic is duplicated in all of the preparePanic functions. Pull it out into one architecture-independent function. Change-Id: I7ef4e78e3eda0b7be1a480fb5245fc7424fb2b4e Reviewed-on: https://go-review.googlesource.com/91255 Run-TryBot: Austin Clements <austin@google.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Ian Lance Taylor <iant@golang.org>
Diffstat (limited to 'src/runtime/panic.go')
-rw-r--r--src/runtime/panic.go33
1 files changed, 33 insertions, 0 deletions
diff --git a/src/runtime/panic.go b/src/runtime/panic.go
index c51948bd18..e1477e2486 100644
--- a/src/runtime/panic.go
+++ b/src/runtime/panic.go
@@ -786,3 +786,36 @@ func canpanic(gp *g) bool {
}
return true
}
+
+// shouldPushSigpanic returns true if pc should be used as sigpanic's
+// return PC (pushing a frame for the call). Otherwise, it should be
+// left alone so that LR is used as sigpanic's return PC, effectively
+// replacing the top-most frame with sigpanic. This is used by
+// preparePanic.
+func shouldPushSigpanic(gp *g, pc, lr uintptr) bool {
+ if pc == 0 {
+ // Probably a call to a nil func. The old LR is more
+ // useful in the stack trace. Not pushing the frame
+ // will make the trace look like a call to sigpanic
+ // instead. (Otherwise the trace will end at sigpanic
+ // and we won't get to see who faulted.)
+ return false
+ }
+ // If we don't recognize the PC as code, but we do recognize
+ // the link register as code, then this assumes the panic was
+ // caused by a call to non-code. In this case, we want to
+ // ignore this call to make unwinding show the context.
+ if findfunc(pc).valid() {
+ // This wasn't a bad call, so use PC as sigpanic's
+ // return PC.
+ return true
+ }
+ if findfunc(lr).valid() {
+ // This was a bad call, but the LR is good, so use the
+ // LR as sigpanic's return PC.
+ return false
+ }
+ // Neither the PC or LR is good. Hopefully pushing a frame
+ // will work.
+ return true
+}