}
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
+}
pc := uintptr(c.eip())
sp := uintptr(c.esp())
- // If we don't recognize the PC as code
- // but we do recognize the top pointer on the stack as code,
- // then assume this was a call to non-code and treat like
- // pc == 0, to make unwinding show the context.
- if pc != 0 && !findfunc(pc).valid() && findfunc(*(*uintptr)(unsafe.Pointer(sp))).valid() {
- pc = 0
- }
-
- // Only push runtime.sigpanic if pc != 0.
- // If pc == 0, probably panicked because of a
- // call to a nil func. Not pushing that onto sp will
- // make the trace look like a call to runtime.sigpanic instead.
- // (Otherwise the trace will end at runtime.sigpanic and we
- // won't get to see who faulted.)
- if pc != 0 {
+ if shouldPushSigpanic(gp, pc, *(*uintptr)(unsafe.Pointer(sp))) {
+ // Make it look like the faulting PC called sigpanic.
if sys.RegSize > sys.PtrSize {
sp -= sys.PtrSize
*(*uintptr)(unsafe.Pointer(sp)) = 0
pc := uintptr(c.rip())
sp := uintptr(c.rsp())
- // If we don't recognize the PC as code
- // but we do recognize the top pointer on the stack as code,
- // then assume this was a call to non-code and treat like
- // pc == 0, to make unwinding show the context.
- if pc != 0 && !findfunc(pc).valid() && findfunc(*(*uintptr)(unsafe.Pointer(sp))).valid() {
- pc = 0
- }
-
- // Only push runtime.sigpanic if pc != 0.
- // If pc == 0, probably panicked because of a
- // call to a nil func. Not pushing that onto sp will
- // make the trace look like a call to runtime.sigpanic instead.
- // (Otherwise the trace will end at runtime.sigpanic and we
- // won't get to see who faulted.)
- if pc != 0 {
+ if shouldPushSigpanic(gp, pc, *(*uintptr)(unsafe.Pointer(sp))) {
+ // Make it look the like faulting PC called sigpanic.
if sys.RegSize > sys.PtrSize {
sp -= sys.PtrSize
*(*uintptr)(unsafe.Pointer(sp)) = 0
pc := gp.sigpc
- // If we don't recognize the PC as code
- // but we do recognize the link register as code,
- // then assume this was a call to non-code and treat like
- // pc == 0, to make unwinding show the context.
- if pc != 0 && !findfunc(pc).valid() && findfunc(uintptr(c.lr())).valid() {
- pc = 0
- }
-
- // Don't bother saving PC if it's zero, which is
- // probably a call to a nil func: the old link register
- // is more useful in the stack trace.
- if pc != 0 {
+ if shouldPushSigpanic(gp, pc, uintptr(c.lr())) {
+ // Make it look the like faulting PC called sigpanic.
c.set_lr(uint32(pc))
}
pc := gp.sigpc
- // If we don't recognize the PC as code
- // but we do recognize the link register as code,
- // then assume this was a call to non-code and treat like
- // pc == 0, to make unwinding show the context.
- if pc != 0 && !findfunc(pc).valid() && findfunc(uintptr(c.lr())).valid() {
- pc = 0
- }
-
- // Don't bother saving PC if it's zero, which is
- // probably a call to a nil func: the old link register
- // is more useful in the stack trace.
- if pc != 0 {
+ if shouldPushSigpanic(gp, pc, uintptr(c.lr())) {
+ // Make it look the like faulting PC called sigpanic.
c.set_lr(uint64(pc))
}
pc := uintptr(gp.sigpc)
- // If we don't recognize the PC as code
- // but we do recognize the link register as code,
- // then assume this was a call to non-code and treat like
- // pc == 0, to make unwinding show the context.
- if pc != 0 && !findfunc(pc).valid() && findfunc(uintptr(c.link())).valid() {
- pc = 0
- }
-
- // Don't bother saving PC if it's zero, which is
- // probably a call to a nil func: the old link register
- // is more useful in the stack trace.
- if pc != 0 {
+ if shouldPushSigpanic(gp, pc, uintptr(c.link())) {
+ // Make it look the like faulting PC called sigpanic.
c.set_link(uint64(pc))
}
pc := gp.sigpc
- // If we don't recognize the PC as code
- // but we do recognize the link register as code,
- // then assume this was a call to non-code and treat like
- // pc == 0, to make unwinding show the context.
- if pc != 0 && !findfunc(pc).valid() && findfunc(uintptr(c.link())).valid() {
- pc = 0
- }
-
- // Don't bother saving PC if it's zero, which is
- // probably a call to a nil func: the old link register
- // is more useful in the stack trace.
- if pc != 0 {
+ if shouldPushSigpanic(gp, pc, uintptr(c.link())) {
+ // Make it look the like faulting PC called sigpanic.
c.set_link(uint64(pc))
}
pc := gp.sigpc
- // If we don't recognize the PC as code
- // but we do recognize the link register as code,
- // then assume this was a call to non-code and treat like
- // pc == 0, to make unwinding show the context.
- if pc != 0 && !findfunc(pc).valid() && findfunc(uintptr(c.link())).valid() {
- pc = 0
- }
-
- // Don't bother saving PC if it's zero, which is
- // probably a call to a nil func: the old link register
- // is more useful in the stack trace.
- if pc != 0 {
+ if shouldPushSigpanic(gp, pc, uintptr(c.link())) {
+ // Make it look the like faulting PC called sigpanic.
c.set_link(uint32(pc))
}
pc := gp.sigpc
- // If we don't recognize the PC as code
- // but we do recognize the link register as code,
- // then assume this was a call to non-code and treat like
- // pc == 0, to make unwinding show the context.
- if pc != 0 && !findfunc(pc).valid() && findfunc(uintptr(c.link())).valid() {
- pc = 0
- }
-
- // Don't bother saving PC if it's zero, which is
- // probably a call to a nil func: the old link register
- // is more useful in the stack trace.
- if pc != 0 {
+ if shouldPushSigpanic(gp, pc, uintptr(c.link())) {
+ // Make it look the like faulting PC called sigpanic.
c.set_link(uint64(pc))
}