@@ -425,11 +425,14 @@ TEXT gogo<>(SB), NOSPLIT, $0
425
425
// Switch to m->g0's stack, call fn(g).
426
426
// Fn must never return. It should gogo(&g->sched)
427
427
// to keep running g.
428
- TEXT runtime·mcall<ABIInternal> (SB), NOSPLIT|NOFRAME , $0 -8
428
+ TEXT runtime·mcall<ABIInternal> (SB), NOSPLIT, $0 -8
429
429
MOVQ AX, DX // DX = fn
430
430
431
- // save state in g->sched
432
- MOVQ 0 (SP), BX // caller's PC
431
+ // Save state in g->sched.
432
+ // The original frame pointer is stored in BP,
433
+ // which is useful for stack unwinding.
434
+ MOVQ SP, BX // hide (SP) reads from vet
435
+ MOVQ 8 (BX), BX // caller's PC
433
436
MOVQ BX, (g_sched+gobuf_pc)(R14)
434
437
LEAQ fn+0 (FP), BX // caller's SP
435
438
MOVQ BX, (g_sched+gobuf_sp)(R14)
@@ -459,11 +462,17 @@ goodm:
459
462
// lives at the bottom of the G stack from the one that lives
460
463
// at the top of the system stack because the one at the top of
461
464
// the system stack terminates the stack walk (see topofstack()).
465
+ // The frame layout needs to match systemstack
466
+ // so that it can pretend to be systemstack_switch.
462
467
TEXT runtime·systemstack_switch(SB), NOSPLIT, $0 -0
468
+ UNDEF
469
+ // Make sure this function is not leaf,
470
+ // so the frame is saved.
471
+ CALL runtime·abort(SB)
463
472
RET
464
473
465
474
// func systemstack(fn func())
466
- TEXT runtime·systemstack(SB), NOSPLIT|NOFRAME , $0 -8
475
+ TEXT runtime·systemstack(SB), NOSPLIT, $0 -8
467
476
MOVQ fn+0 (FP), DI // DI = fn
468
477
get_tls(CX)
469
478
MOVQ g(CX), AX // AX = g
@@ -479,16 +488,17 @@ TEXT runtime·systemstack(SB), NOSPLIT|NOFRAME, $0-8
479
488
CMPQ AX, m_curg(BX)
480
489
JNE bad
481
490
482
- // switch stacks
483
- // save our state in g->sched. Pretend to
491
+ // Switch stacks.
492
+ // The original frame pointer is stored in BP,
493
+ // which is useful for stack unwinding.
494
+ // Save our state in g->sched. Pretend to
484
495
// be systemstack_switch if the G stack is scanned.
485
496
CALL gosave_systemstack_switch<>(SB)
486
497
487
498
// switch to g0
488
499
MOVQ DX, g(CX)
489
500
MOVQ DX, R14 // set the g register
490
- MOVQ (g_sched+gobuf_sp)(DX), BX
491
- MOVQ BX, SP
501
+ MOVQ (g_sched+gobuf_sp)(DX), SP
492
502
493
503
// call target function
494
504
MOVQ DI, DX
@@ -502,7 +512,9 @@ TEXT runtime·systemstack(SB), NOSPLIT|NOFRAME, $0-8
502
512
MOVQ m_curg(BX), AX
503
513
MOVQ AX, g(CX)
504
514
MOVQ (g_sched+gobuf_sp)(AX), SP
515
+ MOVQ (g_sched+gobuf_bp)(AX), BP
505
516
MOVQ $0 , (g_sched+gobuf_sp)(AX)
517
+ MOVQ $0 , (g_sched+gobuf_bp)(AX)
506
518
RET
507
519
508
520
noswitch:
@@ -511,6 +523,9 @@ noswitch:
511
523
// at an intermediate systemstack.
512
524
MOVQ DI, DX
513
525
MOVQ 0 (DI), DI
526
+ // The function epilogue is not called on a tail call.
527
+ // Pop BP from the stack to simulate it.
528
+ POPQ BP
514
529
JMP DI
515
530
516
531
bad:
@@ -571,6 +586,7 @@ TEXT runtime·morestack(SB),NOSPLIT|NOFRAME,$0-0
571
586
MOVQ m_g0(BX), BX
572
587
MOVQ BX, g(CX)
573
588
MOVQ (g_sched+gobuf_sp)(BX), SP
589
+ MOVQ (g_sched+gobuf_bp)(BX), BP
574
590
CALL runtime·newstack(SB)
575
591
CALL runtime·abort(SB) // crash if newstack returns
576
592
RET
@@ -769,11 +785,15 @@ TEXT ·publicationBarrier<ABIInternal>(SB),NOSPLIT,$0-0
769
785
770
786
// Save state of caller into g->sched,
771
787
// but using fake PC from systemstack_switch.
772
- // Must only be called from functions with no locals ($0)
773
- // or else unwinding from systemstack_switch is incorrect.
788
+ // Must only be called from functions with frame pointer
789
+ // and without locals ($0) or else unwinding from
790
+ // systemstack_switch is incorrect.
774
791
// Smashes R9.
775
792
TEXT gosave_systemstack_switch<>(SB),NOSPLIT|NOFRAME,$0
776
- MOVQ $runtime·systemstack_switch(SB), R9
793
+ // Take systemstack_switch PC and add 8 bytes to skip
794
+ // the prologue. The final location does not matter
795
+ // as long as we are between the prologue and the epilogue.
796
+ MOVQ $runtime·systemstack_switch+8 (SB), R9
777
797
MOVQ R9, (g_sched+gobuf_pc)(R14)
778
798
LEAQ 8 (SP), R9
779
799
MOVQ R9, (g_sched+gobuf_sp)(R14)
@@ -789,11 +809,10 @@ TEXT gosave_systemstack_switch<>(SB),NOSPLIT|NOFRAME,$0
789
809
// func asmcgocall_no_g(fn, arg unsafe.Pointer)
790
810
// Call fn(arg) aligned appropriately for the gcc ABI.
791
811
// Called on a system stack, and there may be no g yet (during needm).
792
- TEXT ·asmcgocall_no_g(SB),NOSPLIT|NOFRAME, $0 -16
812
+ TEXT ·asmcgocall_no_g(SB),NOSPLIT, $32 -16
793
813
MOVQ fn+0 (FP), AX
794
814
MOVQ arg+8 (FP), BX
795
815
MOVQ SP, DX
796
- SUBQ $32 , SP
797
816
ANDQ $~15 , SP // alignment
798
817
MOVQ DX, 8 (SP)
799
818
MOVQ BX, DI // DI = first argument in AMD64 ABI
@@ -807,7 +826,7 @@ TEXT ·asmcgocall_no_g(SB),NOSPLIT|NOFRAME,$0-16
807
826
// Call fn(arg) on the scheduler stack,
808
827
// aligned appropriately for the gcc ABI.
809
828
// See cgocall.go for more details.
810
- TEXT ·asmcgocall(SB),NOSPLIT|NOFRAME ,$0 -20
829
+ TEXT ·asmcgocall(SB),NOSPLIT,$0 -20
811
830
MOVQ fn+0 (FP), AX
812
831
MOVQ arg+8 (FP), BX
813
832
@@ -830,6 +849,8 @@ TEXT ·asmcgocall(SB),NOSPLIT|NOFRAME,$0-20
830
849
JEQ nosave
831
850
832
851
// Switch to system stack.
852
+ // The original frame pointer is stored in BP,
853
+ // which is useful for stack unwinding.
833
854
CALL gosave_systemstack_switch<>(SB)
834
855
MOVQ SI, g(CX)
835
856
MOVQ (g_sched+gobuf_sp)(SI), SP
0 commit comments