diff options
| author | Russ Cox <rsc@golang.org> | 2014-06-12 16:34:54 -0400 |
|---|---|---|
| committer | Russ Cox <rsc@golang.org> | 2014-06-12 16:34:54 -0400 |
| commit | 597f87c997dcaa86227725e227f5eb59721a0129 (patch) | |
| tree | 0ab53e0b2f463efe01cb4dc43a0c1f2531ab298a /src/pkg/runtime/traceback_arm.c | |
| parent | 36207a91d3c97a9c64984572af89727495310469 (diff) | |
| download | go-597f87c997dcaa86227725e227f5eb59721a0129.tar.xz | |
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
Diffstat (limited to 'src/pkg/runtime/traceback_arm.c')
| -rw-r--r-- | src/pkg/runtime/traceback_arm.c | 13 |
1 files changed, 13 insertions, 0 deletions
diff --git a/src/pkg/runtime/traceback_arm.c b/src/pkg/runtime/traceback_arm.c index 8d1fc54266..d15244c2a9 100644 --- a/src/pkg/runtime/traceback_arm.c +++ b/src/pkg/runtime/traceback_arm.c @@ -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; |
