1 // dwarf2-signal.h - Catch runtime signals and turn them into exceptions.
2 
3 /* Copyright (C) 2000, 2001, 2009, 2011, 2014  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 *,			\
25 			 void *_p __attribute__ ((__unused__)))
26 
27 // Unwind the stack to the point at which the signal was generated and
28 // then throw an exception.  With the dwarf2 unwinder we don't usually
29 // need to do anything, with some minor exceptions.
30 
31 #ifdef __ia64__
32 
33 #define MAKE_THROW_FRAME(_exception)					\
34 do									\
35 {									\
36   /* IA-64 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   /* Note that we are lying to the unwinder here, which expects the	\
41    faulting pc, not pc+1.  But we claim the unwind information can't	\
42    be changed by such a ld or st instruction, so it doesn't matter. */	\
43   struct sigcontext *_sc = (struct sigcontext *)_p;			\
44   _sc->sc_ip++;								\
45 }									\
46 while (0)
47 
48 #else
49 #define MAKE_THROW_FRAME(_exception)
50 #endif
51 
52 #if defined(__sparc__)
53 #if defined(__arch64__)
54 extern "C" {
__rt_sigreturn_stub(void)55     static void __rt_sigreturn_stub(void)
56     {
57       __asm__("mov %0, %%g1\n\t"
58 	      "ta  0x6d\n\t"
59 	      : /* no outputs */
60 	      : "i" (__NR_rt_sigreturn));
61     }
62     struct kernel_sigaction
63     {
64       void (*k_sa_sigaction)(int,siginfo_t *,void *);
65       unsigned long k_sa_flags;
66       void (*k_sa_restorer)(void);
67       sigset_t k_sa_mask;
68     };
69 }
70 #define INIT_SEGV						\
71 do								\
72   {								\
73     struct kernel_sigaction act;				\
74     unsigned long stub = ((unsigned long)&__rt_sigreturn_stub); \
75     act.k_sa_sigaction = _Jv_catch_segv;      			\
76     sigemptyset (&act.k_sa_mask);				\
77     act.k_sa_flags = SA_SIGINFO;	       			\
78     act.k_sa_restorer = NULL;					\
79     syscall (SYS_rt_sigaction, SIGSEGV, &act, NULL,		\
80              stub - 8, _NSIG / 8);				\
81   }								\
82 while (0)
83 
84 #define INIT_FPE						\
85 do								\
86   { 								\
87     struct kernel_sigaction act;				\
88     unsigned long stub = ((unsigned long)&__rt_sigreturn_stub); \
89     act.k_sa_sigaction = _Jv_catch_fpe;				\
90     sigemptyset (&act.k_sa_mask);				\
91     act.k_sa_flags = SA_SIGINFO;		       		\
92     act.k_sa_restorer = NULL;					\
93     syscall (SYS_rt_sigaction, SIGFPE, &act, NULL,		\
94              stub - 8, _NSIG / 8);				\
95   }								\
96 while (0)
97 #else /* __arch64__ */
98 
99 extern "C" {
100     struct kernel_sigaction
101     {
102       void (*k_sa_sigaction)(int,siginfo_t *,void *);
103       unsigned long k_sa_mask, k_sa_flags;
104       void (*k_sa_restorer)(void);
105     };
106 }
107 
108 #define INIT_SEGV						\
109 do								\
110   {								\
111     struct kernel_sigaction act;				\
112     act.k_sa_sigaction = _Jv_catch_segv;      			\
113     act.k_sa_mask = 0;						\
114     act.k_sa_flags = SA_SIGINFO;	       			\
115     act.k_sa_restorer = NULL;					\
116     syscall (SYS_sigaction, -SIGSEGV, &act, NULL);		\
117   }								\
118 while (0)
119 
120 #define INIT_FPE						\
121 do								\
122   { 								\
123     struct kernel_sigaction act;				\
124     act.k_sa_sigaction = _Jv_catch_fpe;				\
125     act.k_sa_mask = 0;						\
126     act.k_sa_flags = SA_SIGINFO;		       		\
127     act.k_sa_restorer = NULL;					\
128     syscall (SYS_sigaction, -SIGFPE, &act, NULL);		\
129   }								\
130 while (0)
131 #endif
132 #elif !defined(__ia64__)
133 #define INIT_SEGV						\
134 do								\
135   {								\
136     struct sigaction act;					\
137     act.sa_sigaction = _Jv_catch_segv;      			\
138     sigemptyset (&act.sa_mask);					\
139     act.sa_flags = SA_SIGINFO;	       				\
140     syscall (SYS_sigaction, SIGSEGV, &act, NULL);		\
141   }								\
142 while (0)
143 
144 #define INIT_FPE						\
145 do								\
146   { 								\
147     struct sigaction act;					\
148     act.sa_sigaction = _Jv_catch_fpe;				\
149     sigemptyset (&act.sa_mask);					\
150     act.sa_flags = SA_SIGINFO;		       			\
151     syscall (SYS_sigaction, SIGFPE, &act, NULL);		\
152   }								\
153 while (0)
154 
155 /* We use syscall(SYS_sigaction) in INIT_SEGV and INIT_FPE instead of
156  * sigaction() because on some systems the pthreads wrappers for
157  * signal handlers are not compiled with unwind information, so it's
158  * not possible to unwind through them.  This is a problem that will
159  * go away once all systems have pthreads libraries that are
160  * compiled with full unwind info.  */
161 
162 #else  /* __ia64__ */
163 
164 // On IA64, unwind information is mandatory, so we can unwind
165 // correctly through glibc frames.  Thus we call the ordinary
166 // sigaction.
167 
168 #define INIT_SEGV						\
169 do								\
170   {								\
171     struct sigaction act;					\
172     act.sa_sigaction = _Jv_catch_segv;      			\
173     sigemptyset (&act.sa_mask);					\
174     act.sa_flags = SA_SIGINFO;	       				\
175     sigaction (SIGSEGV, &act, NULL);				\
176   }								\
177 while (0)
178 
179 #define INIT_FPE						\
180 do								\
181   { 								\
182     struct sigaction act;					\
183     act.sa_sigaction = _Jv_catch_fpe;				\
184     sigemptyset (&act.sa_mask);					\
185     act.sa_flags = SA_SIGINFO;		       			\
186     sigaction (SIGFPE, &act, NULL);				\
187   }								\
188 while (0)
189 #endif /* __ia64__ || __sparc__ */
190 #endif /* JAVA_SIGNAL_H */
191