OSDN Git Service

Regenerate tree using Autoconf 2.64 and Automake 1.11.
[pf3gnuchains/gcc-fork.git] / libjava / include / dwarf2-signal.h
1 // dwarf2-signal.h - Catch runtime signals and turn them into exceptions.
2
3 /* Copyright (C) 2000, 2001  Free Software Foundation
4
5    This file is part of libgcj.
6
7    Use this file for a target for which the dwarf2 unwinder in libgcc
8    can unwind through signal handlers.
9
10 This software is copyrighted work licensed under the terms of the
11 Libgcj License.  Please consult the file "LIBGCJ_LICENSE" for
12 details.  */
13
14 #ifndef JAVA_SIGNAL_H
15 #define JAVA_SIGNAL_H 1
16
17 #include <signal.h>
18 #include <sys/syscall.h>
19
20 #define HANDLE_SEGV 1
21 #undef HANDLE_FPE
22
23 #define SIGNAL_HANDLER(_name)   \
24 static void _Jv_##_name (int, siginfo_t *_sip, void *_p)
25
26 class java::lang::Throwable;
27
28 // Unwind the stack to the point at which the signal was generated and
29 // then throw an exception.  With the dwarf2 unwinder we don't usually
30 // need to do anything, with some minor exceptions.
31
32 #ifdef __alpha__
33 #define MAKE_THROW_FRAME(_exception)                                    \
34 do                                                                      \
35 {                                                                       \
36   /* Alpha either leaves PC pointing at a faulting instruction or the   \
37    following instruction, depending on the signal.  SEGV always does    \
38    the former, so we adjust the saved PC to point to the following      \
39    instruction; this is what the handler in libgcc expects.  */         \
40   struct sigcontext *_sc = (struct sigcontext *)_p;                     \
41   _sc->sc_pc += 4;                                                      \
42 }                                                                       \
43 while (0)
44
45 #elif defined(__ia64__)
46
47 #define MAKE_THROW_FRAME(_exception)                                    \
48 do                                                                      \
49 {                                                                       \
50   /* IA-64 either leaves PC pointing at a faulting instruction or the   \
51    following instruction, depending on the signal.  SEGV always does    \
52    the former, so we adjust the saved PC to point to the following      \
53    instruction; this is what the handler in libgcc expects.  */         \
54   /* Note that we are lying to the unwinder here, which expects the     \
55    faulting pc, not pc+1.  But we claim the unwind information can't    \
56    be changed by such a ld or st instruction, so it doesn't matter. */  \
57   struct sigcontext *_sc = (struct sigcontext *)_p;                     \
58   _sc->sc_ip++;                                                         \
59 }                                                                       \
60 while (0)
61 #elif defined(__sparc__)
62 /* We could do the unwind of the signal frame quickly by hand here like
63    sparc-signal.h does under Solaris, but that makes debugging unwind
64    failures almost impossible.  */
65 #if !defined(__arch64__)
66 #define MAKE_THROW_FRAME(_exception)                                    \
67 do                                                                      \
68 {                                                                       \
69   /* Sparc-32 leaves PC pointing at a faulting instruction              \
70    always.                                                              \
71    We advance the PC one instruction past the exception causing PC.     \
72    This is done because FDEs are found with "context->ra - 1" in the    \
73    unwinder.                                                            \
74    Also, the dwarf2 unwind machinery is going to add 8 to the           \
75    PC it uses on Sparc.  So we adjust the PC here.  We do it here       \
76    because we run once for such an exception, however the Sparc specific\
77    unwind can run multiple times for the same exception and it would    \
78    adjust the PC more than once resulting in a bogus value.  */         \
79   struct sig_regs {                                                     \
80     unsigned int psr, pc, npc, y, u_regs[16];                           \
81   } *regp;                                                              \
82   unsigned int insn;                                                    \
83   __asm__ __volatile__("ld [%%i7 + 8], %0" : "=r" (insn));              \
84   /* mov __NR_sigaction, %g1; Old signal stack layout */                \
85   if (insn == 0x821020d8)                                               \
86     regp = (struct sig_regs *) _sip;                                    \
87   else                                                                  \
88     /* mov __NR_rt_sigaction, %g1; New signal stack layout */           \
89     regp = (struct sig_regs *) (_sip + 1);                              \
90   regp->pc = ((regp->pc + 4) - 8);                                      \
91 }                                                                       \
92 while (0)
93 #else
94 #define MAKE_THROW_FRAME(_exception)                                    \
95 do                                                                      \
96 {                                                                       \
97   /* Sparc-64 leaves PC pointing at a faulting instruction              \
98    always.                                                              \
99    We advance the PC one instruction past the exception causing PC.     \
100    This is done because FDEs are found with "context->ra - 1" in the    \
101    unwinder.                                                            \
102    Also, the dwarf2 unwind machinery is going to add 8 to the           \
103    PC it uses on Sparc.  So we adjust the PC here.  We do it here       \
104    because we run once for such an exception, however the Sparc specific\
105    unwind can run multiple times for the same exception and it would    \
106    adjust the PC more than once resulting in a bogus value.  */         \
107   struct pt_regs {                                                      \
108     unsigned long u_regs[16];                                           \
109     unsigned long tstate, tpc, tnpc;                                    \
110     unsigned int y, fprs;                                               \
111   } *regp = (struct pt_regs *) (_sip + 1);                              \
112   regp->tpc = ((regp->tpc + 4) - 8);                                    \
113 }                                                                       \
114 while (0)
115 #endif
116 #else
117 #define MAKE_THROW_FRAME(_exception)            \
118 do                                              \
119 {                                               \
120   (void)_p;                                     \
121 }                                               \
122 while (0)
123 #endif
124
125 #if defined(__sparc__)
126 #if defined(__arch64__)
127 extern "C" {
128     static void __rt_sigreturn_stub(void)
129     {
130       __asm__("mov %0, %%g1\n\t"
131               "ta  0x6d\n\t"
132               : /* no outputs */
133               : "i" (__NR_rt_sigreturn));
134     }
135     struct kernel_sigaction
136     {
137       void (*k_sa_sigaction)(int,siginfo_t *,void *);
138       unsigned long k_sa_flags;
139       void (*k_sa_restorer)(void);
140       sigset_t k_sa_mask;
141     };
142 }
143 #define INIT_SEGV                                               \
144 do                                                              \
145   {                                                             \
146     struct kernel_sigaction act;                                \
147     unsigned long stub = ((unsigned long)&__rt_sigreturn_stub); \
148     act.k_sa_sigaction = _Jv_catch_segv;                        \
149     sigemptyset (&act.k_sa_mask);                               \
150     act.k_sa_flags = SA_SIGINFO;                                \
151     act.k_sa_restorer = NULL;                                   \
152     syscall (SYS_rt_sigaction, SIGSEGV, &act, NULL,             \
153              stub - 8, _NSIG / 8);                              \
154   }                                                             \
155 while (0)  
156
157 #define INIT_FPE                                                \
158 do                                                              \
159   {                                                             \
160     struct kernel_sigaction act;                                \
161     unsigned long stub = ((unsigned long)&__rt_sigreturn_stub); \
162     act.k_sa_sigaction = _Jv_catch_fpe;                         \
163     sigemptyset (&act.k_sa_mask);                               \
164     act.k_sa_flags = SA_SIGINFO;                                \
165     act.k_sa_restorer = NULL;                                   \
166     syscall (SYS_rt_sigaction, SIGFPE, &act, NULL,              \
167              stub - 8, _NSIG / 8);                              \
168   }                                                             \
169 while (0)  
170 #else /* __arch64__ */
171
172 extern "C" {
173     struct kernel_sigaction
174     {
175       void (*k_sa_sigaction)(int,siginfo_t *,void *);
176       unsigned long k_sa_mask, k_sa_flags;
177       void (*k_sa_restorer)(void);
178     };
179 }
180
181 #define INIT_SEGV                                               \
182 do                                                              \
183   {                                                             \
184     struct kernel_sigaction act;                                \
185     act.k_sa_sigaction = _Jv_catch_segv;                        \
186     act.k_sa_mask = 0;                                          \
187     act.k_sa_flags = SA_SIGINFO;                                \
188     act.k_sa_restorer = NULL;                                   \
189     syscall (SYS_sigaction, -SIGSEGV, &act, NULL);              \
190   }                                                             \
191 while (0)  
192
193 #define INIT_FPE                                                \
194 do                                                              \
195   {                                                             \
196     struct kernel_sigaction act;                                \
197     act.k_sa_sigaction = _Jv_catch_fpe;                         \
198     act.k_sa_mask = 0;                                          \
199     act.k_sa_flags = SA_SIGINFO;                                \
200     act.k_sa_restorer = NULL;                                   \
201     syscall (SYS_sigaction, -SIGFPE, &act, NULL);               \
202   }                                                             \
203 while (0)  
204 #endif
205 #elif !defined(__ia64__)
206 #define INIT_SEGV                                               \
207 do                                                              \
208   {                                                             \
209     struct sigaction act;                                       \
210     act.sa_sigaction = _Jv_catch_segv;                          \
211     sigemptyset (&act.sa_mask);                                 \
212     act.sa_flags = SA_SIGINFO;                                  \
213     syscall (SYS_sigaction, SIGSEGV, &act, NULL);               \
214   }                                                             \
215 while (0)  
216
217 #define INIT_FPE                                                \
218 do                                                              \
219   {                                                             \
220     struct sigaction act;                                       \
221     act.sa_sigaction = _Jv_catch_fpe;                           \
222     sigemptyset (&act.sa_mask);                                 \
223     act.sa_flags = SA_SIGINFO;                                  \
224     syscall (SYS_sigaction, SIGFPE, &act, NULL);                \
225   }                                                             \
226 while (0)  
227
228 /* We use syscall(SYS_sigaction) in INIT_SEGV and INIT_FPE instead of
229  * sigaction() because on some systems the pthreads wrappers for
230  * signal handlers are not compiled with unwind information, so it's
231  * not possible to unwind through them.  This is a problem that will
232  * go away once all systems have pthreads libraries that are
233  * compiled with full unwind info.  */
234
235 #else  /* __ia64__ */
236
237 // On IA64, unwind information is mandatory, so we can unwind
238 // correctly through glibc frames.  Thus we call the ordinary
239 // sigaction.
240
241 #define INIT_SEGV                                               \
242 do                                                              \
243   {                                                             \
244     struct sigaction act;                                       \
245     act.sa_sigaction = _Jv_catch_segv;                          \
246     sigemptyset (&act.sa_mask);                                 \
247     act.sa_flags = SA_SIGINFO;                                  \
248     sigaction (SIGSEGV, &act, NULL);                            \
249   }                                                             \
250 while (0)  
251
252 #define INIT_FPE                                                \
253 do                                                              \
254   {                                                             \
255     struct sigaction act;                                       \
256     act.sa_sigaction = _Jv_catch_fpe;                           \
257     sigemptyset (&act.sa_mask);                                 \
258     act.sa_flags = SA_SIGINFO;                                  \
259     sigaction (SIGFPE, &act, NULL);                             \
260   }                                                             \
261 while (0)  
262 #endif /* __ia64__ || __sparc__ */
263 #endif /* JAVA_SIGNAL_H */