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