111
|
1 /****************************************************************************
|
|
2 * *
|
|
3 * GNAT COMPILER COMPONENTS *
|
|
4 * *
|
|
5 * S I G T R A M P *
|
|
6 * *
|
|
7 * Asm Implementation File *
|
|
8 * *
|
145
|
9 * Copyright (C) 2011-2019, 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 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 #if defined(__i386__)
|
|
43 #include <version.h>
|
|
44 #endif
|
|
45 #include <sigLib.h>
|
|
46 #else
|
|
47 #include <signal.h>
|
|
48 #include <regs.h>
|
|
49
|
|
50 typedef struct mcontext
|
|
51 {
|
|
52 REG_SET regs;
|
|
53 } mcontext_t;
|
|
54
|
|
55 typedef struct ucontext
|
|
56 {
|
|
57 mcontext_t uc_mcontext; /* register set */
|
|
58 struct ucontext * uc_link; /* not used */
|
|
59 sigset_t uc_sigmask; /* set of signals blocked */
|
|
60 stack_t uc_stack; /* stack of context signaled */
|
|
61 } ucontext_t;
|
|
62 #endif
|
|
63
|
|
64 /* ----------------------
|
|
65 -- General comments --
|
|
66 ----------------------
|
|
67
|
|
68 Stubs are generated from toplevel asms and .cfi directives, much simpler
|
|
69 to use and check for correctness than manual encodings of CFI byte
|
|
70 sequences. The general idea is to establish CFA as sigcontext->sc_pregs
|
|
71 (for DKM) and mcontext (for RTP) and state where to find the registers as
|
|
72 offsets from there.
|
|
73
|
|
74 As of today, we support a stub providing CFI info for common
|
|
75 registers (GPRs, LR, ...). We might need variants with support for floating
|
|
76 point or altivec registers as well at some point.
|
|
77
|
|
78 Checking which variant should apply and getting at sc_pregs / mcontext
|
|
79 is simpler to express in C (we can't use offsetof in toplevel asms and
|
|
80 hardcoding constants is not workable with the flurry of VxWorks variants),
|
|
81 so this is the choice for our toplevel interface.
|
|
82
|
|
83 Note that the registers we "restore" here are those to which we have
|
|
84 direct access through the system sigcontext structure, which includes
|
|
85 only a partial set of the non-volatiles ABI-wise. */
|
|
86
|
|
87 /* -------------------------------------------
|
|
88 -- Prototypes for our internal asm stubs --
|
|
89 -------------------------------------------
|
|
90
|
|
91 Eventhough our symbols will remain local, the prototype claims "extern"
|
|
92 and not "static" to prevent compiler complaints about a symbol used but
|
|
93 never defined. */
|
|
94
|
|
95 #define TRAMP_COMMON __gnat_sigtramp_common
|
|
96
|
|
97 /* sigtramp stub providing CFI info for common registers. */
|
|
98
|
|
99 extern void
|
|
100 TRAMP_COMMON (int signo, void *siginfo, void *sigcontext,
|
|
101 __sigtramphandler_t * handler, REG_SET * sc_pregs);
|
|
102
|
|
103 /* -------------------------------------
|
|
104 -- Common interface implementation --
|
|
105 -------------------------------------
|
|
106
|
|
107 We enforce optimization to minimize the overhead of the extra layer. */
|
|
108
|
|
109 #if defined(__vxworks) && (defined (__i386__) || defined (__x86_64__)) && !defined (VTHREADS)
|
|
110 static int __gnat_is_vxsim = 0;
|
|
111
|
|
112 void __gnat_set_is_vxsim(int val) {
|
|
113 __gnat_is_vxsim = val;
|
|
114 }
|
|
115 #endif
|
|
116
|
|
117 void __gnat_sigtramp (int signo, void *si, void *sc,
|
|
118 __sigtramphandler_t * handler)
|
|
119 __attribute__((optimize(2)));
|
|
120
|
|
121 void __gnat_sigtramp (int signo, void *si, void *sc,
|
|
122 __sigtramphandler_t * handler)
|
|
123 {
|
|
124 REG_SET *pregs;
|
|
125
|
|
126 /* VXSIM uses a different signal context structure than the regular x86
|
|
127 targets:
|
|
128 * on x86-vx6: two 32-bit values are added at the end of the REG_SET, plus
|
|
129 an explicit padding of 0xc8 characters (200 characters). The sigcontext
|
|
130 containing a complete REG_SET just before the field 'sc_pregs', this
|
|
131 adds a 208 bytes offset to get the value of 'sc_pregs'.
|
|
132 * on x86-vx7: the same offset is used on vx7: 3 32-bit values are present
|
|
133 at the end of the reg set, but the padding is then of 0xc4 characters.
|
|
134 * on x86_64-vx7: two 64-bit values are added at the beginning of the
|
|
135 REG_SET. This adds a 16 bytes offset to get the value of 'sc_pregs',
|
|
136 and another 16 bytes offset within the pregs structure to retrieve the
|
|
137 registers list.
|
|
138
|
|
139 * See header file regsSimlinux.h.
|
|
140 */
|
|
141
|
|
142 /* Retrieve the registers to restore : */
|
|
143 #ifndef __RTP__
|
|
144 #ifdef __HANDLE_VXSIM_SC
|
|
145 #if defined(__i386__)
|
|
146 /* move sctx 208 bytes further, so that the vxsim's sc_pregs field coincide
|
|
147 with the expected x86 one */
|
|
148 struct sigcontext * sctx =
|
|
149 (struct sigcontext *) (sc + (__gnat_is_vxsim ?
|
|
150 (_WRS_VXWORKS_MAJOR == 7 ? 204 : 208)
|
|
151 : 0));
|
|
152 #elif defined(__x86_64__)
|
|
153 /* move sctx 16 bytes further, so that the vxsim's sc_pregs field coincide
|
|
154 with the expected x86_64 one */
|
|
155 struct sigcontext * sctx =
|
|
156 (struct sigcontext *) (sc + (__gnat_is_vxsim ? 16 : 0));
|
|
157 #endif /* __i386__ || __x86_64__ */
|
|
158 #else /* __HANDLE_VXSIM_SC__ */
|
|
159 struct sigcontext * sctx = (struct sigcontext *) sc;
|
|
160 #endif
|
|
161
|
|
162 pregs = sctx->sc_pregs;
|
|
163
|
|
164 #else /* !defined(__RTP__) */
|
|
165
|
|
166 mcontext_t *mcontext = &((ucontext_t *) sc)->uc_mcontext;
|
|
167 /* No specific offset in this case for vxsim */
|
|
168 pregs = &(mcontext->regs);
|
|
169
|
|
170 #endif /* !defined(__RTP__) */
|
|
171
|
|
172 #if defined (__HANDLE_VXSIM_SC) && defined (__x86_64__)
|
|
173 /* Ignore the first two values, that are not registers in case of
|
|
174 vxsim */
|
|
175 pregs = (REG_SET *) ((void *)pregs + (__gnat_is_vxsim ? 16 : 0));
|
|
176 #endif
|
|
177
|
|
178 /* And now call the real signal trampoline with the list of registers */
|
|
179 __gnat_sigtramp_common (signo, si, sc, handler, pregs);
|
|
180 }
|
|
181
|
|
182 /* Include the target specific bits. */
|
|
183 #include "sigtramp-vxworks-target.inc"
|
|
184
|
|
185 /* sigtramp stub for common registers. */
|
|
186
|
|
187 asm (SIGTRAMP_START(TRAMP_COMMON));
|
|
188 asm (CFI_DEF_CFA);
|
|
189 asm (CFI_COMMON_REGS);
|
|
190 asm (SIGTRAMP_BODY);
|
|
191 asm (SIGTRAMP_END(TRAMP_COMMON));
|