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