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) 2011-2014, 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 version of the __gnat_sigtramp service *
34 **************************************************/
35
36#include "sigtramp.h"
37/* See sigtramp.h for a general explanation of functionality.  */
38
39#include <vxWorks.h>
40#include <arch/../regs.h>
41#ifndef __RTP__
42#include <sigLib.h>
43#else
44#include <signal.h>
45#include <regs.h>
46
47typedef struct mcontext
48  {
49    REG_SET     regs;
50  } mcontext_t;
51
52typedef struct ucontext
53  {
54    mcontext_t          uc_mcontext;    /* register set */
55    struct ucontext *   uc_link;        /* not used */
56    sigset_t            uc_sigmask;     /* set of signals blocked */
57    stack_t             uc_stack;       /* stack of context signaled */
58  } ucontext_t;
59#endif
60
61/* ----------------------
62   -- General comments --
63   ----------------------
64
65   Stubs are generated from toplevel asms and .cfi directives, much simpler
66   to use and check for correctness than manual encodings of CFI byte
67   sequences.  The general idea is to establish CFA as sigcontext->sc_pregs
68   (for DKM) and mcontext (for RTP) and state where to find the registers as
69   offsets from there.
70
71   As of today, we support a stub providing CFI info for common
72   registers (GPRs, LR, ...). We might need variants with support for floating
73   point or altivec registers as well at some point.
74
75   Checking which variant should apply and getting at sc_pregs / mcontext
76   is simpler to express in C (we can't use offsetof in toplevel asms and
77   hardcoding constants is not workable with the flurry of VxWorks variants),
78   so this is the choice for our toplevel interface.
79
80   Note that the registers we "restore" here are those to which we have
81   direct access through the system sigcontext structure, which includes
82   only a partial set of the non-volatiles ABI-wise.  */
83
84/* -------------------------------------------
85   -- Prototypes for our internal asm stubs --
86   -------------------------------------------
87
88   Eventhough our symbols will remain local, the prototype claims "extern"
89   and not "static" to prevent compiler complaints about a symbol used but
90   never defined.  */
91
92/* sigtramp stub providing CFI info for common registers.  */
93
94extern void __gnat_sigtramp_common
95(int signo, void *siginfo, void *sigcontext,
96 __sigtramphandler_t * handler, void * sc_pregs);
97
98
99/* -------------------------------------
100   -- Common interface implementation --
101   -------------------------------------
102
103   We enforce optimization to minimize the overhead of the extra layer.  */
104
105void __gnat_sigtramp (int signo, void *si, void *sc,
106		      __sigtramphandler_t * handler)
107     __attribute__((optimize(2)));
108
109void __gnat_sigtramp (int signo, void *si, void *sc,
110		      __sigtramphandler_t * handler)
111{
112#ifdef __RTP__
113  mcontext_t *mcontext = &((ucontext_t *) sc)->uc_mcontext;
114
115  /* Pass MCONTEXT in the fifth position so that the assembly code can find
116     it at the same stack location or in the same register as SC_PREGS.  */
117  __gnat_sigtramp_common (signo, si, mcontext, handler, mcontext);
118#else
119  struct sigcontext * sctx = (struct sigcontext *) sc;
120
121  __gnat_sigtramp_common (signo, si, sctx, handler, sctx->sc_pregs);
122#endif
123}
124
125
126/* ---------------------------
127   -- And now the asm stubs --
128   ---------------------------
129
130   They all have a common structure with blocks of asm sequences queued one
131   after the others.  Typically:
132
133   SYMBOL_START
134
135   CFI_DIRECTIVES
136     CFI_DEF_CFA,
137     CFI_COMMON_REGISTERS,
138     ...
139
140   STUB_BODY
141     asm code to establish frame, setup the cfa reg value,
142     call the real signal handler, ...
143
144   SYMBOL_END
145*/
146
147/*--------------------------------
148  -- Misc constants and helpers --
149  -------------------------------- */
150
151/* asm string construction helpers.  */
152
153#define STR(TEXT) #TEXT
154/* stringify expanded TEXT, surrounding it with double quotes.  */
155
156#define S(E) STR(E)
157/* stringify E, which will resolve as text but may contain macros
158   still to be expanded.  */
159
160/* asm (TEXT) outputs <tab>TEXT. These facilitate the output of
161   multine contents:  */
162#define TAB(S) "\t" S
163#define CR(S)  S "\n"
164
165#undef TCR
166#define TCR(S) TAB(CR(S))
167
168/* REGNO constants, dwarf column numbers for registers of interest.  */
169
170#if defined (__PPC__)
171
172#define REGNO_LR  65
173#define REGNO_CTR 66
174#define REGNO_CR  70
175#define REGNO_XER 76
176#define REGNO_GR(N) (N)
177
178#define REGNO_PC  67  /* ARG_POINTER_REGNUM  */
179
180#define FUNCTION "@function"
181
182#elif defined (__ARMEL__)
183
184#define REGNO_G_REG_OFFSET(N) (N)
185
186#define REGNO_PC_OFFSET  15  /* PC_REGNUM  */
187
188#define FUNCTION "%function"
189
190#else
191Not_implemented;
192#endif /* REGNO constants */
193
194
195/*------------------------------
196  -- Stub construction blocks --
197  ------------------------------ */
198
199/* CFA setup block
200   ---------------
201   Only non-volatile registers are suitable for a CFA base. These are the
202   only ones we can expect to be able retrieve from the unwinding context
203   while walking up the chain, saved by at least the bottom-most exception
204   propagation services.  We set a non-volatile register to the value we
205   need in the stub body that follows.  */
206
207#if defined (__PPC__)
208
209/* Use r15 for PPC.  Note that r14 is inappropriate here, even though it
210   is non-volatile according to the ABI, because GCC uses it as an extra
211   SCRATCH on SPE targets.  */
212
213#define CFA_REG 15
214
215#elif defined (__ARMEL__)
216
217/* Use r8 for ARM.  Any of r4-r8 should work.  */
218
219#define CFA_REG 8
220
221#else
222Not_implemented;
223#endif /* CFA setup block */
224
225#define CFI_DEF_CFA \
226CR(".cfi_def_cfa " S(CFA_REG) ", 0")
227
228/* Register location blocks
229   ------------------------
230   Rules to find registers of interest from the CFA. This should comprise
231   all the non-volatile registers relevant to the interrupted context.
232
233   Note that we include r1 in this set, unlike the libgcc unwinding
234   fallbacks.  This is useful for fallbacks to allow the use of r1 in CFI
235   expressions and the absence of rule for r1 gets compensated by using the
236   target CFA instead.  We don't need the expression facility here and
237   setup a fake CFA to allow very simple offset expressions, so having a
238   rule for r1 is the proper thing to do.  We for sure have observed
239   crashes in some cases without it.  */
240
241#define COMMON_CFI(REG) \
242  ".cfi_offset " S(REGNO_##REG) "," S(REG_SET_##REG)
243
244#if defined (__PPC__)
245
246#define CFI_COMMON_REGS \
247CR("# CFI for common registers\n") \
248TCR(COMMON_CFI(GR(0)))  \
249TCR(COMMON_CFI(GR(1)))  \
250TCR(COMMON_CFI(GR(2)))  \
251TCR(COMMON_CFI(GR(3)))  \
252TCR(COMMON_CFI(GR(4)))  \
253TCR(COMMON_CFI(GR(5)))  \
254TCR(COMMON_CFI(GR(6)))  \
255TCR(COMMON_CFI(GR(7)))  \
256TCR(COMMON_CFI(GR(8)))  \
257TCR(COMMON_CFI(GR(9)))  \
258TCR(COMMON_CFI(GR(10)))  \
259TCR(COMMON_CFI(GR(11)))  \
260TCR(COMMON_CFI(GR(12)))  \
261TCR(COMMON_CFI(GR(13)))  \
262TCR(COMMON_CFI(GR(14))) \
263TCR(COMMON_CFI(GR(15))) \
264TCR(COMMON_CFI(GR(16))) \
265TCR(COMMON_CFI(GR(17))) \
266TCR(COMMON_CFI(GR(18))) \
267TCR(COMMON_CFI(GR(19))) \
268TCR(COMMON_CFI(GR(20))) \
269TCR(COMMON_CFI(GR(21))) \
270TCR(COMMON_CFI(GR(22))) \
271TCR(COMMON_CFI(GR(23))) \
272TCR(COMMON_CFI(GR(24))) \
273TCR(COMMON_CFI(GR(25))) \
274TCR(COMMON_CFI(GR(26))) \
275TCR(COMMON_CFI(GR(27))) \
276TCR(COMMON_CFI(GR(28))) \
277TCR(COMMON_CFI(GR(29))) \
278TCR(COMMON_CFI(GR(30))) \
279TCR(COMMON_CFI(GR(31))) \
280TCR(COMMON_CFI(LR)) \
281TCR(COMMON_CFI(CR)) \
282TCR(COMMON_CFI(CTR)) \
283TCR(COMMON_CFI(XER)) \
284TCR(COMMON_CFI(PC)) \
285TCR(".cfi_return_column " S(REGNO_PC))
286
287/* Trampoline body block
288   ---------------------  */
289
290#define SIGTRAMP_BODY \
291CR("") \
292TCR("# Allocate frame and save the non-volatile") \
293TCR("# registers we're going to modify") \
294TCR("stwu %r1,-16(%r1)")  \
295TCR("mflr %r0")	\
296TCR("stw %r0,20(%r1)")	\
297TCR("stw %r" S(CFA_REG) ",8(%r1)")	\
298TCR("")			\
299TCR("# Setup CFA_REG = context, which we'll retrieve as our CFA value") \
300TCR("mr %r" S(CFA_REG) ", %r7") \
301TCR("")			\
302TCR("# Call the real handler. The signo, siginfo and sigcontext") \
303TCR("# arguments are the same as those we received in r3, r4 and r5") \
304TCR("mtctr %r6") \
305TCR("bctrl")	\
306TCR("")		\
307TCR("# Restore our callee-saved items, release our frame and return") \
308TCR("lwz %r" S(CFA_REG) ",8(%r1)")	\
309TCR("lwz %r0,20(%r1)")	\
310TCR("mtlr %r0")		\
311TCR("")			\
312TCR("addi %r1,%r1,16")	\
313TCR("blr")
314
315#elif defined (__ARMEL__)
316
317#define CFI_COMMON_REGS \
318CR("# CFI for common registers\n") \
319TCR(COMMON_CFI(G_REG_OFFSET(0)))  \
320TCR(COMMON_CFI(G_REG_OFFSET(1)))  \
321TCR(COMMON_CFI(G_REG_OFFSET(2)))  \
322TCR(COMMON_CFI(G_REG_OFFSET(3)))  \
323TCR(COMMON_CFI(G_REG_OFFSET(4)))  \
324TCR(COMMON_CFI(G_REG_OFFSET(5)))  \
325TCR(COMMON_CFI(G_REG_OFFSET(6)))  \
326TCR(COMMON_CFI(G_REG_OFFSET(7)))  \
327TCR(COMMON_CFI(G_REG_OFFSET(8)))  \
328TCR(COMMON_CFI(G_REG_OFFSET(9)))  \
329TCR(COMMON_CFI(G_REG_OFFSET(10)))  \
330TCR(COMMON_CFI(G_REG_OFFSET(11)))  \
331TCR(COMMON_CFI(G_REG_OFFSET(12)))  \
332TCR(COMMON_CFI(G_REG_OFFSET(13)))  \
333TCR(COMMON_CFI(G_REG_OFFSET(14))) \
334TCR(COMMON_CFI(PC_OFFSET)) \
335TCR(".cfi_return_column " S(REGNO_PC_OFFSET))
336
337/* Trampoline body block
338   ---------------------  */
339
340#define SIGTRAMP_BODY \
341CR("") \
342TCR("# Allocate frame and save the non-volatile") \
343TCR("# registers we're going to modify") \
344TCR("mov	ip, sp") \
345TCR("stmfd	sp!, {r"S(CFA_REG)", fp, ip, lr, pc}") \
346TCR("# Setup CFA_REG = context, which we'll retrieve as our CFA value") \
347TCR("ldr	r"S(CFA_REG)", [ip]") \
348TCR("")                 \
349TCR("# Call the real handler. The signo, siginfo and sigcontext") \
350TCR("# arguments are the same as those we received in r0, r1 and r2") \
351TCR("sub	fp, ip, #4") \
352TCR("blx	r3") \
353TCR("# Restore our callee-saved items, release our frame and return") \
354TCR("ldmfd	sp, {r"S(CFA_REG)", fp, sp, pc}")
355
356#else
357Not_implemented;
358#endif /* CFI_COMMON_REGS and SIGTRAMP_BODY */
359
360/* Symbol definition block
361   -----------------------  */
362
363#define SIGTRAMP_START(SYM) \
364CR("# " S(SYM) " cfi trampoline") \
365TCR(".type " S(SYM) ", "FUNCTION) \
366CR("") \
367CR(S(SYM) ":") \
368TCR(".cfi_startproc") \
369TCR(".cfi_signal_frame")
370
371/* Symbol termination block
372   ------------------------  */
373
374#define SIGTRAMP_END(SYM) \
375CR(".cfi_endproc") \
376TCR(".size " S(SYM) ", .-" S(SYM))
377
378/*----------------------------
379  -- And now, the real code --
380  ---------------------------- */
381
382/* Text section start.  The compiler isn't aware of that switch.  */
383
384asm (".text\n"
385     TCR(".align 2"));
386
387/* sigtramp stub for common registers.  */
388
389#define TRAMP_COMMON __gnat_sigtramp_common
390
391asm (SIGTRAMP_START(TRAMP_COMMON));
392asm (CFI_DEF_CFA);
393asm (CFI_COMMON_REGS);
394asm (SIGTRAMP_BODY);
395asm (SIGTRAMP_END(TRAMP_COMMON));
396
397
398