]>
Commit | Line | Data |
---|---|---|
4ccfdb28 | 1 | /* DWARF2 EH unwinding support for FreeBSD/ARM64 (aarch64). |
83ffe9cd | 2 | Copyright (C) 2017-2023 Free Software Foundation, Inc. |
4ccfdb28 JM |
3 | Contributed by John Marino <gnugcc@marino.st> |
4 | ||
5 | This file is part of GCC. | |
6 | ||
7 | GCC is free software; you can redistribute it and/or modify | |
8 | it under the terms of the GNU General Public License as published by | |
9 | the Free Software Foundation; either version 3, or (at your option) | |
10 | any later version. | |
11 | ||
12 | GCC is distributed in the hope that it will be useful, | |
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
15 | GNU General Public License for more details. | |
16 | ||
17 | Under Section 7 of GPL version 3, you are granted additional | |
18 | permissions described in the GCC Runtime Library Exception, version | |
19 | 3.1, as published by the Free Software Foundation. | |
20 | ||
21 | You should have received a copy of the GNU General Public License and | |
22 | a copy of the GCC Runtime Library Exception along with this program; | |
23 | see the files COPYING3 and COPYING.RUNTIME respectively. If not, see | |
24 | <http://www.gnu.org/licenses/>. */ | |
25 | ||
26 | /* Identify a signal frame, and set the frame state data appropriately. | |
27 | See unwind-dw2.c for the structs. */ | |
28 | ||
29 | /* Always include AArch64 unwinder header file. */ | |
30 | #include "config/aarch64/aarch64-unwind.h" | |
31 | ||
32 | #include <sys/types.h> | |
33 | #include <signal.h> | |
34 | #include <unistd.h> | |
35 | #include <sys/ucontext.h> | |
36 | #include <machine/frame.h> | |
37 | #include <sys/user.h> | |
38 | #include <sys/sysctl.h> | |
39 | ||
40 | #define REG_NAME(reg) mc_gpregs.gp_## reg | |
41 | #define XREG(num) mc_gpregs.gp_x[num] | |
42 | #define DARC __LIBGCC_DWARF_ALT_FRAME_RETURN_COLUMN__ | |
43 | ||
44 | #define MD_FALLBACK_FRAME_STATE_FOR aarch64_freebsd_fallback_frame_state | |
45 | ||
46 | static int | |
47 | aarch64_outside_sigtramp_range (unsigned char *pc) | |
48 | { | |
49 | static int sigtramp_range_determined = 0; | |
50 | static unsigned char *sigtramp_start, *sigtramp_end; | |
51 | ||
52 | if (sigtramp_range_determined == 0) | |
53 | { | |
54 | struct kinfo_sigtramp kst = {0}; | |
55 | size_t len = sizeof (kst); | |
56 | int mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_SIGTRAMP, getpid() }; | |
57 | ||
58 | sigtramp_range_determined = 1; | |
59 | if (sysctl (mib, 4, &kst, &len, NULL, 0) == 0) | |
60 | { | |
61 | sigtramp_range_determined = 2; | |
62 | sigtramp_start = kst.ksigtramp_start; | |
63 | sigtramp_end = kst.ksigtramp_end; | |
64 | } | |
65 | } | |
66 | if (sigtramp_range_determined < 2) /* sysctl failed if < 2 */ | |
67 | return 1; | |
68 | ||
69 | return (pc < sigtramp_start || pc >= sigtramp_end); | |
70 | } | |
71 | ||
72 | static _Unwind_Reason_Code | |
73 | aarch64_freebsd_fallback_frame_state | |
74 | (struct _Unwind_Context *context, _Unwind_FrameState *fs) | |
75 | { | |
76 | int n; | |
77 | struct sigframe *sf; | |
78 | mcontext_t *sc; | |
79 | _Unwind_Ptr new_cfa; | |
80 | ||
81 | if (aarch64_outside_sigtramp_range(context->ra)) | |
82 | return _URC_END_OF_STACK; | |
83 | ||
84 | sf = (struct sigframe *) context->cfa; | |
85 | sc = &sf->sf_uc.uc_mcontext; | |
86 | ||
87 | new_cfa = (_Unwind_Ptr) sc; | |
88 | fs->regs.cfa_how = CFA_REG_OFFSET; | |
89 | fs->regs.cfa_reg = __LIBGCC_STACK_POINTER_REGNUM__; | |
90 | fs->regs.cfa_offset = new_cfa - (_Unwind_Ptr) context->cfa; | |
91 | ||
92 | for (n = 0; n < 32; n++) | |
146e4591 | 93 | fs->regs.how[n] = REG_SAVED_OFFSET; |
4ccfdb28 JM |
94 | |
95 | for (n = 0; n < 30; n++) | |
96 | fs->regs.reg[n].loc.offset = (_Unwind_Ptr) &(sc->XREG(n)) - new_cfa; | |
97 | ||
98 | fs->regs.reg[30].loc.offset = (_Unwind_Ptr) &(sc->REG_NAME(lr)) - new_cfa; | |
99 | fs->regs.reg[31].loc.offset = (_Unwind_Ptr) &(sc->REG_NAME(sp)) - new_cfa; | |
100 | ||
146e4591 | 101 | fs->regs.how[DARC] = REG_SAVED_OFFSET; |
4ccfdb28 JM |
102 | fs->regs.reg[DARC].loc.offset = (_Unwind_Ptr) &(sc->REG_NAME(elr)) - new_cfa; |
103 | ||
104 | fs->retaddr_column = DARC; | |
105 | fs->signal_frame = 1; | |
106 | ||
107 | return _URC_NO_REASON; | |
108 | } |