]>
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 \ | |
6ea53170 DM |
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. */ \ | |
714708c8 DM |
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)); \ | |
4bf01445 | 84 | /* mov __NR_sigaction, %g1; Old signal stack layout */ \ |
714708c8 DM |
85 | if (insn == 0x821020d8) \ |
86 | regp = (struct sig_regs *) _sip; \ | |
87 | else \ | |
4bf01445 | 88 | /* mov __NR_rt_sigaction, %g1; New signal stack layout */ \ |
714708c8 | 89 | regp = (struct sig_regs *) (_sip + 1); \ |
6ea53170 | 90 | regp->pc = ((regp->pc + 4) - 8); \ |
714708c8 DM |
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 \ | |
6ea53170 DM |
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. */ \ | |
714708c8 DM |
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); \ | |
6ea53170 | 112 | regp->tpc = ((regp->tpc + 4) - 8); \ |
714708c8 DM |
113 | } \ |
114 | while (0) | |
115 | #endif | |
c9bffcd5 | 116 | #else |
01936f3a AH |
117 | #define MAKE_THROW_FRAME(_exception) \ |
118 | do \ | |
119 | { \ | |
c9bffcd5 | 120 | (void)_p; \ |
01936f3a AH |
121 | } \ |
122 | while (0) | |
c9bffcd5 | 123 | #endif |
01936f3a | 124 | |
714708c8 | 125 | #if !(defined(__ia64__) || defined(__sparc__)) |
01936f3a AH |
126 | #define INIT_SEGV \ |
127 | do \ | |
128 | { \ | |
129 | nullp = new java::lang::NullPointerException (); \ | |
130 | struct sigaction act; \ | |
c9bffcd5 | 131 | act.sa_sigaction = _Jv_catch_segv; \ |
01936f3a | 132 | sigemptyset (&act.sa_mask); \ |
c9bffcd5 | 133 | act.sa_flags = SA_SIGINFO; \ |
d6220b3a | 134 | syscall (SYS_sigaction, SIGSEGV, &act, NULL); \ |
01936f3a AH |
135 | } \ |
136 | while (0) | |
137 | ||
138 | #define INIT_FPE \ | |
139 | do \ | |
140 | { \ | |
141 | arithexception = new java::lang::ArithmeticException \ | |
142 | (JvNewStringLatin1 ("/ by zero")); \ | |
143 | struct sigaction act; \ | |
c9bffcd5 | 144 | act.sa_sigaction = _Jv_catch_fpe; \ |
01936f3a | 145 | sigemptyset (&act.sa_mask); \ |
c9bffcd5 | 146 | act.sa_flags = SA_SIGINFO; \ |
d6220b3a | 147 | syscall (SYS_sigaction, SIGFPE, &act, NULL); \ |
01936f3a AH |
148 | } \ |
149 | while (0) | |
150 | ||
151 | /* We use syscall(SYS_sigaction) in INIT_SEGV and INIT_FPE instead of | |
152 | * sigaction() because on some systems the pthreads wrappers for | |
153 | * signal handlers are not compiled with unwind information, so it's | |
154 | * not possible to unwind through them. This is a problem that will | |
155 | * go away once all systems have pthreads libraries that are | |
156 | * compiled with full unwind info. */ | |
157 | ||
714708c8 | 158 | #else /* __ia64__ || __sparc__ */ |
3cb20545 AH |
159 | |
160 | // FIXME: We shouldn't be using libc_sigaction here, since it should | |
161 | // be glibc private. But using syscall here would mean translating to | |
162 | // the kernel's struct sigaction and argument sequence, which we | |
163 | // shouldn't either. The right solution is to call sigaction and to | |
164 | // make sure that we can unwind correctly through the pthread signal | |
165 | // wrapper. | |
166 | extern "C" int __libc_sigaction (int __sig, | |
167 | __const struct sigaction *__restrict __act, | |
168 | struct sigaction *__restrict __oact) throw (); | |
169 | ||
170 | #define INIT_SEGV \ | |
171 | do \ | |
172 | { \ | |
173 | nullp = new java::lang::NullPointerException (); \ | |
174 | struct sigaction act; \ | |
175 | act.sa_sigaction = _Jv_catch_segv; \ | |
176 | sigemptyset (&act.sa_mask); \ | |
177 | act.sa_flags = SA_SIGINFO; \ | |
178 | __libc_sigaction (SIGSEGV, &act, NULL); \ | |
179 | } \ | |
180 | while (0) | |
181 | ||
182 | #define INIT_FPE \ | |
183 | do \ | |
184 | { \ | |
185 | arithexception = new java::lang::ArithmeticException \ | |
186 | (JvNewStringLatin1 ("/ by zero")); \ | |
187 | struct sigaction act; \ | |
188 | act.sa_sigaction = _Jv_catch_fpe; \ | |
189 | sigemptyset (&act.sa_mask); \ | |
190 | act.sa_flags = SA_SIGINFO; \ | |
191 | __libc_sigaction (SIGFPE, &act, NULL); \ | |
192 | } \ | |
193 | while (0) | |
714708c8 | 194 | #endif /* __ia64__ || __sparc__ */ |
01936f3a | 195 | #endif /* JAVA_SIGNAL_H */ |