]>
Commit | Line | Data |
---|---|---|
01936f3a AH |
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 | ||
c9bffcd5 AH |
7 | Use this file for a target for which the dwarf2 unwinder in libgcc |
8 | can unwind through signal handlers. | |
01936f3a AH |
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) \ | |
714708c8 | 24 | static void _Jv_##_name (int, siginfo_t *_sip, void *_p) |
01936f3a AH |
25 | |
26 | class java::lang::Throwable; | |
27 | ||
28 | // Unwind the stack to the point at which the signal was generated and | |
c9bffcd5 AH |
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) | |
3cb20545 AH |
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) | |
714708c8 DM |
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. So we adjust the saved PC to point to the following \ | |
71 | instruction; this is what the handler in libgcc expects. */ \ | |
72 | /* Note that we are lying to the unwinder here, which expects the \ | |
73 | faulting pc, not pc+1. But we claim the unwind information can't \ | |
74 | be changed by such a ld or st instruction, so it doesn't matter. */ \ | |
75 | struct sig_regs { \ | |
76 | unsigned int psr, pc, npc, y, u_regs[16]; \ | |
77 | } *regp; \ | |
78 | unsigned int insn; \ | |
79 | __asm__ __volatile__("ld [%%i7 + 8], %0" : "=r" (insn)); \ | |
4bf01445 | 80 | /* mov __NR_sigaction, %g1; Old signal stack layout */ \ |
714708c8 DM |
81 | if (insn == 0x821020d8) \ |
82 | regp = (struct sig_regs *) _sip; \ | |
83 | else \ | |
4bf01445 | 84 | /* mov __NR_rt_sigaction, %g1; New signal stack layout */ \ |
714708c8 DM |
85 | regp = (struct sig_regs *) (_sip + 1); \ |
86 | regp->pc = regp->npc; \ | |
87 | regp->npc += 4; \ | |
88 | } \ | |
89 | while (0) | |
90 | #else | |
91 | #define MAKE_THROW_FRAME(_exception) \ | |
92 | do \ | |
93 | { \ | |
94 | /* Sparc-64 leaves PC pointing at a faulting instruction \ | |
95 | always. So we adjust the saved PC to point to the following \ | |
96 | instruction; this is what the handler in libgcc expects. */ \ | |
97 | /* Note that we are lying to the unwinder here, which expects the \ | |
98 | faulting pc, not pc+1. But we claim the unwind information can't \ | |
99 | be changed by such a ld or st instruction, so it doesn't matter. */ \ | |
100 | struct pt_regs { \ | |
101 | unsigned long u_regs[16]; \ | |
102 | unsigned long tstate, tpc, tnpc; \ | |
103 | unsigned int y, fprs; \ | |
104 | } *regp = (struct pt_regs *) (_sip + 1); \ | |
105 | regp->tpc = regp->tnpc; \ | |
106 | regp->tnpc += 4; \ | |
107 | } \ | |
108 | while (0) | |
109 | #endif | |
c9bffcd5 | 110 | #else |
01936f3a AH |
111 | #define MAKE_THROW_FRAME(_exception) \ |
112 | do \ | |
113 | { \ | |
c9bffcd5 | 114 | (void)_p; \ |
01936f3a AH |
115 | } \ |
116 | while (0) | |
c9bffcd5 | 117 | #endif |
01936f3a | 118 | |
714708c8 | 119 | #if !(defined(__ia64__) || defined(__sparc__)) |
01936f3a AH |
120 | #define INIT_SEGV \ |
121 | do \ | |
122 | { \ | |
123 | nullp = new java::lang::NullPointerException (); \ | |
124 | struct sigaction act; \ | |
c9bffcd5 | 125 | act.sa_sigaction = _Jv_catch_segv; \ |
01936f3a | 126 | sigemptyset (&act.sa_mask); \ |
c9bffcd5 | 127 | act.sa_flags = SA_SIGINFO; \ |
d6220b3a | 128 | syscall (SYS_sigaction, SIGSEGV, &act, NULL); \ |
01936f3a AH |
129 | } \ |
130 | while (0) | |
131 | ||
132 | #define INIT_FPE \ | |
133 | do \ | |
134 | { \ | |
135 | arithexception = new java::lang::ArithmeticException \ | |
136 | (JvNewStringLatin1 ("/ by zero")); \ | |
137 | struct sigaction act; \ | |
c9bffcd5 | 138 | act.sa_sigaction = _Jv_catch_fpe; \ |
01936f3a | 139 | sigemptyset (&act.sa_mask); \ |
c9bffcd5 | 140 | act.sa_flags = SA_SIGINFO; \ |
d6220b3a | 141 | syscall (SYS_sigaction, SIGFPE, &act, NULL); \ |
01936f3a AH |
142 | } \ |
143 | while (0) | |
144 | ||
145 | /* We use syscall(SYS_sigaction) in INIT_SEGV and INIT_FPE instead of | |
146 | * sigaction() because on some systems the pthreads wrappers for | |
147 | * signal handlers are not compiled with unwind information, so it's | |
148 | * not possible to unwind through them. This is a problem that will | |
149 | * go away once all systems have pthreads libraries that are | |
150 | * compiled with full unwind info. */ | |
151 | ||
714708c8 | 152 | #else /* __ia64__ || __sparc__ */ |
3cb20545 AH |
153 | |
154 | // FIXME: We shouldn't be using libc_sigaction here, since it should | |
155 | // be glibc private. But using syscall here would mean translating to | |
156 | // the kernel's struct sigaction and argument sequence, which we | |
157 | // shouldn't either. The right solution is to call sigaction and to | |
158 | // make sure that we can unwind correctly through the pthread signal | |
159 | // wrapper. | |
160 | extern "C" int __libc_sigaction (int __sig, | |
161 | __const struct sigaction *__restrict __act, | |
162 | struct sigaction *__restrict __oact) throw (); | |
163 | ||
164 | #define INIT_SEGV \ | |
165 | do \ | |
166 | { \ | |
167 | nullp = new java::lang::NullPointerException (); \ | |
168 | struct sigaction act; \ | |
169 | act.sa_sigaction = _Jv_catch_segv; \ | |
170 | sigemptyset (&act.sa_mask); \ | |
171 | act.sa_flags = SA_SIGINFO; \ | |
172 | __libc_sigaction (SIGSEGV, &act, NULL); \ | |
173 | } \ | |
174 | while (0) | |
175 | ||
176 | #define INIT_FPE \ | |
177 | do \ | |
178 | { \ | |
179 | arithexception = new java::lang::ArithmeticException \ | |
180 | (JvNewStringLatin1 ("/ by zero")); \ | |
181 | struct sigaction act; \ | |
182 | act.sa_sigaction = _Jv_catch_fpe; \ | |
183 | sigemptyset (&act.sa_mask); \ | |
184 | act.sa_flags = SA_SIGINFO; \ | |
185 | __libc_sigaction (SIGFPE, &act, NULL); \ | |
186 | } \ | |
187 | while (0) | |
714708c8 | 188 | #endif /* __ia64__ || __sparc__ */ |
01936f3a | 189 | #endif /* JAVA_SIGNAL_H */ |