111
|
1 /****************************************************************************
|
|
2 * *
|
|
3 * GNAT COMPILER COMPONENTS *
|
|
4 * *
|
|
5 * S I G T R A M P - T A R G E T *
|
|
6 * *
|
|
7 * Asm Implementation Include File *
|
|
8 * *
|
131
|
9 * Copyright (C) 2011-2018, Free Software Foundation, Inc. *
|
111
|
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 * VxWorks target specific part of the __gnat_sigtramp service *
|
|
34 ***************************************************************/
|
|
35
|
|
36 /* Note: This target specific part is kept in a separate file to avoid
|
|
37 duplication of its code for the vxworks and vxworks-vxsim asm
|
|
38 implementation files. */
|
|
39
|
|
40 /* ---------------------------
|
|
41 -- And now the asm stubs --
|
|
42 ---------------------------
|
|
43
|
|
44 They all have a common structure with blocks of asm sequences queued one
|
|
45 after the others. Typically:
|
|
46
|
|
47 SYMBOL_START
|
|
48
|
|
49 CFI_DIRECTIVES
|
|
50 CFI_DEF_CFA,
|
|
51 CFI_COMMON_REGISTERS,
|
|
52 ...
|
|
53
|
|
54 STUB_BODY
|
|
55 asm code to establish frame, setup the cfa reg value,
|
|
56 call the real signal handler, ...
|
|
57
|
|
58 SYMBOL_END
|
|
59 */
|
|
60
|
|
61 /*--------------------------------
|
|
62 -- Misc constants and helpers --
|
|
63 -------------------------------- */
|
|
64
|
|
65 /* asm string construction helpers. */
|
|
66
|
|
67 #define STR(TEXT) #TEXT
|
|
68 /* stringify expanded TEXT, surrounding it with double quotes. */
|
|
69
|
|
70 #define S(E) STR(E)
|
|
71 /* stringify E, which will resolve as text but may contain macros
|
|
72 still to be expanded. */
|
|
73
|
|
74 /* asm (TEXT) outputs <tab>TEXT. These facilitate the output of
|
|
75 multine contents: */
|
|
76 #define TAB(S) "\t" S
|
|
77 #define CR(S) S "\n"
|
|
78
|
|
79 #undef TCR
|
|
80 #define TCR(S) TAB(CR(S))
|
|
81
|
|
82 /* REGNO constants, dwarf column numbers for registers of interest. */
|
|
83
|
|
84 #if defined (__PPC__)
|
|
85
|
|
86 #define REGNO_LR 65
|
|
87 #define REGNO_CTR 66
|
|
88 #define REGNO_CR 70
|
|
89 #define REGNO_XER 76
|
|
90 #define REGNO_GR(N) (N)
|
|
91
|
|
92 #define REGNO_PC 67 /* ARG_POINTER_REGNUM */
|
|
93
|
|
94 #define FUNCTION "@function"
|
|
95
|
131
|
96 #elif defined (ARMEL)
|
111
|
97
|
|
98 #define REGNO_G_REG_OFFSET(N) (N)
|
|
99
|
131
|
100 #define FUNCTION "%function"
|
|
101
|
|
102 #ifdef __aarch64__
|
|
103 #define REGNO_PC_OFFSET 80 /* aka V16, a scratch register */
|
|
104 #else
|
|
105 #define REGNO_PC_OFFSET 15 /* PC_REGNUM */
|
|
106 #endif
|
111
|
107
|
131
|
108 /* Mapping of CFI Column, Gcc Regno, Signal context offset for _LP64
|
|
109
|
|
110 Name CFI GCC SCTX
|
|
111 G0-G30 0-30 0-30 0-30
|
|
112 SP 31 31 31
|
|
113 PC 32
|
|
114 V0-V31 64-95 32-63 N/A
|
|
115
|
|
116 */
|
111
|
117
|
|
118 #elif defined (i386)
|
|
119
|
|
120 /* These are the cfi colunm numbers */
|
|
121
|
|
122 #define REGNO_EDI 7
|
|
123 #define REGNO_ESI 6
|
|
124 #define REGNO_EBP 5
|
|
125 #define REGNO_ESP 4
|
|
126 #define REGNO_EBX 3
|
|
127 #define REGNO_EDX 2
|
|
128 #define REGNO_ECX 1
|
|
129 #define REGNO_EAX 0
|
|
130 #define REGNO_EFLAGS 9
|
|
131 #define REGNO_SET_PC 8 /* aka %eip */
|
|
132
|
|
133 #define FUNCTION "@function"
|
|
134
|
|
135 /* Mapping of CFI Column, Gcc Regno, Signal context offset for 32bit
|
|
136
|
|
137 Name CFI GCC SCTX
|
|
138 %eax 0 0 7
|
|
139 %ecx 1 2 6
|
|
140 %edx 2 1 5
|
|
141 %ebx 3 3 4
|
|
142 %esp 4 7 3
|
|
143 %ebp 5 6 2
|
|
144 %esi 6 4 1
|
|
145 %edi 7 5 0
|
|
146 %eflags 9 17 8
|
|
147 %eip 8 n/a 9
|
|
148
|
|
149
|
|
150 In general:
|
|
151 There is no unique numbering for the x86 architecture. It's parameterized
|
|
152 by DWARF_FRAME_REGNUM, which is DBX_REGISTER_NUMBER except for Windows, and
|
|
153 the latter depends on the platform.
|
|
154 */
|
|
155
|
|
156 #elif defined (__x86_64__)
|
|
157
|
|
158 /* These are the cfi colunm numbers */
|
|
159
|
|
160 #define REGNO_RAX 0
|
|
161 #define REGNO_RDX 1
|
|
162 #define REGNO_RCX 2
|
|
163 #define REGNO_RBX 3
|
|
164 #define REGNO_RSI 4
|
|
165 #define REGNO_RDI 5
|
|
166 #define REGNO_RBP 6
|
|
167 #define REGNO_RSP 7
|
|
168 #define REGNO_R8 8
|
|
169 #define REGNO_R9 9
|
|
170 #define REGNO_R10 10
|
|
171 #define REGNO_R11 11
|
|
172 #define REGNO_R12 12
|
|
173 #define REGNO_R13 13
|
|
174 #define REGNO_R14 14
|
|
175 #define REGNO_R15 15
|
|
176 #define REGNO_RPC 16 /* aka %rip */
|
|
177 #define REGNO_EFLAGS 49
|
|
178 #define REGNO_FS 54
|
|
179
|
|
180 #define FUNCTION "@function"
|
|
181
|
|
182 #else
|
|
183 Not_implemented;
|
|
184 #endif /* REGNO constants */
|
|
185
|
|
186
|
|
187 /*------------------------------
|
|
188 -- Stub construction blocks --
|
|
189 ------------------------------ */
|
|
190
|
|
191 /* CFA setup block
|
|
192 ---------------
|
|
193 Only non-volatile registers are suitable for a CFA base. These are the
|
|
194 only ones we can expect to be able retrieve from the unwinding context
|
|
195 while walking up the chain, saved by at least the bottom-most exception
|
|
196 propagation services. We set a non-volatile register to the value we
|
|
197 need in the stub body that follows. */
|
|
198
|
|
199 #if defined (__PPC__)
|
|
200
|
|
201 /* Use r15 for PPC. Note that r14 is inappropriate here, even though it
|
|
202 is non-volatile according to the ABI, because GCC uses it as an extra
|
|
203 SCRATCH on SPE targets. */
|
|
204
|
|
205 #define CFA_REG 15
|
|
206
|
131
|
207 #elif defined (ARMEL)
|
111
|
208
|
131
|
209 #ifdef __aarch64__
|
|
210 #define CFA_REG 19
|
|
211 #else
|
111
|
212 /* Use r8 for ARM. Any of r4-r8 should work. */
|
|
213 #define CFA_REG 8
|
131
|
214 #endif
|
111
|
215
|
|
216 #elif defined (i386)
|
|
217
|
|
218 #define CFA_REG 7
|
|
219
|
|
220 #elif defined (__x86_64__)
|
|
221
|
|
222 /* R15 register */
|
|
223 #define CFA_REG 15
|
|
224
|
|
225 #else
|
|
226 Not_implemented;
|
|
227 #endif /* CFA setup block */
|
|
228
|
|
229 #define CFI_DEF_CFA \
|
|
230 CR(".cfi_def_cfa " S(CFA_REG) ", 0")
|
|
231
|
|
232 /* Register location blocks
|
|
233 ------------------------
|
|
234 Rules to find registers of interest from the CFA. This should comprise
|
|
235 all the non-volatile registers relevant to the interrupted context.
|
|
236
|
|
237 Note that we include r1 in this set, unlike the libgcc unwinding
|
|
238 fallbacks. This is useful for fallbacks to allow the use of r1 in CFI
|
|
239 expressions and the absence of rule for r1 gets compensated by using the
|
|
240 target CFA instead. We don't need the expression facility here and
|
|
241 setup a fake CFA to allow very simple offset expressions, so having a
|
|
242 rule for r1 is the proper thing to do. We for sure have observed
|
|
243 crashes in some cases without it. */
|
|
244
|
|
245 #if defined (__PPC__)
|
|
246
|
|
247 #define COMMON_CFI(REG) \
|
|
248 ".cfi_offset " S(REGNO_##REG) "," S(REG_SET_##REG)
|
|
249
|
|
250 #define CFI_COMMON_REGS \
|
|
251 CR("# CFI for common registers\n") \
|
|
252 TCR(COMMON_CFI(GR(0))) \
|
|
253 TCR(COMMON_CFI(GR(1))) \
|
|
254 TCR(COMMON_CFI(GR(2))) \
|
|
255 TCR(COMMON_CFI(GR(3))) \
|
|
256 TCR(COMMON_CFI(GR(4))) \
|
|
257 TCR(COMMON_CFI(GR(5))) \
|
|
258 TCR(COMMON_CFI(GR(6))) \
|
|
259 TCR(COMMON_CFI(GR(7))) \
|
|
260 TCR(COMMON_CFI(GR(8))) \
|
|
261 TCR(COMMON_CFI(GR(9))) \
|
|
262 TCR(COMMON_CFI(GR(10))) \
|
|
263 TCR(COMMON_CFI(GR(11))) \
|
|
264 TCR(COMMON_CFI(GR(12))) \
|
|
265 TCR(COMMON_CFI(GR(13))) \
|
|
266 TCR(COMMON_CFI(GR(14))) \
|
|
267 TCR(COMMON_CFI(GR(15))) \
|
|
268 TCR(COMMON_CFI(GR(16))) \
|
|
269 TCR(COMMON_CFI(GR(17))) \
|
|
270 TCR(COMMON_CFI(GR(18))) \
|
|
271 TCR(COMMON_CFI(GR(19))) \
|
|
272 TCR(COMMON_CFI(GR(20))) \
|
|
273 TCR(COMMON_CFI(GR(21))) \
|
|
274 TCR(COMMON_CFI(GR(22))) \
|
|
275 TCR(COMMON_CFI(GR(23))) \
|
|
276 TCR(COMMON_CFI(GR(24))) \
|
|
277 TCR(COMMON_CFI(GR(25))) \
|
|
278 TCR(COMMON_CFI(GR(26))) \
|
|
279 TCR(COMMON_CFI(GR(27))) \
|
|
280 TCR(COMMON_CFI(GR(28))) \
|
|
281 TCR(COMMON_CFI(GR(29))) \
|
|
282 TCR(COMMON_CFI(GR(30))) \
|
|
283 TCR(COMMON_CFI(GR(31))) \
|
|
284 TCR(COMMON_CFI(LR)) \
|
|
285 TCR(COMMON_CFI(CR)) \
|
|
286 TCR(COMMON_CFI(CTR)) \
|
|
287 TCR(COMMON_CFI(XER)) \
|
|
288 TCR(COMMON_CFI(PC)) \
|
|
289 TCR(".cfi_return_column " S(REGNO_PC))
|
|
290
|
|
291 /* Trampoline body block
|
|
292 --------------------- */
|
|
293
|
|
294 #if !defined (__PPC64__)
|
|
295 #define SIGTRAMP_BODY \
|
|
296 CR("") \
|
|
297 TCR("# Allocate frame and save the non-volatile") \
|
|
298 TCR("# registers we're going to modify") \
|
|
299 TCR("stwu %r1,-16(%r1)") \
|
|
300 TCR("mflr %r0") \
|
|
301 TCR("stw %r0,20(%r1)") \
|
|
302 TCR("stw %r" S(CFA_REG) ",8(%r1)") \
|
|
303 TCR("") \
|
|
304 TCR("# Setup CFA_REG = context, which we'll retrieve as our CFA value") \
|
|
305 TCR("mr %r" S(CFA_REG) ", %r7") \
|
|
306 TCR("") \
|
|
307 TCR("# Call the real handler. The signo, siginfo and sigcontext") \
|
|
308 TCR("# arguments are the same as those we received in r3, r4 and r5") \
|
|
309 TCR("mtctr %r6") \
|
|
310 TCR("bctrl") \
|
|
311 TCR("") \
|
|
312 TCR("# Restore our callee-saved items, release our frame and return") \
|
|
313 TCR("lwz %r" S(CFA_REG) ",8(%r1)") \
|
|
314 TCR("lwz %r0,20(%r1)") \
|
|
315 TCR("mtlr %r0") \
|
|
316 TCR("") \
|
|
317 TCR("addi %r1,%r1,16") \
|
|
318 TCR("blr")
|
|
319 #else
|
|
320 #define SIGTRAMP_BODY \
|
|
321 CR("") \
|
|
322 TCR("0:") \
|
|
323 TCR("addis 2,12,.TOC.-0@ha") \
|
|
324 TCR("addi 2,2,.TOC.-0@l") \
|
|
325 TCR(".localentry __gnat_sigtramp_common,.-__gnat_sigtramp_common") \
|
|
326 TCR("# Allocate frame and save the non-volatile") \
|
|
327 TCR("# registers we're going to modify") \
|
|
328 TCR("mflr %r0") \
|
|
329 TCR("std %r0,16(%r1)") \
|
|
330 TCR("stdu %r1,-32(%r1)") \
|
|
331 TCR("std %r2,24(%r1)") \
|
|
332 TCR("std %r" S(CFA_REG) ",8(%r1)") \
|
|
333 TCR("") \
|
|
334 TCR("# Setup CFA_REG = context, which we'll retrieve as our CFA value") \
|
|
335 TCR("mr %r" S(CFA_REG) ", %r7") \
|
|
336 TCR("") \
|
|
337 TCR("# Call the real handler. The signo, siginfo and sigcontext") \
|
|
338 TCR("# arguments are the same as those we received in r3, r4 and r5") \
|
|
339 TCR("mr %r12,%r6") \
|
|
340 TCR("mtctr %r6") \
|
|
341 TCR("bctrl") \
|
|
342 TCR("") \
|
|
343 TCR("# Restore our callee-saved items, release our frame and return") \
|
|
344 TCR("ld %r" S(CFA_REG) ",8(%r1)") \
|
|
345 TCR("ld %r2,24(%r1)") \
|
|
346 TCR("addi %r1,%r1,32") \
|
|
347 TCR("ld %r0,16(%r1)") \
|
|
348 TCR("mtlr %r0") \
|
|
349 TCR("blr")
|
|
350 #endif
|
|
351
|
131
|
352 #elif defined (ARMEL)
|
111
|
353
|
|
354 #define COMMON_CFI(REG) \
|
|
355 ".cfi_offset " S(REGNO_##REG) "," S(REG_SET_##REG)
|
|
356
|
131
|
357 #ifdef __aarch64__
|
|
358 #define CFI_COMMON_REGS \
|
|
359 CR("# CFI for common registers\n") \
|
|
360 TCR(COMMON_CFI(G_REG_OFFSET(0))) \
|
|
361 TCR(COMMON_CFI(G_REG_OFFSET(1))) \
|
|
362 TCR(COMMON_CFI(G_REG_OFFSET(2))) \
|
|
363 TCR(COMMON_CFI(G_REG_OFFSET(3))) \
|
|
364 TCR(COMMON_CFI(G_REG_OFFSET(4))) \
|
|
365 TCR(COMMON_CFI(G_REG_OFFSET(5))) \
|
|
366 TCR(COMMON_CFI(G_REG_OFFSET(6))) \
|
|
367 TCR(COMMON_CFI(G_REG_OFFSET(7))) \
|
|
368 TCR(COMMON_CFI(G_REG_OFFSET(8))) \
|
|
369 TCR(COMMON_CFI(G_REG_OFFSET(9))) \
|
|
370 TCR(COMMON_CFI(G_REG_OFFSET(10))) \
|
|
371 TCR(COMMON_CFI(G_REG_OFFSET(11))) \
|
|
372 TCR(COMMON_CFI(G_REG_OFFSET(12))) \
|
|
373 TCR(COMMON_CFI(G_REG_OFFSET(13))) \
|
|
374 TCR(COMMON_CFI(G_REG_OFFSET(14))) \
|
|
375 TCR(COMMON_CFI(G_REG_OFFSET(15))) \
|
|
376 TCR(COMMON_CFI(G_REG_OFFSET(16))) \
|
|
377 TCR(COMMON_CFI(G_REG_OFFSET(17))) \
|
|
378 TCR(COMMON_CFI(G_REG_OFFSET(18))) \
|
|
379 TCR(COMMON_CFI(G_REG_OFFSET(19))) \
|
|
380 TCR(COMMON_CFI(G_REG_OFFSET(20))) \
|
|
381 TCR(COMMON_CFI(G_REG_OFFSET(21))) \
|
|
382 TCR(COMMON_CFI(G_REG_OFFSET(22))) \
|
|
383 TCR(COMMON_CFI(G_REG_OFFSET(23))) \
|
|
384 TCR(COMMON_CFI(G_REG_OFFSET(24))) \
|
|
385 TCR(COMMON_CFI(G_REG_OFFSET(25))) \
|
|
386 TCR(COMMON_CFI(G_REG_OFFSET(26))) \
|
|
387 TCR(COMMON_CFI(G_REG_OFFSET(27))) \
|
|
388 TCR(COMMON_CFI(G_REG_OFFSET(28))) \
|
|
389 TCR(COMMON_CFI(G_REG_OFFSET(29))) \
|
|
390 TCR(COMMON_CFI(G_REG_OFFSET(30))) \
|
145
|
391 TCR(COMMON_CFI(G_REG_OFFSET(31))) \
|
131
|
392 TCR(COMMON_CFI(PC_OFFSET)) \
|
|
393 TCR(".cfi_return_column " S(REGNO_PC_OFFSET))
|
|
394 #else
|
111
|
395 #define CFI_COMMON_REGS \
|
|
396 CR("# CFI for common registers\n") \
|
|
397 TCR(COMMON_CFI(G_REG_OFFSET(0))) \
|
|
398 TCR(COMMON_CFI(G_REG_OFFSET(1))) \
|
|
399 TCR(COMMON_CFI(G_REG_OFFSET(2))) \
|
|
400 TCR(COMMON_CFI(G_REG_OFFSET(3))) \
|
|
401 TCR(COMMON_CFI(G_REG_OFFSET(4))) \
|
|
402 TCR(COMMON_CFI(G_REG_OFFSET(5))) \
|
|
403 TCR(COMMON_CFI(G_REG_OFFSET(6))) \
|
|
404 TCR(COMMON_CFI(G_REG_OFFSET(7))) \
|
|
405 TCR(COMMON_CFI(G_REG_OFFSET(8))) \
|
|
406 TCR(COMMON_CFI(G_REG_OFFSET(9))) \
|
|
407 TCR(COMMON_CFI(G_REG_OFFSET(10))) \
|
|
408 TCR(COMMON_CFI(G_REG_OFFSET(11))) \
|
|
409 TCR(COMMON_CFI(G_REG_OFFSET(12))) \
|
|
410 TCR(COMMON_CFI(G_REG_OFFSET(13))) \
|
|
411 TCR(COMMON_CFI(G_REG_OFFSET(14))) \
|
|
412 TCR(COMMON_CFI(PC_OFFSET)) \
|
|
413 TCR(".cfi_return_column " S(REGNO_PC_OFFSET))
|
131
|
414 #endif
|
111
|
415
|
|
416 /* Trampoline body block
|
|
417 --------------------- */
|
131
|
418 #ifdef __aarch64__
|
|
419 #define SIGTRAMP_BODY \
|
|
420 CR("") \
|
|
421 TCR("# Allocate the frame (16bytes aligned) and push FP and LR") \
|
|
422 TCR("stp x29, x30, [sp, #-32]!") \
|
|
423 TCR("add x29, sp, 0") \
|
|
424 TCR("# Store register used to hold the CFA on stack (pro forma)") \
|
|
425 TCR("str x" S(CFA_REG) ", [sp, 16]") \
|
|
426 TCR("# Set the CFA reg from the 5th arg") \
|
|
427 TCR("mov x" S(CFA_REG) ", x4") \
|
|
428 TCR("# Call the handler") \
|
|
429 TCR("blr x3") \
|
|
430 TCR("# Release our frame and return (should never get here!).") \
|
|
431 TCR("ldr x" S(CFA_REG) ", [sp, 16]") \
|
|
432 TCR("ldp x29, x30, [sp], 32") \
|
|
433 TCR("ret")
|
|
434 #else
|
111
|
435 #define SIGTRAMP_BODY \
|
|
436 CR("") \
|
|
437 TCR("# Allocate frame and save the non-volatile") \
|
|
438 TCR("# registers we're going to modify") \
|
|
439 TCR("mov ip, sp") \
|
|
440 TCR("stmfd sp!, {r"S(CFA_REG)", fp, ip, lr, pc}") \
|
|
441 TCR("# Setup CFA_REG = context, which we'll retrieve as our CFA value") \
|
|
442 TCR("ldr r"S(CFA_REG)", [ip]") \
|
|
443 TCR("") \
|
|
444 TCR("# Call the real handler. The signo, siginfo and sigcontext") \
|
|
445 TCR("# arguments are the same as those we received in r0, r1 and r2") \
|
|
446 TCR("sub fp, ip, #4") \
|
|
447 TCR("blx r3") \
|
|
448 TCR("# Restore our callee-saved items, release our frame and return") \
|
|
449 TCR("ldmfd sp, {r"S(CFA_REG)", fp, sp, pc}")
|
131
|
450 #endif
|
111
|
451
|
|
452 #elif defined (i386)
|
|
453
|
|
454 #if CPU == SIMNT || CPU == SIMPENTIUM || CPU == SIMLINUX
|
|
455 #define COMMON_CFI(REG) \
|
|
456 ".cfi_offset " S(REGNO_##REG) "," S(REG_SET_##REG)
|
|
457 #else
|
|
458 #define COMMON_CFI(REG) \
|
|
459 ".cfi_offset " S(REGNO_##REG) "," S(REG_##REG)
|
|
460 #endif
|
|
461
|
|
462 #define PC_CFI(REG) \
|
|
463 ".cfi_offset " S(REGNO_##REG) "," S(REG_##REG)
|
|
464
|
|
465 #define CFI_COMMON_REGS \
|
|
466 CR("# CFI for common registers\n") \
|
|
467 TCR(COMMON_CFI(EDI)) \
|
|
468 TCR(COMMON_CFI(ESI)) \
|
|
469 TCR(COMMON_CFI(EBP)) \
|
|
470 TCR(COMMON_CFI(ESP)) \
|
|
471 TCR(COMMON_CFI(EBX)) \
|
|
472 TCR(COMMON_CFI(EDX)) \
|
|
473 TCR(COMMON_CFI(ECX)) \
|
|
474 TCR(COMMON_CFI(EAX)) \
|
|
475 TCR(COMMON_CFI(EFLAGS)) \
|
|
476 TCR(PC_CFI(SET_PC)) \
|
|
477 TCR(".cfi_return_column " S(REGNO_SET_PC))
|
|
478
|
|
479 /* Trampoline body block
|
|
480 --------------------- */
|
|
481
|
|
482 #define SIGTRAMP_BODY \
|
|
483 CR("") \
|
|
484 TCR("# Allocate frame and save the non-volatile") \
|
|
485 TCR("# registers we're going to modify") \
|
|
486 TCR("pushl %ebp") \
|
|
487 TCR("movl %esp, %ebp") \
|
|
488 TCR("pushl %edi") \
|
|
489 TCR("subl $24, %esp") \
|
|
490 TCR("# Setup CFA_REG = context, which we'll retrieve as our CFA value") \
|
|
491 TCR("movl 24(%ebp), %edi") \
|
|
492 TCR("# Call the real handler. The signo, siginfo and sigcontext") \
|
|
493 TCR("# arguments are the same as those we received") \
|
|
494 TCR("movl 16(%ebp), %eax") \
|
|
495 TCR("movl %eax, 8(%esp)") \
|
|
496 TCR("movl 12(%ebp), %eax") \
|
|
497 TCR("movl %eax, 4(%esp)") \
|
|
498 TCR("movl 8(%ebp), %eax") \
|
|
499 TCR("movl %eax, (%esp)") \
|
|
500 TCR("call *20(%ebp)") \
|
|
501 TCR("# Restore our callee-saved items, release our frame and return") \
|
|
502 TCR("popl %edi") \
|
|
503 TCR("leave") \
|
|
504 TCR("ret")
|
|
505
|
|
506 #elif defined (__x86_64__)
|
|
507
|
|
508 #define COMMON_CFI(REG) \
|
|
509 ".cfi_offset " S(REGNO_##REG) "," S(REG_##REG)
|
|
510
|
|
511 #define CFI_COMMON_REGS \
|
|
512 CR("# CFI for common registers\n") \
|
|
513 TCR(COMMON_CFI(R15)) \
|
|
514 TCR(COMMON_CFI(R14)) \
|
|
515 TCR(COMMON_CFI(R13)) \
|
|
516 TCR(COMMON_CFI(R12)) \
|
|
517 TCR(COMMON_CFI(R11)) \
|
|
518 TCR(COMMON_CFI(R10)) \
|
|
519 TCR(COMMON_CFI(R9)) \
|
|
520 TCR(COMMON_CFI(R8)) \
|
|
521 TCR(COMMON_CFI(RDI)) \
|
|
522 TCR(COMMON_CFI(RSI)) \
|
|
523 TCR(COMMON_CFI(RBP)) \
|
|
524 TCR(COMMON_CFI(RSP)) \
|
|
525 TCR(COMMON_CFI(RBX)) \
|
|
526 TCR(COMMON_CFI(RDX)) \
|
|
527 TCR(COMMON_CFI(RCX)) \
|
|
528 TCR(COMMON_CFI(RAX)) \
|
|
529 TCR(COMMON_CFI(RPC)) \
|
|
530 TCR(".cfi_return_column " S(REGNO_RPC))
|
|
531
|
|
532 /* Trampoline body block
|
|
533 --------------------- */
|
|
534
|
|
535 #define SIGTRAMP_BODY \
|
|
536 CR("") \
|
|
537 TCR("# Allocate frame and save the non-volatile") \
|
|
538 TCR("# registers we're going to modify") \
|
|
539 TCR("subq $8, %rsp") \
|
|
540 TCR("# Setup CFA_REG = context, which we'll retrieve as our CFA value") \
|
|
541 TCR("movq %r8, %r15") \
|
|
542 TCR("# Call the real handler. The signo, siginfo and sigcontext") \
|
|
543 TCR("# arguments are the same as those we received") \
|
|
544 TCR("call *%rcx") \
|
|
545 TCR("# This part should never be executed") \
|
|
546 TCR("addq $8, %rsp") \
|
|
547 TCR("ret")
|
|
548
|
|
549 #else
|
|
550 Not_implemented;
|
|
551 #endif /* CFI_COMMON_REGS and SIGTRAMP_BODY */
|
|
552
|
|
553 /* Symbol definition block
|
|
554 ----------------------- */
|
|
555
|
|
556 #ifdef __x86_64__
|
|
557 #define FUNC_ALIGN TCR(".p2align 4,,15")
|
|
558 #else
|
|
559 #define FUNC_ALIGN
|
|
560 #endif
|
|
561
|
|
562 #define SIGTRAMP_START(SYM) \
|
|
563 CR("# " S(SYM) " cfi trampoline") \
|
|
564 TCR(".type " S(SYM) ", "FUNCTION) \
|
|
565 CR("") \
|
|
566 FUNC_ALIGN \
|
|
567 CR(S(SYM) ":") \
|
|
568 TCR(".cfi_startproc") \
|
|
569 TCR(".cfi_signal_frame")
|
|
570
|
|
571 /* Symbol termination block
|
|
572 ------------------------ */
|
|
573
|
|
574 #define SIGTRAMP_END(SYM) \
|
|
575 CR(".cfi_endproc") \
|
|
576 TCR(".size " S(SYM) ", .-" S(SYM))
|
|
577
|
|
578 /*----------------------------
|
|
579 -- And now, the real code --
|
|
580 ---------------------------- */
|
|
581
|
|
582 /* Text section start. The compiler isn't aware of that switch. */
|
|
583
|
|
584 asm (".text\n"
|
|
585 TCR(".align 2"));
|