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 /* Advance the program counter so that it is after the start of the \
35 instruction: the x86 exception handler expects \
36 the PC to point to the instruction after a call. */ \
42 #define HANDLE_DIVIDE_OVERFLOW \
45 void **_p = (void **)&_dummy; \
46 struct sigcontext_struct *_regs = (struct sigcontext_struct *)++_p; \
48 register unsigned char *_eip = (unsigned char *)_regs->eip; \
50 /* According to the JVM spec, "if the dividend is the negative \
51 * integer of the smallest magnitude and the divisor is -1, then \
52 * overflow occurs and the result is equal to the dividend. Despite \
53 * the overflow, no exception occurs". \
55 * We handle this by inspecting the instruction which generated the \
56 * signal and advancing eip to point to the following instruction. \
57 * As the instructions are variable length it is necessary to do a \
58 * little calculation to figure out where the following instruction \
63 if (_eip[0] == 0xf7) \
65 unsigned char _modrm = _eip[1]; \
67 if (_regs->eax == 0x80000000 \
68 && ((_modrm >> 3) & 7) == 7) /* Signed divide */ \
70 _regs->edx = 0; /* the remainder is zero */ \
71 switch (_modrm >> 6) \
74 if ((_modrm & 7) == 5) \
87 _regs->eip = (unsigned long)_eip; \
92 /* Advance the program counter so that it is after the start \
93 of the instruction: this is because the x86 exception \
94 handler expects the PC to point to the instruction after a \
105 nullp = new java::lang::NullPointerException (); \
106 struct sigaction act; \
107 act.sa_handler = catch_segv; \
108 sigemptyset (&act.sa_mask); \
110 syscall (SYS_sigaction, SIGSEGV, &act, NULL); \
117 arithexception = new java::lang::ArithmeticException \
118 (JvNewStringLatin1 ("/ by zero")); \
119 struct sigaction act; \
120 act.sa_handler = catch_fpe; \
121 sigemptyset (&act.sa_mask); \
123 syscall (SYS_sigaction, SIGFPE, &act, NULL); \
127 /* You might wonder why we use syscall(SYS_sigaction) in INIT_FPE
128 * instead of the standard sigaction(). This is necessary because of
129 * the shenanigans above where we increment the PC saved in the
130 * context and then return. This trick will only work when we are
131 * called _directly_ by the kernel, because linuxthreads wraps signal
132 * handlers and its wrappers do not copy the sigcontext struct back
133 * when returning from a signal handler. If we return from our divide
134 * handler to a linuxthreads wrapper, we will lose the PC adjustment
135 * we made and return to the faulting instruction again. Using
136 * syscall(SYS_sigaction) causes our handler to be called directly by
137 * the kernel, bypassing any wrappers. This is a kludge, and a future
138 * version of this handler will do something better. */
140 #endif /* JAVA_SIGNAL_H */