1*0bfacb9bSmrg /* Copyright (C) 2016-2020 Free Software Foundation, Inc.
2ac8e35e1Smrg
3ac8e35e1Smrg This file is free software; you can redistribute it and/or modify it
4ac8e35e1Smrg under the terms of the GNU General Public License as published by the
5ac8e35e1Smrg Free Software Foundation; either version 3, or (at your option) any
6ac8e35e1Smrg later version.
7ac8e35e1Smrg
8ac8e35e1Smrg This file is distributed in the hope that it will be useful, but
9ac8e35e1Smrg WITHOUT ANY WARRANTY; without even the implied warranty of
10ac8e35e1Smrg MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11ac8e35e1Smrg General Public License for more details.
12ac8e35e1Smrg
13ac8e35e1Smrg Under Section 7 of GPL version 3, you are granted additional
14ac8e35e1Smrg permissions described in the GCC Runtime Library Exception, version
15ac8e35e1Smrg 3.1, as published by the Free Software Foundation.
16ac8e35e1Smrg
17ac8e35e1Smrg You should have received a copy of the GNU General Public License and
18ac8e35e1Smrg a copy of the GCC Runtime Library Exception along with this program;
19ac8e35e1Smrg see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
20ac8e35e1Smrg <http://www.gnu.org/licenses/>. */
21ac8e35e1Smrg
22ac8e35e1Smrg #ifndef inhibit_libc
23ac8e35e1Smrg
24ac8e35e1Smrg #include <signal.h>
25ac8e35e1Smrg #include <stdint.h>
26ac8e35e1Smrg #include <sys/ucontext.h>
27ac8e35e1Smrg
28ac8e35e1Smrg #define LI_A7_8B 0x08b00893
29ac8e35e1Smrg #define ECALL 0x00000073
30ac8e35e1Smrg
31ac8e35e1Smrg #define MD_FALLBACK_FRAME_STATE_FOR riscv_fallback_frame_state
32ac8e35e1Smrg
33ac8e35e1Smrg static _Unwind_Reason_Code
riscv_fallback_frame_state(struct _Unwind_Context * context,_Unwind_FrameState * fs)34ac8e35e1Smrg riscv_fallback_frame_state (struct _Unwind_Context *context,
35ac8e35e1Smrg _Unwind_FrameState * fs)
36ac8e35e1Smrg {
37ac8e35e1Smrg /* The kernel creates an rt_sigframe on the stack immediately prior
38ac8e35e1Smrg to delivering a signal.
39ac8e35e1Smrg
40ac8e35e1Smrg This structure must have the same shape as the linux kernel
41ac8e35e1Smrg equivalent. */
42ac8e35e1Smrg struct rt_sigframe
43ac8e35e1Smrg {
44ac8e35e1Smrg siginfo_t info;
45ac8e35e1Smrg ucontext_t uc;
46ac8e35e1Smrg };
47ac8e35e1Smrg
48ac8e35e1Smrg struct rt_sigframe *rt_;
49ac8e35e1Smrg _Unwind_Ptr new_cfa;
50ac8e35e1Smrg uint16_t *pc = context->ra;
51ac8e35e1Smrg struct sigcontext *sc;
52ac8e35e1Smrg int i;
53ac8e35e1Smrg
54ac8e35e1Smrg /* A signal frame will have a return address pointing to
55ac8e35e1Smrg __default_sa_restorer. This code is hardwired as:
56ac8e35e1Smrg
57ac8e35e1Smrg 0x08b00893 li a7,0x8b
58ac8e35e1Smrg 0x00000073 ecall
59ac8e35e1Smrg
60ac8e35e1Smrg Note, the PC might only have 2-byte alignment.
61ac8e35e1Smrg */
62ac8e35e1Smrg if (pc[0] != (uint16_t)LI_A7_8B || pc[1] != (uint16_t)(LI_A7_8B >> 16)
63ac8e35e1Smrg || pc[2] != (uint16_t)ECALL || pc[3] != (uint16_t)(ECALL >> 16))
64ac8e35e1Smrg return _URC_END_OF_STACK;
65ac8e35e1Smrg
66ac8e35e1Smrg rt_ = context->cfa;
67ac8e35e1Smrg sc = &rt_->uc.uc_mcontext;
68ac8e35e1Smrg
69ac8e35e1Smrg new_cfa = (_Unwind_Ptr) sc;
70ac8e35e1Smrg fs->regs.cfa_how = CFA_REG_OFFSET;
71ac8e35e1Smrg fs->regs.cfa_reg = __LIBGCC_STACK_POINTER_REGNUM__;
72ac8e35e1Smrg fs->regs.cfa_offset = new_cfa - (_Unwind_Ptr) context->cfa;
73ac8e35e1Smrg
74ac8e35e1Smrg for (i = 0; i < 32; i++)
75ac8e35e1Smrg {
76ac8e35e1Smrg fs->regs.reg[i].how = REG_SAVED_OFFSET;
77ac8e35e1Smrg fs->regs.reg[i].loc.offset = (_Unwind_Ptr) &sc->gregs[i] - new_cfa;
78ac8e35e1Smrg }
79ac8e35e1Smrg
80ac8e35e1Smrg fs->signal_frame = 1;
81ac8e35e1Smrg fs->retaddr_column = __LIBGCC_DWARF_ALT_FRAME_RETURN_COLUMN__;
82ac8e35e1Smrg fs->regs.reg[fs->retaddr_column].how = REG_SAVED_VAL_OFFSET;
83ac8e35e1Smrg fs->regs.reg[fs->retaddr_column].loc.offset =
84ac8e35e1Smrg (_Unwind_Ptr) sc->gregs[0] - new_cfa;
85ac8e35e1Smrg
86ac8e35e1Smrg return _URC_NO_REASON;
87ac8e35e1Smrg }
88ac8e35e1Smrg
89ac8e35e1Smrg #endif
90