]> git.ipfire.org Git - thirdparty/gcc.git/blob - libgcc/config/aarch64/freebsd-unwind.h
Update copyright years.
[thirdparty/gcc.git] / libgcc / config / aarch64 / freebsd-unwind.h
1 /* DWARF2 EH unwinding support for FreeBSD/ARM64 (aarch64).
2 Copyright (C) 2017-2020 Free Software Foundation, Inc.
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++)
93 fs->regs.reg[n].how = REG_SAVED_OFFSET;
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
101 fs->regs.reg[DARC].how = REG_SAVED_OFFSET;
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 }