1 // i386-signal.h - Catch runtime signals and turn them into exceptions.
3 /* Copyright (C) 1998, 1999, 2001 Free Software Foundation
5 This file is part of libgcj.
7 This software is copyrighted work licensed under the terms of the
8 Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
11 /* This technique should work for all i386 based Unices which conform
12 * to iBCS2. This includes all versions of Linux more recent than 1.3
17 #define JAVA_SIGNAL_H 1
20 #include <sys/syscall.h>
25 #define SIGNAL_HANDLER(_name) \
26 static void _name (int _dummy)
28 #define MAKE_THROW_FRAME(_exception) \
31 void **_p = (void **)&_dummy; \
32 struct sigcontext_struct *_regs = (struct sigcontext_struct *)++_p; \
34 register unsigned long _ebp = _regs->ebp; \
35 register unsigned char *_eip = (unsigned char *)_regs->eip; \
37 /* Advance the program counter so that it is after the start of the \
38 instruction: the x86 exception handler expects \
39 the PC to point to the instruction after a call. */ \
42 asm volatile ("mov %0, (%%ebp); mov %1, 4(%%ebp)" \
43 : : "r"(_ebp), "r"(_eip)); \
47 #define HANDLE_DIVIDE_OVERFLOW \
50 void **_p = (void **)&_dummy; \
51 struct sigcontext_struct *_regs = (struct sigcontext_struct *)++_p; \
53 register unsigned long *_ebp = (unsigned long *)_regs->ebp; \
54 register unsigned char *_eip = (unsigned char *)_regs->eip; \
56 /* According to the JVM spec, "if the dividend is the negative \
57 * integer of the smallest magnitude and the divisor is -1, then \
58 * overflow occurs and the result is equal to the dividend. Despite \
59 * the overflow, no exception occurs". \
61 * We handle this by inspecting the instruction which generated the \
62 * signal and advancing eip to point to the following instruction. \
63 * As the instructions are variable length it is necessary to do a \
64 * little calculation to figure out where the following instruction \
69 if (_eip[0] == 0xf7) \
71 unsigned char _modrm = _eip[1]; \
73 if (_regs->eax == 0x80000000 \
74 && ((_modrm >> 3) & 7) == 7) /* Signed divide */ \
76 _regs->edx = 0; /* the remainder is zero */ \
77 switch (_modrm >> 6) \
80 if ((_modrm & 7) == 5) \
93 _regs->eip = (unsigned long)_eip; \
96 else if (((_modrm >> 3) & 7) == 6) /* Unsigned divide */ \
98 /* We assume that unsigned divisions are in library code, so \
99 * we throw one level down the stack, which was hopefully \
100 * the place that called the library routine. This will \
101 * break if the library is ever compiled with \
102 * -fomit-frame-pointer, but at least this way we've got a \
103 * good chance of finding the exception handler. */ \
105 _eip = (unsigned char *)_ebp[1]; \
106 _ebp = (unsigned long *)_ebp[0]; \
110 /* Advance the program counter so that it is after the start \
111 of the instruction: this is because the x86 exception \
112 handler expects the PC to point to the instruction after a \
118 asm volatile ("mov %0, (%%ebp); mov %1, 4(%%ebp)" \
119 : : "r"(_ebp), "r"(_eip)); \
126 nullp = new java::lang::NullPointerException (); \
127 struct sigaction act; \
128 act.sa_handler = catch_segv; \
129 sigemptyset (&act.sa_mask); \
131 __sigaction (SIGSEGV, &act, NULL); \
138 arithexception = new java::lang::ArithmeticException \
139 (JvNewStringLatin1 ("/ by zero")); \
140 struct sigaction act; \
141 act.sa_handler = catch_fpe; \
142 sigemptyset (&act.sa_mask); \
144 syscall (SYS_sigaction, SIGFPE, &act, NULL); \
148 /* You might wonder why we use syscall(SYS_sigaction) in INIT_FPE
149 * instead of the standard sigaction(). This is necessary because of
150 * the shenanigans above where we increment the PC saved in the
151 * context and then return. This trick will only work when we are
152 * called _directly_ by the kernel, because linuxthreads wraps signal
153 * handlers and its wrappers do not copy the sigcontext struct back
154 * when returning from a signal handler. If we return from our divide
155 * handler to a linuxthreads wrapper, we will lose the PC adjustment
156 * we made and return to the faulting instruction again. Using
157 * syscall(SYS_sigaction) causes our handler to be called directly by
158 * the kernel, bypassing any wrappers. This is a kludge, and a future
159 * version of this handler will do something better. */
161 #endif /* JAVA_SIGNAL_H */