OSDN Git Service

* include/dwarf2-signal.h (INIT_SEGV, INIT_FPE for ia64):
[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     nullp = new java::lang::NullPointerException ();            \
147     struct kernel_sigaction act;                                \
148     unsigned long stub = ((unsigned long)&__rt_sigreturn_stub); \
149     act.k_sa_sigaction = _Jv_catch_segv;                        \
150     sigemptyset (&act.k_sa_mask);                               \
151     act.k_sa_flags = SA_SIGINFO;                                \
152     act.k_sa_restorer = NULL;                                   \
153     syscall (SYS_rt_sigaction, SIGSEGV, &act, NULL,             \
154              stub - 8, _NSIG / 8);                              \
155   }                                                             \
156 while (0)  
157
158 #define INIT_FPE                                                \
159 do                                                              \
160   {                                                             \
161     arithexception = new java::lang::ArithmeticException        \
162       (JvNewStringLatin1 ("/ by zero"));                        \
163     struct kernel_sigaction act;                                \
164     unsigned long stub = ((unsigned long)&__rt_sigreturn_stub); \
165     act.k_sa_sigaction = _Jv_catch_fpe;                         \
166     sigemptyset (&act.k_sa_mask);                               \
167     act.k_sa_flags = SA_SIGINFO;                                \
168     act.k_sa_restorer = NULL;                                   \
169     syscall (SYS_rt_sigaction, SIGFPE, &act, NULL,              \
170              stub - 8, _NSIG / 8);                              \
171   }                                                             \
172 while (0)  
173 #else /* __arch64__ */
174
175 extern "C" {
176     struct kernel_sigaction
177     {
178       void (*k_sa_sigaction)(int,siginfo_t *,void *);
179       unsigned long k_sa_mask, k_sa_flags;
180       void (*k_sa_restorer)(void);
181     };
182 }
183
184 #define INIT_SEGV                                               \
185 do                                                              \
186   {                                                             \
187     struct kernel_sigaction act;                                \
188     nullp = new java::lang::NullPointerException ();            \
189     act.k_sa_sigaction = _Jv_catch_segv;                        \
190     act.k_sa_mask = 0;                                          \
191     act.k_sa_flags = SA_SIGINFO;                                \
192     act.k_sa_restorer = NULL;                                   \
193     syscall (SYS_sigaction, -SIGSEGV, &act, NULL);              \
194   }                                                             \
195 while (0)  
196
197 #define INIT_FPE                                                \
198 do                                                              \
199   {                                                             \
200     arithexception = new java::lang::ArithmeticException        \
201       (JvNewStringLatin1 ("/ by zero"));                        \
202     struct kernel_sigaction act;                                \
203     act.k_sa_sigaction = _Jv_catch_fpe;                         \
204     act.k_sa_mask = 0;                                          \
205     act.k_sa_flags = SA_SIGINFO;                                \
206     act.k_sa_restorer = NULL;                                   \
207     syscall (SYS_sigaction, -SIGFPE, &act, NULL);               \
208   }                                                             \
209 while (0)  
210 #endif
211 #elif !defined(__ia64__)
212 #define INIT_SEGV                                               \
213 do                                                              \
214   {                                                             \
215     nullp = new java::lang::NullPointerException ();            \
216     struct sigaction act;                                       \
217     act.sa_sigaction = _Jv_catch_segv;                          \
218     sigemptyset (&act.sa_mask);                                 \
219     act.sa_flags = SA_SIGINFO;                                  \
220     syscall (SYS_sigaction, SIGSEGV, &act, NULL);               \
221   }                                                             \
222 while (0)  
223
224 #define INIT_FPE                                                \
225 do                                                              \
226   {                                                             \
227     arithexception = new java::lang::ArithmeticException        \
228       (JvNewStringLatin1 ("/ by zero"));                        \
229     struct sigaction act;                                       \
230     act.sa_sigaction = _Jv_catch_fpe;                           \
231     sigemptyset (&act.sa_mask);                                 \
232     act.sa_flags = SA_SIGINFO;                                  \
233     syscall (SYS_sigaction, SIGFPE, &act, NULL);                \
234   }                                                             \
235 while (0)  
236
237 /* We use syscall(SYS_sigaction) in INIT_SEGV and INIT_FPE instead of
238  * sigaction() because on some systems the pthreads wrappers for
239  * signal handlers are not compiled with unwind information, so it's
240  * not possible to unwind through them.  This is a problem that will
241  * go away once all systems have pthreads libraries that are
242  * compiled with full unwind info.  */
243
244 #else  /* __ia64__ */
245
246 // On IA64, unwind information is mandatory, so we can unwind
247 // correctly through glibc frames.  Thus we call the ordinary
248 // sigaction.
249
250 #define INIT_SEGV                                               \
251 do                                                              \
252   {                                                             \
253     nullp = new java::lang::NullPointerException ();            \
254     struct sigaction act;                                       \
255     act.sa_sigaction = _Jv_catch_segv;                          \
256     sigemptyset (&act.sa_mask);                                 \
257     act.sa_flags = SA_SIGINFO;                                  \
258     sigaction (SIGSEGV, &act, NULL);                            \
259   }                                                             \
260 while (0)  
261
262 #define INIT_FPE                                                \
263 do                                                              \
264   {                                                             \
265     arithexception = new java::lang::ArithmeticException        \
266       (JvNewStringLatin1 ("/ by zero"));                        \
267     struct sigaction act;                                       \
268     act.sa_sigaction = _Jv_catch_fpe;                           \
269     sigemptyset (&act.sa_mask);                                 \
270     act.sa_flags = SA_SIGINFO;                                  \
271     sigaction (SIGFPE, &act, NULL);                             \
272   }                                                             \
273 while (0)  
274 #endif /* __ia64__ || __sparc__ */
275 #endif /* JAVA_SIGNAL_H */