diff --git a/sysdeps/unix/sysv/linux/aarch64/uw-sigframe.h b/sysdeps/unix/sysv/linux/aarch64/uw-sigframe.h new file mode 100644 index 0000000000..3a77c23369 --- /dev/null +++ b/sysdeps/unix/sysv/linux/aarch64/uw-sigframe.h @@ -0,0 +1,78 @@ +/* Signal frame backtracing support for SFrame on AARCH64. + Copyright (C) 2025 Free Software Foundation, Inc. + + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License + as published by the Free Software Foundation; either version 2.1 of + the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +/* This code is inspired from libgcc's MD_FALLBACK_FRAME_STATE_FOR + implementation. See libgcc/config/aarch64/linux-unwind.h */ + +#include +#include +#include + +#if __AARCH64EL__ +#define MOVZ_X8_8B 0xd2801168 +#define SVC_0 0xd4000001 +#else +#define MOVZ_X8_8B 0x681180d2 +#define SVC_0 0x010000d4 +#endif + +#define MD_DECODE_SIGNAL_FRAME aarch64_decode_signal_frame + +static _Unwind_Reason_Code +aarch64_decode_signal_frame (frame *frame) +{ + unsigned int *pc = (unsigned int *) frame->pc; + mcontext_t *mt; + struct kernel_rt_sigframe *rt_; + + if ((frame->pc & 3) != 0) + return _URC_END_OF_STACK; + + /* A signal frame will have a return address pointing to + __kernel_rt_sigreturn. This code is hardwired as: + + 0xd2801168 movz x8, #0x8b + 0xd4000001 svc 0x0 + */ + if (pc[0] != MOVZ_X8_8B || pc[1] != SVC_0) + return _URC_END_OF_STACK; + + rt_ = (struct kernel_rt_sigframe *) frame->sp; + mt = &rt_->uc.uc_mcontext; + + /* Frame pointer register number. */ +#define FP_REGNUM 30 + + frame->pc = (_Unwind_Ptr) mt->pc; + frame->sp = (_Unwind_Ptr) mt->sp; + frame->fp = (_Unwind_Ptr) mt->regs[FP_REGNUM]; + return _URC_NO_REASON; +} + +#define MD_DETECT_OUTERMOST_FRAME aarch64_detect_outermost_frame + +static _Unwind_Reason_Code +aarch64_detect_outermost_frame (frame *frame) +{ + /* Initial frame has LR and FP set to zero. We track only FP. */ + if (frame->fp == 0) + return _URC_END_OF_STACK; + + return _URC_NO_REASON; +}