git: bf3a14b41a7b - main - linux(4): Fix stack unwinding on arm64 [1/2]

From: Dmitry Chagin <dchagin_at_FreeBSD.org>
Date: Sun, 14 May 2023 21:31:06 UTC
The branch main has been updated by dchagin:

URL: https://cgit.FreeBSD.org/src/commit/?id=bf3a14b41a7bfe8357a4672a8f901cfc887f3862

commit bf3a14b41a7bfe8357a4672a8f901cfc887f3862
Author:     Dmitry Chagin <dchagin@FreeBSD.org>
AuthorDate: 2023-05-14 21:24:57 +0000
Commit:     Dmitry Chagin <dchagin@FreeBSD.org>
CommitDate: 2023-05-14 21:24:57 +0000

    linux(4): Fix stack unwinding on arm64 [1/2]
    
    An Aarch64 sigreturn trampoline frame can't currently be described in
    a DWARF .eh_frame section, because Aarch64 does not define a register
    number for PC and provide no direct way to encode PC of the previous
    frame. Instead, unwinders (libgcc, gdb, libunwind) detect the sigreturn
    frame by looking for the sigreturn instruction. If a sigreturn frame is
    detected, unwinders restores all the gprs, SP and PC by assuming that
    sp points to an rt_sigframe Linux kernel struct
    When entering the kernel, the link register (lr) contains the return
    address of the previous frame, the exception link register (elr) contains
    the address of the next instruction after the one which generated the
    exception, i.e., PC.
    
    MFC after:              1 week
---
 sys/arm64/linux/linux_sysvec.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/sys/arm64/linux/linux_sysvec.c b/sys/arm64/linux/linux_sysvec.c
index a49e41c21525..b2853d8e8359 100644
--- a/sys/arm64/linux/linux_sysvec.c
+++ b/sys/arm64/linux/linux_sysvec.c
@@ -295,7 +295,7 @@ linux_rt_sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask)
 	memcpy(&frame->sf.sf_uc.uc_sc.regs, tf->tf_x, sizeof(tf->tf_x));
 	frame->sf.sf_uc.uc_sc.regs[30] = tf->tf_lr;
 	frame->sf.sf_uc.uc_sc.sp = tf->tf_sp;
-	frame->sf.sf_uc.uc_sc.pc = tf->tf_lr;
+	frame->sf.sf_uc.uc_sc.pc = tf->tf_elr;
 	frame->sf.sf_uc.uc_sc.pstate = tf->tf_spsr;
 	frame->sf.sf_uc.uc_sc.fault_address = (register_t)ksi->ksi_addr;