annotate gcc/ada/sigtramp-ios.c @ 111:04ced10e8804

gcc 7
author kono
date Fri, 27 Oct 2017 22:46:09 +0900
parents
children 84e7813d76e9
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
111
kono
parents:
diff changeset
1 /****************************************************************************
kono
parents:
diff changeset
2 * *
kono
parents:
diff changeset
3 * GNAT COMPILER COMPONENTS *
kono
parents:
diff changeset
4 * *
kono
parents:
diff changeset
5 * S I G T R A M P *
kono
parents:
diff changeset
6 * *
kono
parents:
diff changeset
7 * Asm Implementation File *
kono
parents:
diff changeset
8 * *
kono
parents:
diff changeset
9 * Copyright (C) 2015, Free Software Foundation, Inc. *
kono
parents:
diff changeset
10 * *
kono
parents:
diff changeset
11 * GNAT is free software; you can redistribute it and/or modify it under *
kono
parents:
diff changeset
12 * terms of the GNU General Public License as published by the Free Soft- *
kono
parents:
diff changeset
13 * ware Foundation; either version 3, or (at your option) any later ver- *
kono
parents:
diff changeset
14 * sion. GNAT is distributed in the hope that it will be useful, but WITH- *
kono
parents:
diff changeset
15 * OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY *
kono
parents:
diff changeset
16 * or FITNESS FOR A PARTICULAR PURPOSE. *
kono
parents:
diff changeset
17 * *
kono
parents:
diff changeset
18 * As a special exception under Section 7 of GPL version 3, you are granted *
kono
parents:
diff changeset
19 * additional permissions described in the GCC Runtime Library Exception, *
kono
parents:
diff changeset
20 * version 3.1, as published by the Free Software Foundation. *
kono
parents:
diff changeset
21 * *
kono
parents:
diff changeset
22 * In particular, you can freely distribute your programs built with the *
kono
parents:
diff changeset
23 * GNAT Pro compiler, including any required library run-time units, using *
kono
parents:
diff changeset
24 * any licensing terms of your choosing. See the AdaCore Software License *
kono
parents:
diff changeset
25 * for full details. *
kono
parents:
diff changeset
26 * *
kono
parents:
diff changeset
27 * GNAT was originally developed by the GNAT team at New York University. *
kono
parents:
diff changeset
28 * Extensive contributions were provided by Ada Core Technologies Inc. *
kono
parents:
diff changeset
29 * *
kono
parents:
diff changeset
30 ****************************************************************************/
kono
parents:
diff changeset
31
kono
parents:
diff changeset
32 /****************************************************
kono
parents:
diff changeset
33 * ARM64/IOS version of the __gnat_sigtramp service *
kono
parents:
diff changeset
34 ****************************************************/
kono
parents:
diff changeset
35
kono
parents:
diff changeset
36 #include <sys/ucontext.h>
kono
parents:
diff changeset
37
kono
parents:
diff changeset
38 #include "sigtramp.h"
kono
parents:
diff changeset
39 /* See sigtramp.h for a general explanation of functionality. */
kono
parents:
diff changeset
40
kono
parents:
diff changeset
41 /* ----------------------
kono
parents:
diff changeset
42 -- General comments --
kono
parents:
diff changeset
43 ----------------------
kono
parents:
diff changeset
44
kono
parents:
diff changeset
45 Unfortunately the libunwind library used on this platform comes with severe
kono
parents:
diff changeset
46 limitations that make the implementation convoluted:
kono
parents:
diff changeset
47
kono
parents:
diff changeset
48 1. At each step, the stack pointer register SP is restored with the CFA.
kono
parents:
diff changeset
49 This makes it impossible to set the CFA to an arbitrary value, for
kono
parents:
diff changeset
50 example to the address of the context saved on the stack, which means
kono
parents:
diff changeset
51 that the simple CFI directives cannot be used for the registers.
kono
parents:
diff changeset
52
kono
parents:
diff changeset
53 2. For the ARM64 architecture (and only it), DWARF expressions are not
kono
parents:
diff changeset
54 supported to compute the CFA. Only DW_CFA_def_cfa is supported, which
kono
parents:
diff changeset
55 means that the CFA (modulo offset) must be loaded into a register.
kono
parents:
diff changeset
56
kono
parents:
diff changeset
57 3. The return column cannot be changed (30 for the ARM64 architecture).
kono
parents:
diff changeset
58 Since column 30 is that of the LR register, this makes it impossible
kono
parents:
diff changeset
59 to restore both the LR register and the PC.
kono
parents:
diff changeset
60
kono
parents:
diff changeset
61 Therefore we need 2 distinct call-saved registers in the trampoline and
kono
parents:
diff changeset
62 we resort to manual encoding of CFI byte sequences. */
kono
parents:
diff changeset
63
kono
parents:
diff changeset
64 /* -----------------------------------------
kono
parents:
diff changeset
65 -- Protypes for our internal asm stubs --
kono
parents:
diff changeset
66 -----------------------------------------
kono
parents:
diff changeset
67
kono
parents:
diff changeset
68 Even though our symbols will remain local, the prototype claims "extern"
kono
parents:
diff changeset
69 and not "static" to prevent compiler complaints about a symbol used but
kono
parents:
diff changeset
70 never defined. */
kono
parents:
diff changeset
71
kono
parents:
diff changeset
72 /* sigtramp stub providing unwind info for common registers. */
kono
parents:
diff changeset
73
kono
parents:
diff changeset
74 extern void __gnat_sigtramp_common
kono
parents:
diff changeset
75 (int signo, void *siginfo, void *sigcontext,
kono
parents:
diff changeset
76 __sigtramphandler_t * handler);
kono
parents:
diff changeset
77
kono
parents:
diff changeset
78 void __gnat_sigtramp (int signo, void *si, void *ucontext,
kono
parents:
diff changeset
79 __sigtramphandler_t * handler)
kono
parents:
diff changeset
80 __attribute__((optimize(2)));
kono
parents:
diff changeset
81
kono
parents:
diff changeset
82 void __gnat_sigtramp (int signo, void *si, void *ucontext,
kono
parents:
diff changeset
83 __sigtramphandler_t * handler)
kono
parents:
diff changeset
84 {
kono
parents:
diff changeset
85 mcontext_t mcontext = ((ucontext_t *) ucontext)->uc_mcontext;
kono
parents:
diff changeset
86
kono
parents:
diff changeset
87 __gnat_sigtramp_common (signo, si, mcontext, handler);
kono
parents:
diff changeset
88 }
kono
parents:
diff changeset
89
kono
parents:
diff changeset
90 /* asm string construction helpers. */
kono
parents:
diff changeset
91
kono
parents:
diff changeset
92 #define STR(TEXT) #TEXT
kono
parents:
diff changeset
93 /* stringify expanded TEXT, surrounding it with double quotes. */
kono
parents:
diff changeset
94
kono
parents:
diff changeset
95 #define S(E) STR(E)
kono
parents:
diff changeset
96 /* stringify E, which will resolve as text but may contain macros
kono
parents:
diff changeset
97 still to be expanded. */
kono
parents:
diff changeset
98
kono
parents:
diff changeset
99 /* asm (TEXT) outputs <tab>TEXT. These facilitate the output of
kono
parents:
diff changeset
100 multiline contents: */
kono
parents:
diff changeset
101 #define TAB(S) "\t" S
kono
parents:
diff changeset
102 #define CR(S) S "\n"
kono
parents:
diff changeset
103
kono
parents:
diff changeset
104 #undef TCR
kono
parents:
diff changeset
105 #define TCR(S) TAB(CR(S))
kono
parents:
diff changeset
106
kono
parents:
diff changeset
107 /* Offset in uc_mcontext of the __ss structure containing the registers. */
kono
parents:
diff changeset
108 #define UC_MCONTEXT_SS 16
kono
parents:
diff changeset
109
kono
parents:
diff changeset
110 #define CFA_REG 19
kono
parents:
diff changeset
111 #define BASE_REG 20
kono
parents:
diff changeset
112
kono
parents:
diff changeset
113 #define DW_CFA_def_cfa 0x0c
kono
parents:
diff changeset
114 #define DW_CFA_expression 0x10
kono
parents:
diff changeset
115
kono
parents:
diff changeset
116 #define DW_OP_breg(n) 0x70+(n)
kono
parents:
diff changeset
117
kono
parents:
diff changeset
118 #define REG_REGNO_GR(n) n
kono
parents:
diff changeset
119 #define REG_REGNO_PC 30
kono
parents:
diff changeset
120
kono
parents:
diff changeset
121 /* The first byte of the SLEB128 value of the offset. */
kono
parents:
diff changeset
122 #define REG_OFFSET_GR(n) (UC_MCONTEXT_SS + n * 8)
kono
parents:
diff changeset
123 #define REG_OFFSET_LONG_GR(n) (UC_MCONTEXT_SS + n * 8 + 128)
kono
parents:
diff changeset
124 #define REG_OFFSET_LONG128_GR(n) (UC_MCONTEXT_SS + (n - 16) * 8 + 128)
kono
parents:
diff changeset
125 #define REG_OFFSET_LONG256_GR(n) (UC_MCONTEXT_SS + (n - 32) * 8 + 128)
kono
parents:
diff changeset
126
kono
parents:
diff changeset
127 #define REG_OFFSET_LONG256_PC REG_OFFSET_LONG256_GR(32)
kono
parents:
diff changeset
128
kono
parents:
diff changeset
129 #define CFI_DEF_CFA \
kono
parents:
diff changeset
130 TCR(".cfi_def_cfa " S(CFA_REG) ", 0")
kono
parents:
diff changeset
131
kono
parents:
diff changeset
132 /* We need 4 variants depending on the offset: 0+, 64+, 128+, 256+. */
kono
parents:
diff changeset
133 #define COMMON_CFI(REG) \
kono
parents:
diff changeset
134 ".cfi_escape " S(DW_CFA_expression) "," S(REG_REGNO_##REG) ",2," \
kono
parents:
diff changeset
135 S(DW_OP_breg(BASE_REG)) "," S(REG_OFFSET_##REG)
kono
parents:
diff changeset
136
kono
parents:
diff changeset
137 #define COMMON_LONG_CFI(REG) \
kono
parents:
diff changeset
138 ".cfi_escape " S(DW_CFA_expression) "," S(REG_REGNO_##REG) ",3," \
kono
parents:
diff changeset
139 S(DW_OP_breg(BASE_REG)) "," S(REG_OFFSET_LONG_##REG) ",0"
kono
parents:
diff changeset
140
kono
parents:
diff changeset
141 #define COMMON_LONG128_CFI(REG) \
kono
parents:
diff changeset
142 ".cfi_escape " S(DW_CFA_expression) "," S(REG_REGNO_##REG) ",3," \
kono
parents:
diff changeset
143 S(DW_OP_breg(BASE_REG)) "," S(REG_OFFSET_LONG128_##REG) ",1"
kono
parents:
diff changeset
144
kono
parents:
diff changeset
145 #define COMMON_LONG256_CFI(REG) \
kono
parents:
diff changeset
146 ".cfi_escape " S(DW_CFA_expression) "," S(REG_REGNO_##REG) ",3," \
kono
parents:
diff changeset
147 S(DW_OP_breg(BASE_REG)) "," S(REG_OFFSET_LONG256_##REG) ",2"
kono
parents:
diff changeset
148
kono
parents:
diff changeset
149 #define CFI_COMMON_REGS \
kono
parents:
diff changeset
150 CR("# CFI for common registers\n") \
kono
parents:
diff changeset
151 TCR(COMMON_CFI(GR(0))) \
kono
parents:
diff changeset
152 TCR(COMMON_CFI(GR(1))) \
kono
parents:
diff changeset
153 TCR(COMMON_CFI(GR(2))) \
kono
parents:
diff changeset
154 TCR(COMMON_CFI(GR(3))) \
kono
parents:
diff changeset
155 TCR(COMMON_CFI(GR(4))) \
kono
parents:
diff changeset
156 TCR(COMMON_CFI(GR(5))) \
kono
parents:
diff changeset
157 TCR(COMMON_LONG_CFI(GR(6))) \
kono
parents:
diff changeset
158 TCR(COMMON_LONG_CFI(GR(7))) \
kono
parents:
diff changeset
159 TCR(COMMON_LONG_CFI(GR(8))) \
kono
parents:
diff changeset
160 TCR(COMMON_LONG_CFI(GR(9))) \
kono
parents:
diff changeset
161 TCR(COMMON_LONG_CFI(GR(10))) \
kono
parents:
diff changeset
162 TCR(COMMON_LONG_CFI(GR(11))) \
kono
parents:
diff changeset
163 TCR(COMMON_LONG_CFI(GR(12))) \
kono
parents:
diff changeset
164 TCR(COMMON_LONG_CFI(GR(13))) \
kono
parents:
diff changeset
165 TCR(COMMON_LONG128_CFI(GR(14))) \
kono
parents:
diff changeset
166 TCR(COMMON_LONG128_CFI(GR(15))) \
kono
parents:
diff changeset
167 TCR(COMMON_LONG128_CFI(GR(16))) \
kono
parents:
diff changeset
168 TCR(COMMON_LONG128_CFI(GR(17))) \
kono
parents:
diff changeset
169 TCR(COMMON_LONG128_CFI(GR(18))) \
kono
parents:
diff changeset
170 TCR(COMMON_LONG128_CFI(GR(19))) \
kono
parents:
diff changeset
171 TCR(COMMON_LONG128_CFI(GR(20))) \
kono
parents:
diff changeset
172 TCR(COMMON_LONG128_CFI(GR(21))) \
kono
parents:
diff changeset
173 TCR(COMMON_LONG128_CFI(GR(22))) \
kono
parents:
diff changeset
174 TCR(COMMON_LONG128_CFI(GR(23))) \
kono
parents:
diff changeset
175 TCR(COMMON_LONG128_CFI(GR(24))) \
kono
parents:
diff changeset
176 TCR(COMMON_LONG128_CFI(GR(25))) \
kono
parents:
diff changeset
177 TCR(COMMON_LONG128_CFI(GR(26))) \
kono
parents:
diff changeset
178 TCR(COMMON_LONG128_CFI(GR(27))) \
kono
parents:
diff changeset
179 TCR(COMMON_LONG128_CFI(GR(28))) \
kono
parents:
diff changeset
180 TCR(COMMON_LONG128_CFI(GR(29))) \
kono
parents:
diff changeset
181 TCR(COMMON_LONG256_CFI(PC))
kono
parents:
diff changeset
182
kono
parents:
diff changeset
183 /* Trampoline body block
kono
parents:
diff changeset
184 --------------------- */
kono
parents:
diff changeset
185
kono
parents:
diff changeset
186 #define SIGTRAMP_BODY \
kono
parents:
diff changeset
187 TCR("stp fp, lr, [sp, #-32]!") \
kono
parents:
diff changeset
188 TCR("stp x" S(CFA_REG) ", x" S(BASE_REG) ", [sp, #16]") \
kono
parents:
diff changeset
189 TCR("mov fp, sp") \
kono
parents:
diff changeset
190 TCR("# Load the saved value of the stack pointer as CFA") \
kono
parents:
diff changeset
191 TCR("ldr x" S(CFA_REG) ", [x2, #" S(REG_OFFSET_GR(31)) "]") \
kono
parents:
diff changeset
192 TCR("# Use x" S(BASE_REG) " as base register for the CFI") \
kono
parents:
diff changeset
193 TCR("mov x" S(BASE_REG) ", x2") \
kono
parents:
diff changeset
194 TCR("# Call the handler") \
kono
parents:
diff changeset
195 TCR("blr x3") \
kono
parents:
diff changeset
196 TCR("# Release our frame and return (should never get here!).") \
kono
parents:
diff changeset
197 TCR("ldp x" S(CFA_REG) ", x" S(BASE_REG)" , [sp, #16]") \
kono
parents:
diff changeset
198 TCR("ldp fp, lr, [sp], 32") \
kono
parents:
diff changeset
199 TCR("ret")
kono
parents:
diff changeset
200
kono
parents:
diff changeset
201 /* -----------------------------
kono
parents:
diff changeset
202 -- Symbol definition block --
kono
parents:
diff changeset
203 ----------------------------- */
kono
parents:
diff changeset
204
kono
parents:
diff changeset
205 #define SIGTRAMP_START(SYM) \
kono
parents:
diff changeset
206 CR("# " S(SYM) " signal trampoline") \
kono
parents:
diff changeset
207 CR(S(SYM) ":") \
kono
parents:
diff changeset
208 TCR(".cfi_startproc") \
kono
parents:
diff changeset
209 TCR(".cfi_signal_frame")
kono
parents:
diff changeset
210
kono
parents:
diff changeset
211 /* ------------------------------
kono
parents:
diff changeset
212 -- Symbol termination block --
kono
parents:
diff changeset
213 ------------------------------ */
kono
parents:
diff changeset
214
kono
parents:
diff changeset
215 #define SIGTRAMP_END(SYM) \
kono
parents:
diff changeset
216 TCR(".cfi_endproc")
kono
parents:
diff changeset
217
kono
parents:
diff changeset
218 /*----------------------------
kono
parents:
diff changeset
219 -- And now, the real code --
kono
parents:
diff changeset
220 ---------------------------- */
kono
parents:
diff changeset
221
kono
parents:
diff changeset
222 asm(".text\n"
kono
parents:
diff changeset
223 TCR(".align 2"));
kono
parents:
diff changeset
224
kono
parents:
diff changeset
225 /* sigtramp stub for common registers. */
kono
parents:
diff changeset
226
kono
parents:
diff changeset
227 #define TRAMP_COMMON ___gnat_sigtramp_common
kono
parents:
diff changeset
228
kono
parents:
diff changeset
229 asm (SIGTRAMP_START(TRAMP_COMMON));
kono
parents:
diff changeset
230 asm (CFI_DEF_CFA);
kono
parents:
diff changeset
231 asm (CFI_COMMON_REGS);
kono
parents:
diff changeset
232 asm (SIGTRAMP_BODY);
kono
parents:
diff changeset
233 asm (SIGTRAMP_END(TRAMP_COMMON));