diff options
| author | Austin Clements <austin@google.com> | 2015-01-14 11:09:50 -0500 |
|---|---|---|
| committer | Austin Clements <austin@google.com> | 2015-02-02 19:36:05 +0000 |
| commit | 3c0fee10dbe82771dcaa956a95bdfabdced5fff7 (patch) | |
| tree | 67ece87374bc9a50bd912d1012b7f62cf50e6aa8 /src/runtime/asm_amd64.s | |
| parent | 20a6ff7261adecc1ba0dc3f3cd6a29054fdf90b7 (diff) | |
| download | go-3c0fee10dbe82771dcaa956a95bdfabdced5fff7.tar.xz | |
cmd/6g, liblink, runtime: support saving base pointers
This adds a "framepointer" GOEXPERIMENT that that makes the amd64
toolchain maintain base pointer chains in the same way that gcc
-fno-omit-frame-pointer does. Go doesn't use these saved base
pointers, but this does enable external tools like Linux perf and
VTune to unwind Go stacks when collecting system-wide profiles.
This requires support in the compilers to not clobber BP, support in
liblink for generating the BP-saving function prologue and unwinding
epilogue, and support in the runtime to save BPs across preemption, to
skip saved BPs during stack unwinding and, and to adjust saved BPs
during stack moving.
As with other GOEXPERIMENTs, everything from the toolchain to the
runtime must be compiled with this experiment enabled. To do this,
run make.bash (or all.bash) with GOEXPERIMENT=framepointer.
Change-Id: I4024853beefb9539949e5ca381adfdd9cfada544
Reviewed-on: https://go-review.googlesource.com/2992
Reviewed-by: Russ Cox <rsc@golang.org>
Diffstat (limited to 'src/runtime/asm_amd64.s')
| -rw-r--r-- | src/runtime/asm_amd64.s | 26 |
1 files changed, 23 insertions, 3 deletions
diff --git a/src/runtime/asm_amd64.s b/src/runtime/asm_amd64.s index b1bf4ca987..f09e5ae250 100644 --- a/src/runtime/asm_amd64.s +++ b/src/runtime/asm_amd64.s @@ -134,6 +134,7 @@ TEXT runtime·gosave(SB), NOSPLIT, $0-8 MOVQ BX, gobuf_pc(AX) MOVQ $0, gobuf_ret(AX) MOVQ $0, gobuf_ctxt(AX) + MOVQ BP, gobuf_bp(AX) get_tls(CX) MOVQ g(CX), BX MOVQ BX, gobuf_g(AX) @@ -150,9 +151,11 @@ TEXT runtime·gogo(SB), NOSPLIT, $0-8 MOVQ gobuf_sp(BX), SP // restore SP MOVQ gobuf_ret(BX), AX MOVQ gobuf_ctxt(BX), DX + MOVQ gobuf_bp(BX), BP MOVQ $0, gobuf_sp(BX) // clear to help garbage collector MOVQ $0, gobuf_ret(BX) MOVQ $0, gobuf_ctxt(BX) + MOVQ $0, gobuf_bp(BX) MOVQ gobuf_pc(BX), BX JMP BX @@ -170,6 +173,7 @@ TEXT runtime·mcall(SB), NOSPLIT, $0-8 LEAQ fn+0(FP), BX // caller's SP MOVQ BX, (g_sched+gobuf_sp)(AX) MOVQ AX, (g_sched+gobuf_g)(AX) + MOVQ BP, (g_sched+gobuf_bp)(AX) // switch to m->g0 & its stack, call fn MOVQ g(CX), BX @@ -228,6 +232,7 @@ switch: MOVQ SI, (g_sched+gobuf_pc)(AX) MOVQ SP, (g_sched+gobuf_sp)(AX) MOVQ AX, (g_sched+gobuf_g)(AX) + MOVQ BP, (g_sched+gobuf_bp)(AX) // switch to g0 MOVQ DX, g(CX) @@ -303,6 +308,7 @@ TEXT runtime·morestack(SB),NOSPLIT,$0-0 LEAQ 8(SP), AX // f's SP MOVQ AX, (g_sched+gobuf_sp)(SI) MOVQ DX, (g_sched+gobuf_ctxt)(SI) + MOVQ BP, (g_sched+gobuf_bp)(SI) // Call newstack on m->g0's stack. MOVQ m_g0(BX), BX @@ -592,6 +598,7 @@ TEXT gosave<>(SB),NOSPLIT,$0 MOVQ R9, (g_sched+gobuf_sp)(R8) MOVQ $0, (g_sched+gobuf_ret)(R8) MOVQ $0, (g_sched+gobuf_ctxt)(R8) + MOVQ BP, (g_sched+gobuf_bp)(R8) RET // asmcgocall(void(*fn)(void*), void *arg) @@ -747,17 +754,30 @@ havem: MOVQ (g_sched+gobuf_sp)(SI), DI // prepare stack as DI MOVQ (g_sched+gobuf_pc)(SI), BX MOVQ BX, -8(DI) - LEAQ -(8+8)(DI), SP + // Compute the size of the frame, including return PC and, if + // GOEXPERIMENT=framepointer, the saved based pointer + LEAQ x+0(FP), AX + SUBQ SP, AX + SUBQ AX, DI + MOVQ DI, SP + MOVQ R8, 0(SP) CALL runtime·cgocallbackg(SB) MOVQ 0(SP), R8 + // Compute the size of the frame again. FP and SP have + // completely different values here than they did above, + // but only their difference matters. + LEAQ x+0(FP), AX + SUBQ SP, AX + // Restore g->sched (== m->curg->sched) from saved values. get_tls(CX) MOVQ g(CX), SI - MOVQ 8(SP), BX + MOVQ SP, DI + ADDQ AX, DI + MOVQ -8(DI), BX MOVQ BX, (g_sched+gobuf_pc)(SI) - LEAQ (8+8)(SP), DI MOVQ DI, (g_sched+gobuf_sp)(SI) // Switch back to m->g0's stack and restore m->g0->sched.sp. |
