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 *                                                                          *
9 *         Copyright (C) 2011-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 * 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
96#elif defined (__ARMEL__)
97
98#define REGNO_G_REG_OFFSET(N) (N)
99
100#define REGNO_PC_OFFSET  15  /* PC_REGNUM  */
101
102#define FUNCTION "%function"
103
104#elif defined (i386)
105
106/* These are the cfi colunm numbers */
107
108#define REGNO_EDI 7
109#define REGNO_ESI 6
110#define REGNO_EBP 5
111#define REGNO_ESP 4
112#define REGNO_EBX 3
113#define REGNO_EDX 2
114#define REGNO_ECX 1
115#define REGNO_EAX 0
116#define REGNO_EFLAGS 9
117#define REGNO_SET_PC 8 /* aka %eip */
118
119#define FUNCTION "@function"
120
121/* Mapping of CFI Column, Gcc Regno, Signal context offset for 32bit
122
123   Name	   CFI	   GCC	   SCTX
124   %eax	    0	    0	    7
125   %ecx	    1	    2	    6
126   %edx	    2	    1	    5
127   %ebx     3	    3	    4
128   %esp	    4	    7	    3
129   %ebp	    5	    6	    2
130   %esi	    6	    4	    1
131   %edi	    7	    5	    0
132   %eflags  9	   17 	    8
133   %eip	    8	  n/a	    9
134
135
136   In general:
137   There is no unique numbering for the x86 architecture.  It's parameterized
138   by DWARF_FRAME_REGNUM, which is DBX_REGISTER_NUMBER except for Windows, and
139   the latter depends on the platform.
140*/
141
142#elif defined (__x86_64__)
143
144/* These are the cfi colunm numbers */
145
146#define REGNO_RAX 0
147#define REGNO_RDX 1
148#define REGNO_RCX 2
149#define REGNO_RBX 3
150#define REGNO_RSI 4
151#define REGNO_RDI 5
152#define REGNO_RBP 6
153#define REGNO_RSP 7
154#define REGNO_R8 8
155#define REGNO_R9 9
156#define REGNO_R10 10
157#define REGNO_R11 11
158#define REGNO_R12 12
159#define REGNO_R13 13
160#define REGNO_R14 14
161#define REGNO_R15 15
162#define REGNO_SET_PC 16 /* aka %rip */
163#define REGNO_EFLAGS 49
164#define REGNO_FS 54
165
166#define FUNCTION "@function"
167
168#else
169Not_implemented;
170#endif /* REGNO constants */
171
172
173/*------------------------------
174  -- Stub construction blocks --
175  ------------------------------ */
176
177/* CFA setup block
178   ---------------
179   Only non-volatile registers are suitable for a CFA base. These are the
180   only ones we can expect to be able retrieve from the unwinding context
181   while walking up the chain, saved by at least the bottom-most exception
182   propagation services.  We set a non-volatile register to the value we
183   need in the stub body that follows.  */
184
185#if defined (__PPC__)
186
187/* Use r15 for PPC.  Note that r14 is inappropriate here, even though it
188   is non-volatile according to the ABI, because GCC uses it as an extra
189   SCRATCH on SPE targets.  */
190
191#define CFA_REG 15
192
193#elif defined (__ARMEL__)
194
195/* Use r8 for ARM.  Any of r4-r8 should work.  */
196
197#define CFA_REG 8
198
199#elif defined (i386)
200
201#define CFA_REG 7
202
203#elif defined (__x86_64__)
204
205/* R15 register */
206#define CFA_REG 15
207
208#else
209Not_implemented;
210#endif /* CFA setup block */
211
212#define CFI_DEF_CFA \
213CR(".cfi_def_cfa " S(CFA_REG) ", 0")
214
215/* Register location blocks
216   ------------------------
217   Rules to find registers of interest from the CFA. This should comprise
218   all the non-volatile registers relevant to the interrupted context.
219
220   Note that we include r1 in this set, unlike the libgcc unwinding
221   fallbacks.  This is useful for fallbacks to allow the use of r1 in CFI
222   expressions and the absence of rule for r1 gets compensated by using the
223   target CFA instead.  We don't need the expression facility here and
224   setup a fake CFA to allow very simple offset expressions, so having a
225   rule for r1 is the proper thing to do.  We for sure have observed
226   crashes in some cases without it.  */
227
228#if defined (__PPC__)
229
230#define COMMON_CFI(REG) \
231  ".cfi_offset " S(REGNO_##REG) "," S(REG_SET_##REG)
232
233#define CFI_COMMON_REGS \
234CR("# CFI for common registers\n") \
235TCR(COMMON_CFI(GR(0)))  \
236TCR(COMMON_CFI(GR(1)))  \
237TCR(COMMON_CFI(GR(2)))  \
238TCR(COMMON_CFI(GR(3)))  \
239TCR(COMMON_CFI(GR(4)))  \
240TCR(COMMON_CFI(GR(5)))  \
241TCR(COMMON_CFI(GR(6)))  \
242TCR(COMMON_CFI(GR(7)))  \
243TCR(COMMON_CFI(GR(8)))  \
244TCR(COMMON_CFI(GR(9)))  \
245TCR(COMMON_CFI(GR(10)))  \
246TCR(COMMON_CFI(GR(11)))  \
247TCR(COMMON_CFI(GR(12)))  \
248TCR(COMMON_CFI(GR(13)))  \
249TCR(COMMON_CFI(GR(14))) \
250TCR(COMMON_CFI(GR(15))) \
251TCR(COMMON_CFI(GR(16))) \
252TCR(COMMON_CFI(GR(17))) \
253TCR(COMMON_CFI(GR(18))) \
254TCR(COMMON_CFI(GR(19))) \
255TCR(COMMON_CFI(GR(20))) \
256TCR(COMMON_CFI(GR(21))) \
257TCR(COMMON_CFI(GR(22))) \
258TCR(COMMON_CFI(GR(23))) \
259TCR(COMMON_CFI(GR(24))) \
260TCR(COMMON_CFI(GR(25))) \
261TCR(COMMON_CFI(GR(26))) \
262TCR(COMMON_CFI(GR(27))) \
263TCR(COMMON_CFI(GR(28))) \
264TCR(COMMON_CFI(GR(29))) \
265TCR(COMMON_CFI(GR(30))) \
266TCR(COMMON_CFI(GR(31))) \
267TCR(COMMON_CFI(LR)) \
268TCR(COMMON_CFI(CR)) \
269TCR(COMMON_CFI(CTR)) \
270TCR(COMMON_CFI(XER)) \
271TCR(COMMON_CFI(PC)) \
272TCR(".cfi_return_column " S(REGNO_PC))
273
274/* Trampoline body block
275   ---------------------  */
276
277#define SIGTRAMP_BODY \
278CR("") \
279TCR("# Allocate frame and save the non-volatile") \
280TCR("# registers we're going to modify") \
281TCR("stwu %r1,-16(%r1)")  \
282TCR("mflr %r0")	\
283TCR("stw %r0,20(%r1)")	\
284TCR("stw %r" S(CFA_REG) ",8(%r1)")	\
285TCR("")			\
286TCR("# Setup CFA_REG = context, which we'll retrieve as our CFA value") \
287TCR("mr %r" S(CFA_REG) ", %r7") \
288TCR("")			\
289TCR("# Call the real handler. The signo, siginfo and sigcontext") \
290TCR("# arguments are the same as those we received in r3, r4 and r5") \
291TCR("mtctr %r6") \
292TCR("bctrl")	\
293TCR("")		\
294TCR("# Restore our callee-saved items, release our frame and return") \
295TCR("lwz %r" S(CFA_REG) ",8(%r1)")	\
296TCR("lwz %r0,20(%r1)")	\
297TCR("mtlr %r0")		\
298TCR("")			\
299TCR("addi %r1,%r1,16")	\
300TCR("blr")
301
302#elif defined (__ARMEL__)
303
304#define COMMON_CFI(REG) \
305  ".cfi_offset " S(REGNO_##REG) "," S(REG_SET_##REG)
306
307#define CFI_COMMON_REGS \
308CR("# CFI for common registers\n") \
309TCR(COMMON_CFI(G_REG_OFFSET(0)))  \
310TCR(COMMON_CFI(G_REG_OFFSET(1)))  \
311TCR(COMMON_CFI(G_REG_OFFSET(2)))  \
312TCR(COMMON_CFI(G_REG_OFFSET(3)))  \
313TCR(COMMON_CFI(G_REG_OFFSET(4)))  \
314TCR(COMMON_CFI(G_REG_OFFSET(5)))  \
315TCR(COMMON_CFI(G_REG_OFFSET(6)))  \
316TCR(COMMON_CFI(G_REG_OFFSET(7)))  \
317TCR(COMMON_CFI(G_REG_OFFSET(8)))  \
318TCR(COMMON_CFI(G_REG_OFFSET(9)))  \
319TCR(COMMON_CFI(G_REG_OFFSET(10)))  \
320TCR(COMMON_CFI(G_REG_OFFSET(11)))  \
321TCR(COMMON_CFI(G_REG_OFFSET(12)))  \
322TCR(COMMON_CFI(G_REG_OFFSET(13)))  \
323TCR(COMMON_CFI(G_REG_OFFSET(14))) \
324TCR(COMMON_CFI(PC_OFFSET)) \
325TCR(".cfi_return_column " S(REGNO_PC_OFFSET))
326
327/* Trampoline body block
328   ---------------------  */
329
330#define SIGTRAMP_BODY \
331CR("") \
332TCR("# Allocate frame and save the non-volatile") \
333TCR("# registers we're going to modify") \
334TCR("mov	ip, sp") \
335TCR("stmfd	sp!, {r"S(CFA_REG)", fp, ip, lr, pc}") \
336TCR("# Setup CFA_REG = context, which we'll retrieve as our CFA value") \
337TCR("ldr	r"S(CFA_REG)", [ip]") \
338TCR("")                 \
339TCR("# Call the real handler. The signo, siginfo and sigcontext") \
340TCR("# arguments are the same as those we received in r0, r1 and r2") \
341TCR("sub	fp, ip, #4") \
342TCR("blx	r3") \
343TCR("# Restore our callee-saved items, release our frame and return") \
344TCR("ldmfd	sp, {r"S(CFA_REG)", fp, sp, pc}")
345
346#elif defined (i386)
347
348#if CPU == SIMNT || CPU == SIMPENTIUM || CPU == SIMLINUX
349#define COMMON_CFI(REG) \
350  ".cfi_offset " S(REGNO_##REG) "," S(REG_SET_##REG)
351#else
352#define COMMON_CFI(REG) \
353  ".cfi_offset " S(REGNO_##REG) "," S(REG_##REG)
354#endif
355
356#define PC_CFI(REG) \
357  ".cfi_offset " S(REGNO_##REG) "," S(REG_##REG)
358
359#define CFI_COMMON_REGS \
360CR("# CFI for common registers\n") \
361TCR(COMMON_CFI(EDI)) \
362TCR(COMMON_CFI(ESI)) \
363TCR(COMMON_CFI(EBP)) \
364TCR(COMMON_CFI(ESP)) \
365TCR(COMMON_CFI(EBX)) \
366TCR(COMMON_CFI(EDX)) \
367TCR(COMMON_CFI(ECX)) \
368TCR(COMMON_CFI(EAX)) \
369TCR(COMMON_CFI(EFLAGS)) \
370TCR(PC_CFI(SET_PC)) \
371TCR(".cfi_return_column " S(REGNO_SET_PC))
372
373/* Trampoline body block
374   ---------------------  */
375
376#define SIGTRAMP_BODY \
377CR("") \
378TCR("# Allocate frame and save the non-volatile") \
379TCR("# registers we're going to modify") \
380TCR("pushl	%ebp") \
381TCR("movl	%esp, %ebp") \
382TCR("pushl	%edi") \
383TCR("subl	$24, %esp") \
384TCR("# Setup CFA_REG = context, which we'll retrieve as our CFA value") \
385TCR("movl	24(%ebp), %edi") \
386TCR("# Call the real handler. The signo, siginfo and sigcontext") \
387TCR("# arguments are the same as those we received") \
388TCR("movl	16(%ebp), %eax") \
389TCR("movl	%eax, 8(%esp)") \
390TCR("movl	12(%ebp), %eax") \
391TCR("movl	%eax, 4(%esp)") \
392TCR("movl	8(%ebp), %eax") \
393TCR("movl	%eax, (%esp)") \
394TCR("call	*20(%ebp)") \
395TCR("# Restore our callee-saved items, release our frame and return") \
396TCR("popl	%edi") \
397TCR("leave") \
398TCR("ret")
399
400#elif defined (__x86_64__)
401
402#define COMMON_CFI(REG) \
403  ".cfi_offset " S(REGNO_##REG) "," S(REG_##REG)
404#define PC_CFI(REG) \
405  ".cfi_offset " S(REGNO_##REG) "," S(REG_##REG)
406
407#define CFI_COMMON_REGS \
408CR("# CFI for common registers\n") \
409TCR(COMMON_CFI(R15)) \
410TCR(COMMON_CFI(R14)) \
411TCR(COMMON_CFI(R13)) \
412TCR(COMMON_CFI(R12)) \
413TCR(COMMON_CFI(R11)) \
414TCR(COMMON_CFI(R10)) \
415TCR(COMMON_CFI(R9)) \
416TCR(COMMON_CFI(R8)) \
417TCR(COMMON_CFI(RDI)) \
418TCR(COMMON_CFI(RSI)) \
419TCR(COMMON_CFI(RBP)) \
420TCR(COMMON_CFI(RSP)) \
421TCR(COMMON_CFI(RBX)) \
422TCR(COMMON_CFI(RDX)) \
423TCR(COMMON_CFI(RCX)) \
424TCR(COMMON_CFI(RAX)) \
425TCR(COMMON_CFI(EFLAGS)) \
426TCR(COMMON_CFI(SET_PC)) \
427TCR(COMMON_CFI(FS)) \
428TCR(".cfi_return_column " S(REGNO_SET_PC))
429
430/* Trampoline body block
431   ---------------------  */
432
433#define SIGTRAMP_BODY \
434CR("") \
435TCR("# Allocate frame and save the non-volatile") \
436TCR("# registers we're going to modify") \
437TCR("subq	$8, %rsp") \
438TCR("# Setup CFA_REG = context, which we'll retrieve as our CFA value") \
439TCR("movq	%r8, %r15") \
440TCR("# Call the real handler. The signo, siginfo and sigcontext") \
441TCR("# arguments are the same as those we received") \
442TCR("call	*%rcx") \
443TCR("# This part should never be executed") \
444TCR("addq	$8, %rsp") \
445TCR("ret")
446
447#else
448Not_implemented;
449#endif /* CFI_COMMON_REGS and SIGTRAMP_BODY */
450
451/* Symbol definition block
452   -----------------------  */
453
454#define SIGTRAMP_START(SYM) \
455CR("# " S(SYM) " cfi trampoline") \
456TCR(".type " S(SYM) ", "FUNCTION) \
457CR("") \
458CR(S(SYM) ":") \
459TCR(".cfi_startproc") \
460TCR(".cfi_signal_frame")
461
462/* Symbol termination block
463   ------------------------  */
464
465#define SIGTRAMP_END(SYM) \
466CR(".cfi_endproc") \
467TCR(".size " S(SYM) ", .-" S(SYM))
468
469/*----------------------------
470  -- And now, the real code --
471  ---------------------------- */
472
473/* Text section start.  The compiler isn't aware of that switch.  */
474
475asm (".text\n"
476     TCR(".align 2"));
477
478