mirror of
https://github.com/golang/go
synced 2024-09-30 05:07:17 +00:00
[release-branch.go1.3] runtime: do not trace past jmpdefer during pprof traceback on arm
««« CL 107970043 / b336da131a84 runtime: do not trace past jmpdefer during pprof traceback on arm jmpdefer modifies PC, SP, and LR, and not atomically, so walking past jmpdefer will often end up in a state where the three are not a consistent execution snapshot. This was causing warning messages a few frames later when the traceback realized it was confused, but given the right memory it could easily crash instead. Update #8153 LGTM=minux, iant R=golang-codereviews, minux, iant CC=golang-codereviews, r https://golang.org/cl/107970043 »»» LGTM=r R=golang-codereviews, r CC=adg, golang-codereviews, iant https://golang.org/cl/101260043
This commit is contained in:
parent
5c196b842a
commit
1305c4ce9d
|
@ -394,6 +394,10 @@ TEXT runtime·lessstack(SB), NOSPLIT, $-4-0
|
|||
// 1. grab stored LR for caller
|
||||
// 2. sub 4 bytes to get back to BL deferreturn
|
||||
// 3. B to fn
|
||||
// TODO(rsc): Push things on stack and then use pop
|
||||
// to load all registers simultaneously, so that a profiling
|
||||
// interrupt can never see mismatched SP/LR/PC.
|
||||
// (And double-check that pop is atomic in that way.)
|
||||
TEXT runtime·jmpdefer(SB), NOSPLIT, $0-8
|
||||
MOVW 0(SP), LR
|
||||
MOVW $-4(LR), LR // BL deferreturn
|
||||
|
|
|
@ -110,6 +110,19 @@ runtime·gentraceback(uintptr pc0, uintptr sp0, uintptr lr0, G *gp, int32 skip,
|
|||
if(runtime·topofstack(f)) {
|
||||
frame.lr = 0;
|
||||
flr = nil;
|
||||
} else if(f->entry == (uintptr)runtime·jmpdefer) {
|
||||
// jmpdefer modifies SP/LR/PC non-atomically.
|
||||
// If a profiling interrupt arrives during jmpdefer,
|
||||
// the stack unwind may see a mismatched register set
|
||||
// and get confused. Stop if we see PC within jmpdefer
|
||||
// to avoid that confusion.
|
||||
// See golang.org/issue/8153.
|
||||
// This check can be deleted if jmpdefer is changed
|
||||
// to restore all three atomically using pop.
|
||||
if(callback != nil)
|
||||
runtime·throw("traceback_arm: found jmpdefer when tracing with callback");
|
||||
frame.lr = 0;
|
||||
flr = nil;
|
||||
} else {
|
||||
if((n == 0 && frame.sp < frame.fp) || frame.lr == 0)
|
||||
frame.lr = *(uintptr*)frame.sp;
|
||||
|
|
Loading…
Reference in a new issue