@@ -537,7 +537,7 @@ var ptrnames = []string{
537
537
// +------------------+ <- frame->argp
538
538
// | return address |
539
539
// +------------------+
540
- // | caller's BP (*) | (*) if framepointer_enabled && varp < sp
540
+ // | caller's BP (*) | (*) if framepointer_enabled && varp > sp
541
541
// +------------------+ <- frame->varp
542
542
// | locals |
543
543
// +------------------+
@@ -549,13 +549,18 @@ var ptrnames = []string{
549
549
// | args from caller |
550
550
// +------------------+ <- frame->argp
551
551
// | caller's retaddr |
552
+ // +------------------+
553
+ // | caller's FP (*) | (*) on ARM64, if framepointer_enabled && varp > sp
552
554
// +------------------+ <- frame->varp
553
555
// | locals |
554
556
// +------------------+
555
557
// | args to callee |
556
558
// +------------------+
557
559
// | return address |
558
560
// +------------------+ <- frame->sp
561
+ //
562
+ // varp > sp means that the function has a frame;
563
+ // varp == sp means frameless function.
559
564
560
565
type adjustinfo struct {
561
566
old stack
@@ -673,9 +678,8 @@ func adjustframe(frame *stkframe, adjinfo *adjustinfo) {
673
678
adjustpointers (unsafe .Pointer (frame .varp - size ), & locals , adjinfo , f )
674
679
}
675
680
676
- // Adjust saved base pointer if there is one.
677
- // TODO what about arm64 frame pointer adjustment?
678
- if goarch .ArchFamily == goarch .AMD64 && frame .argp - frame .varp == 2 * goarch .PtrSize {
681
+ // Adjust saved frame pointer if there is one.
682
+ if (goarch .ArchFamily == goarch .AMD64 || goarch .ArchFamily == goarch .ARM64 ) && frame .argp - frame .varp == 2 * goarch .PtrSize {
679
683
if stackDebug >= 3 {
680
684
print (" saved bp\n " )
681
685
}
@@ -689,6 +693,10 @@ func adjustframe(frame *stkframe, adjinfo *adjustinfo) {
689
693
throw ("bad frame pointer" )
690
694
}
691
695
}
696
+ // On AMD64, this is the caller's frame pointer saved in the current
697
+ // frame.
698
+ // On ARM64, this is the frame pointer of the caller's caller saved
699
+ // by the caller in its frame (one word below its SP).
692
700
adjustpointer (adjinfo , unsafe .Pointer (frame .varp ))
693
701
}
694
702
@@ -750,7 +758,17 @@ func adjustctxt(gp *g, adjinfo *adjustinfo) {
750
758
throw ("bad top frame pointer" )
751
759
}
752
760
}
761
+ oldfp := gp .sched .bp
753
762
adjustpointer (adjinfo , unsafe .Pointer (& gp .sched .bp ))
763
+ if GOARCH == "arm64" {
764
+ // On ARM64, the frame pointer is saved one word *below* the SP,
765
+ // which is not copied or adjusted in any frame. Do it explicitly
766
+ // here.
767
+ if oldfp == gp .sched .sp - goarch .PtrSize {
768
+ memmove (unsafe .Pointer (gp .sched .bp ), unsafe .Pointer (oldfp ), goarch .PtrSize )
769
+ adjustpointer (adjinfo , unsafe .Pointer (gp .sched .bp ))
770
+ }
771
+ }
754
772
}
755
773
756
774
func adjustdefers (gp * g , adjinfo * adjustinfo ) {
0 commit comments