annotate libgcc/config/aarch64/linux-unwind.h @ 158:494b0b89df80 default tip

...
author Shinji KONO <kono@ie.u-ryukyu.ac.jp>
date Mon, 25 May 2020 18:13:55 +0900
parents 1830386684a0
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1 /* Copyright (C) 2009-2020 Free Software Foundation, Inc.
111
kono
parents:
diff changeset
2 Contributed by ARM Ltd.
kono
parents:
diff changeset
3
kono
parents:
diff changeset
4 This file is free software; you can redistribute it and/or modify it
kono
parents:
diff changeset
5 under the terms of the GNU General Public License as published by the
kono
parents:
diff changeset
6 Free Software Foundation; either version 3, or (at your option) any
kono
parents:
diff changeset
7 later version.
kono
parents:
diff changeset
8
kono
parents:
diff changeset
9 This file is distributed in the hope that it will be useful, but
kono
parents:
diff changeset
10 WITHOUT ANY WARRANTY; without even the implied warranty of
kono
parents:
diff changeset
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
kono
parents:
diff changeset
12 General Public License for more details.
kono
parents:
diff changeset
13
kono
parents:
diff changeset
14 Under Section 7 of GPL version 3, you are granted additional
kono
parents:
diff changeset
15 permissions described in the GCC Runtime Library Exception, version
kono
parents:
diff changeset
16 3.1, as published by the Free Software Foundation.
kono
parents:
diff changeset
17
kono
parents:
diff changeset
18 You should have received a copy of the GNU General Public License and
kono
parents:
diff changeset
19 a copy of the GCC Runtime Library Exception along with this program;
kono
parents:
diff changeset
20 see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
kono
parents:
diff changeset
21 <http://www.gnu.org/licenses/>. */
kono
parents:
diff changeset
22
kono
parents:
diff changeset
23 /* Always include AArch64 unwinder header file. */
kono
parents:
diff changeset
24 #include "config/aarch64/aarch64-unwind.h"
kono
parents:
diff changeset
25
kono
parents:
diff changeset
26 #ifndef inhibit_libc
kono
parents:
diff changeset
27
kono
parents:
diff changeset
28 #include <signal.h>
kono
parents:
diff changeset
29 #include <sys/ucontext.h>
kono
parents:
diff changeset
30
kono
parents:
diff changeset
31
kono
parents:
diff changeset
32 /* Since insns are always stored LE, on a BE system the opcodes will
kono
parents:
diff changeset
33 be loaded byte-reversed. Therefore, define two sets of opcodes,
kono
parents:
diff changeset
34 one for LE and one for BE. */
kono
parents:
diff changeset
35
kono
parents:
diff changeset
36 #if __AARCH64EB__
kono
parents:
diff changeset
37 #define MOVZ_X8_8B 0x681180d2
kono
parents:
diff changeset
38 #define SVC_0 0x010000d4
kono
parents:
diff changeset
39 #else
kono
parents:
diff changeset
40 #define MOVZ_X8_8B 0xd2801168
kono
parents:
diff changeset
41 #define SVC_0 0xd4000001
kono
parents:
diff changeset
42 #endif
kono
parents:
diff changeset
43
kono
parents:
diff changeset
44 #define MD_FALLBACK_FRAME_STATE_FOR aarch64_fallback_frame_state
kono
parents:
diff changeset
45
kono
parents:
diff changeset
46 static _Unwind_Reason_Code
kono
parents:
diff changeset
47 aarch64_fallback_frame_state (struct _Unwind_Context *context,
kono
parents:
diff changeset
48 _Unwind_FrameState * fs)
kono
parents:
diff changeset
49 {
kono
parents:
diff changeset
50 /* The kernel creates an rt_sigframe on the stack immediately prior
kono
parents:
diff changeset
51 to delivering a signal.
kono
parents:
diff changeset
52
kono
parents:
diff changeset
53 This structure must have the same shape as the linux kernel
kono
parents:
diff changeset
54 equivalent. */
kono
parents:
diff changeset
55 struct rt_sigframe
kono
parents:
diff changeset
56 {
kono
parents:
diff changeset
57 siginfo_t info;
kono
parents:
diff changeset
58 ucontext_t uc;
kono
parents:
diff changeset
59 };
kono
parents:
diff changeset
60
kono
parents:
diff changeset
61 struct rt_sigframe *rt_;
kono
parents:
diff changeset
62 _Unwind_Ptr new_cfa;
kono
parents:
diff changeset
63 unsigned *pc = context->ra;
kono
parents:
diff changeset
64 struct sigcontext *sc;
kono
parents:
diff changeset
65 struct _aarch64_ctx *extension_marker;
kono
parents:
diff changeset
66 int i;
kono
parents:
diff changeset
67
kono
parents:
diff changeset
68 /* A signal frame will have a return address pointing to
kono
parents:
diff changeset
69 __default_sa_restorer. This code is hardwired as:
kono
parents:
diff changeset
70
kono
parents:
diff changeset
71 0xd2801168 movz x8, #0x8b
kono
parents:
diff changeset
72 0xd4000001 svc 0x0
kono
parents:
diff changeset
73 */
kono
parents:
diff changeset
74 if (pc[0] != MOVZ_X8_8B || pc[1] != SVC_0)
kono
parents:
diff changeset
75 {
kono
parents:
diff changeset
76 return _URC_END_OF_STACK;
kono
parents:
diff changeset
77 }
kono
parents:
diff changeset
78
kono
parents:
diff changeset
79 rt_ = context->cfa;
kono
parents:
diff changeset
80 sc = &rt_->uc.uc_mcontext;
kono
parents:
diff changeset
81
kono
parents:
diff changeset
82 /* This define duplicates the definition in aarch64.md */
kono
parents:
diff changeset
83 #define SP_REGNUM 31
kono
parents:
diff changeset
84
kono
parents:
diff changeset
85 new_cfa = (_Unwind_Ptr) sc;
kono
parents:
diff changeset
86 fs->regs.cfa_how = CFA_REG_OFFSET;
kono
parents:
diff changeset
87 fs->regs.cfa_reg = __LIBGCC_STACK_POINTER_REGNUM__;
kono
parents:
diff changeset
88 fs->regs.cfa_offset = new_cfa - (_Unwind_Ptr) context->cfa;
kono
parents:
diff changeset
89
kono
parents:
diff changeset
90 for (i = 0; i < AARCH64_DWARF_NUMBER_R; i++)
kono
parents:
diff changeset
91 {
kono
parents:
diff changeset
92 fs->regs.reg[AARCH64_DWARF_R0 + i].how = REG_SAVED_OFFSET;
kono
parents:
diff changeset
93 fs->regs.reg[AARCH64_DWARF_R0 + i].loc.offset =
kono
parents:
diff changeset
94 (_Unwind_Ptr) & (sc->regs[i]) - new_cfa;
kono
parents:
diff changeset
95 }
kono
parents:
diff changeset
96
kono
parents:
diff changeset
97 /* The core context may be extended with an arbitrary set of
kono
parents:
diff changeset
98 additional contexts appended sequentially. Each additional
kono
parents:
diff changeset
99 context contains a magic identifier and size in bytes. The size
kono
parents:
diff changeset
100 field can be used to skip over unrecognized context extensions.
kono
parents:
diff changeset
101 The end of the context sequence is marked by a context with magic
kono
parents:
diff changeset
102 0 or size 0. */
kono
parents:
diff changeset
103 for (extension_marker = (struct _aarch64_ctx *) &sc->__reserved;
kono
parents:
diff changeset
104 extension_marker->magic;
kono
parents:
diff changeset
105 extension_marker = (struct _aarch64_ctx *)
kono
parents:
diff changeset
106 ((unsigned char *) extension_marker + extension_marker->size))
kono
parents:
diff changeset
107 {
kono
parents:
diff changeset
108 if (extension_marker->magic == FPSIMD_MAGIC)
kono
parents:
diff changeset
109 {
kono
parents:
diff changeset
110 struct fpsimd_context *ctx =
kono
parents:
diff changeset
111 (struct fpsimd_context *) extension_marker;
kono
parents:
diff changeset
112 int i;
kono
parents:
diff changeset
113
kono
parents:
diff changeset
114 for (i = 0; i < AARCH64_DWARF_NUMBER_V; i++)
kono
parents:
diff changeset
115 {
kono
parents:
diff changeset
116 _Unwind_Sword offset;
kono
parents:
diff changeset
117
kono
parents:
diff changeset
118 fs->regs.reg[AARCH64_DWARF_V0 + i].how = REG_SAVED_OFFSET;
kono
parents:
diff changeset
119
kono
parents:
diff changeset
120 /* sigcontext contains 32 128bit registers for V0 to
kono
parents:
diff changeset
121 V31. The kernel will have saved the contents of the
kono
parents:
diff changeset
122 V registers. We want to unwind the callee save D
kono
parents:
diff changeset
123 registers. Each D register comprises the least
kono
parents:
diff changeset
124 significant half of the corresponding V register. We
kono
parents:
diff changeset
125 need to offset into the saved V register dependent on
kono
parents:
diff changeset
126 our endianness to find the saved D register. */
kono
parents:
diff changeset
127
kono
parents:
diff changeset
128 offset = (_Unwind_Ptr) & (ctx->vregs[i]) - new_cfa;
kono
parents:
diff changeset
129
kono
parents:
diff changeset
130 /* The endianness adjustment code below expects that a
kono
parents:
diff changeset
131 saved V register is 16 bytes. */
kono
parents:
diff changeset
132 gcc_assert (sizeof (ctx->vregs[0]) == 16);
kono
parents:
diff changeset
133 #if defined (__AARCH64EB__)
kono
parents:
diff changeset
134 offset = offset + 8;
kono
parents:
diff changeset
135 #endif
kono
parents:
diff changeset
136 fs->regs.reg[AARCH64_DWARF_V0 + i].loc.offset = offset;
kono
parents:
diff changeset
137 }
kono
parents:
diff changeset
138 }
kono
parents:
diff changeset
139 else
kono
parents:
diff changeset
140 {
kono
parents:
diff changeset
141 /* There is context provided that we do not recognize! */
kono
parents:
diff changeset
142 }
kono
parents:
diff changeset
143 }
kono
parents:
diff changeset
144
kono
parents:
diff changeset
145 fs->regs.reg[31].how = REG_SAVED_OFFSET;
kono
parents:
diff changeset
146 fs->regs.reg[31].loc.offset = (_Unwind_Ptr) & (sc->sp) - new_cfa;
kono
parents:
diff changeset
147
kono
parents:
diff changeset
148 fs->signal_frame = 1;
kono
parents:
diff changeset
149
kono
parents:
diff changeset
150 fs->regs.reg[__LIBGCC_DWARF_ALT_FRAME_RETURN_COLUMN__].how =
kono
parents:
diff changeset
151 REG_SAVED_VAL_OFFSET;
kono
parents:
diff changeset
152 fs->regs.reg[__LIBGCC_DWARF_ALT_FRAME_RETURN_COLUMN__].loc.offset =
kono
parents:
diff changeset
153 (_Unwind_Ptr) (sc->pc) - new_cfa;
kono
parents:
diff changeset
154
kono
parents:
diff changeset
155 fs->retaddr_column = __LIBGCC_DWARF_ALT_FRAME_RETURN_COLUMN__;
kono
parents:
diff changeset
156
kono
parents:
diff changeset
157 return _URC_NO_REASON;
kono
parents:
diff changeset
158 }
kono
parents:
diff changeset
159
kono
parents:
diff changeset
160 #endif