]>
Commit | Line | Data |
---|---|---|
7b27e183 AC |
1 | /**************************************************************************** |
2 | * * | |
3 | * GNAT COMPILER COMPONENTS * | |
4 | * * | |
5 | * S I G T R A M P * | |
6 | * * | |
7 | * Asm Implementation File * | |
8 | * * | |
8d0d46f4 | 9 | * Copyright (C) 2011-2021, Free Software Foundation, Inc. * |
7b27e183 AC |
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 | ||
155562cb AC |
32 | /************************************************** |
33 | * VxWorks version of the __gnat_sigtramp service * | |
34 | **************************************************/ | |
7b27e183 AC |
35 | |
36 | #include "sigtramp.h" | |
80c2c202 | 37 | /* See sigtramp.h for a general explanation of functionality. */ |
7b27e183 AC |
38 | |
39 | #include <vxWorks.h> | |
40 | #include <arch/../regs.h> | |
3808a9c7 | 41 | #ifndef __RTP__ |
b2c3160c AC |
42 | #if defined(__i386__) |
43 | #include <version.h> | |
44 | #endif | |
7b27e183 | 45 | #include <sigLib.h> |
3808a9c7 AC |
46 | #else |
47 | #include <signal.h> | |
155562cb AC |
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; | |
3808a9c7 | 62 | #endif |
7b27e183 AC |
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 | |
3808a9c7 AC |
71 | (for DKM) and mcontext (for RTP) and state where to find the registers as |
72 | offsets from there. | |
7b27e183 | 73 | |
6782b1ef | 74 | As of today, we support a stub providing CFI info for common |
7b27e183 AC |
75 | registers (GPRs, LR, ...). We might need variants with support for floating |
76 | point or altivec registers as well at some point. | |
77 | ||
3808a9c7 AC |
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. | |
7b27e183 AC |
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 | ||
3808a9c7 AC |
87 | /* ------------------------------------------- |
88 | -- Prototypes for our internal asm stubs -- | |
89 | ------------------------------------------- | |
7b27e183 | 90 | |
3808a9c7 AC |
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. */ | |
7b27e183 | 94 | |
0d66b596 | 95 | #define TRAMP_COMMON __gnat_sigtramp_common |
7b27e183 | 96 | |
0d66b596 | 97 | /* sigtramp stub providing CFI info for common registers. */ |
7b27e183 | 98 | |
0d66b596 AC |
99 | extern void |
100 | TRAMP_COMMON (int signo, void *siginfo, void *sigcontext, | |
101 | __sigtramphandler_t * handler, REG_SET * sc_pregs); | |
7b27e183 AC |
102 | |
103 | /* ------------------------------------- | |
104 | -- Common interface implementation -- | |
105 | ------------------------------------- | |
106 | ||
107 | We enforce optimization to minimize the overhead of the extra layer. */ | |
108 | ||
0d66b596 AC |
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 | ||
7b27e183 | 117 | void __gnat_sigtramp (int signo, void *si, void *sc, |
6782b1ef | 118 | __sigtramphandler_t * handler) |
7b27e183 AC |
119 | __attribute__((optimize(2))); |
120 | ||
121 | void __gnat_sigtramp (int signo, void *si, void *sc, | |
6782b1ef | 122 | __sigtramphandler_t * handler) |
7b27e183 | 123 | { |
0d66b596 AC |
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 | |
b2c3160c | 133 | at the end of the reg set, but the padding is then of 0xc4 characters. |
0d66b596 AC |
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. | |
b2c3160c AC |
138 | |
139 | * See header file regsSimlinux.h. | |
0d66b596 AC |
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 = | |
b2c3160c AC |
149 | (struct sigcontext *) (sc + (__gnat_is_vxsim ? |
150 | (_WRS_VXWORKS_MAJOR == 7 ? 204 : 208) | |
151 | : 0)); | |
0d66b596 AC |
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 | ||
3808a9c7 | 166 | mcontext_t *mcontext = &((ucontext_t *) sc)->uc_mcontext; |
0d66b596 AC |
167 | /* No specific offset in this case for vxsim */ |
168 | pregs = &(mcontext->regs); | |
3808a9c7 | 169 | |
0d66b596 | 170 | #endif /* !defined(__RTP__) */ |
7b27e183 | 171 | |
0d66b596 AC |
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)); | |
3808a9c7 | 176 | #endif |
0d66b596 AC |
177 | |
178 | /* And now call the real signal trampoline with the list of registers */ | |
179 | __gnat_sigtramp_common (signo, si, sc, handler, pregs); | |
7b27e183 AC |
180 | } |
181 | ||
e8c84c8f | 182 | /* Include the target specific bits. */ |
6e8b502c | 183 | #include "sigtramp-vxworks-target.h" |
7b27e183 AC |
184 | |
185 | /* sigtramp stub for common registers. */ | |
186 | ||
7b27e183 AC |
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)); |