From 389a070437f76bef36c6b7c090f1e453fe343a76 Mon Sep 17 00:00:00 2001 From: thorpej Date: Tue, 23 Nov 2021 18:45:53 +0000 Subject: [PATCH] Decorate the ARM signal trampoline with the appropriate .cfi directives to allow exception unwind / backtrace across a signal handler. --- lib/libc/arch/arm/genassym.cf | 37 ++++++++++++++++----------- lib/libc/arch/arm/sys/__sigtramp2.S | 39 +++++++++++++++++++++++++++-- 2 files changed, 60 insertions(+), 16 deletions(-) diff --git a/lib/libc/arch/arm/genassym.cf b/lib/libc/arch/arm/genassym.cf index ef4be91816ac..a87a748b6780 100644 --- a/lib/libc/arch/arm/genassym.cf +++ b/lib/libc/arch/arm/genassym.cf @@ -1,4 +1,4 @@ -# $NetBSD: genassym.cf,v 1.3 2020/10/24 07:03:11 skrll Exp $ +# $NetBSD: genassym.cf,v 1.4 2021/11/23 18:45:53 thorpej Exp $ # # Copyright (c) 2012 The NetBSD Foundation, Inc. @@ -30,21 +30,30 @@ # include +include include +define _UC_GREGS offsetof(ucontext_t, uc_mcontext.__gregs[0]) define _UC_REGS_R0 offsetof(ucontext_t, uc_mcontext.__gregs[_REG_R0]) -define _UC_REGS_R1 offsetof(ucontext_t, uc_mcontext.__gregs[_REG_R1]) -define _UC_REGS_R2 offsetof(ucontext_t, uc_mcontext.__gregs[_REG_R2]) -define _UC_REGS_R3 offsetof(ucontext_t, uc_mcontext.__gregs[_REG_R3]) -define _UC_REGS_R4 offsetof(ucontext_t, uc_mcontext.__gregs[_REG_R4]) -define _UC_REGS_R5 offsetof(ucontext_t, uc_mcontext.__gregs[_REG_R5]) -define _UC_REGS_R6 offsetof(ucontext_t, uc_mcontext.__gregs[_REG_R6]) -define _UC_REGS_R7 offsetof(ucontext_t, uc_mcontext.__gregs[_REG_R7]) -define _UC_REGS_R8 offsetof(ucontext_t, uc_mcontext.__gregs[_REG_R8]) -define _UC_REGS_R9 offsetof(ucontext_t, uc_mcontext.__gregs[_REG_R9]) -define _UC_REGS_R10 offsetof(ucontext_t, uc_mcontext.__gregs[_REG_R10]) -define _UC_REGS_R11 offsetof(ucontext_t, uc_mcontext.__gregs[_REG_R11]) -define _UC_REGS_R12 offsetof(ucontext_t, uc_mcontext.__gregs[_REG_R12]) define _UC_REGS_SP offsetof(ucontext_t, uc_mcontext.__gregs[_REG_SP]) -define _UC_REGS_LR offsetof(ucontext_t, uc_mcontext.__gregs[_REG_LR]) define _UC_REGS_PC offsetof(ucontext_t, uc_mcontext.__gregs[_REG_PC]) + +define SIZEOF_SIGINFO sizeof(siginfo_t) + +define _REG_R0 _REG_R0 +define _REG_R1 _REG_R1 +define _REG_R2 _REG_R2 +define _REG_R3 _REG_R3 +define _REG_R4 _REG_R4 +define _REG_R5 _REG_R5 +define _REG_R6 _REG_R6 +define _REG_R7 _REG_R7 +define _REG_R8 _REG_R8 +define _REG_R9 _REG_R9 +define _REG_R10 _REG_R10 +define _REG_R11 _REG_R11 +define _REG_R12 _REG_R12 +define _REG_R13 _REG_R13 +define _REG_R14 _REG_R14 +define _REG_R15 _REG_R15 +define _REG_SP _REG_SP diff --git a/lib/libc/arch/arm/sys/__sigtramp2.S b/lib/libc/arch/arm/sys/__sigtramp2.S index 4ee638e351ed..204aaa3d30d6 100755 --- a/lib/libc/arch/arm/sys/__sigtramp2.S +++ b/lib/libc/arch/arm/sys/__sigtramp2.S @@ -1,4 +1,4 @@ -/* $NetBSD: __sigtramp2.S,v 1.3 2013/08/16 23:20:59 matt Exp $ */ +/* $NetBSD: __sigtramp2.S,v 1.4 2021/11/23 18:45:53 thorpej Exp $ */ /*- * Copyright (c) 2002 The NetBSD Foundation, Inc. @@ -30,6 +30,7 @@ */ #include "SYS.h" +#include "assym.h" /* * The ARM signal trampoline is invoked only to return from @@ -39,12 +40,46 @@ * * ucontext structure * sp-> siginfo structure - * and r5 points to the ucontext + * and r5 points to the ucontext */ + +#define CFI_OFFSET(r) .cfi_offset r, r * 4 + + _TEXT_SECTION + .cfi_startproc + .cfi_signal_frame + .cfi_def_cfa _REG_SP, SIZEOF_SIGINFO + _UC_GREGS + CFI_OFFSET(_REG_R0) + CFI_OFFSET(_REG_R1) + CFI_OFFSET(_REG_R2) + CFI_OFFSET(_REG_R3) + CFI_OFFSET(_REG_R4) + CFI_OFFSET(_REG_R5) + CFI_OFFSET(_REG_R6) + CFI_OFFSET(_REG_R7) + CFI_OFFSET(_REG_R8) + CFI_OFFSET(_REG_R9) + CFI_OFFSET(_REG_R10) + CFI_OFFSET(_REG_R11) + CFI_OFFSET(_REG_R12) + CFI_OFFSET(_REG_R13) /* a.k.a. _REG_SP */ + CFI_OFFSET(_REG_R14) /* a.k.a. _REG_LR */ + .cfi_return_column _REG_R15 + CFI_OFFSET(_REG_R15) /* a.k.a. _REG_PC */ + +/* + * The unwind entry includes the one instruction prior to the trampoline + * because the unwinder will look up (return PC - 1) while unwinding. + * Normally this would be the jump / branch, but since there isn't one in + * this case, we place an explicit nop there instead. + */ + nop + ENTRY_NP(__sigtramp_siginfo_2) mov r0, r5 /* set the arg */ SYSTRAP(setcontext) /* and call setcontext */ /* If that failed, exit with the error code. */ SYSTRAP(exit) + .cfi_endproc END(__sigtramp_siginfo_2)