source: branches/libc-0.6/src/gcc/libjava/include/i386-signal.h

Last change on this file was 1392, checked in by bird, 21 years ago

This commit was generated by cvs2svn to compensate for changes in r1391,
which included commits to RCS files with non-trunk default branches.

  • Property cvs2svn:cvs-rev set to 1.1.1.2
  • Property svn:eol-style set to native
  • Property svn:executable set to *
File size: 5.3 KB
Line 
1// i386-signal.h - Catch runtime signals and turn them into exceptions
2// on an i386 based Linux system.
3
4/* Copyright (C) 1998, 1999, 2001, 2002 Free Software Foundation
5
6 This file is part of libgcj.
7
8This software is copyrighted work licensed under the terms of the
9Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
10details. */
11
12
13#ifndef JAVA_SIGNAL_H
14#define JAVA_SIGNAL_H 1
15
16#include <signal.h>
17#include <sys/syscall.h>
18
19#define HANDLE_SEGV 1
20#define HANDLE_FPE 1
21
22#define SIGNAL_HANDLER(_name) \
23static void _name (int _dummy)
24
25#define MAKE_THROW_FRAME(_exception) \
26do \
27{ \
28 void **_p = (void **)&_dummy; \
29 struct sigcontext_struct *_regs = (struct sigcontext_struct *)++_p; \
30 \
31 /* Advance the program counter so that it is after the start of the \
32 instruction: the x86 exception handler expects \
33 the PC to point to the instruction after a call. */ \
34 _regs->eip += 2; \
35 \
36} \
37while (0)
38
39#define HANDLE_DIVIDE_OVERFLOW \
40do \
41{ \
42 void **_p = (void **)&_dummy; \
43 struct sigcontext_struct *_regs = (struct sigcontext_struct *)++_p; \
44 \
45 register unsigned char *_eip = (unsigned char *)_regs->eip; \
46 \
47 /* According to the JVM spec, "if the dividend is the negative \
48 * integer of the smallest magnitude and the divisor is -1, then \
49 * overflow occurs and the result is equal to the dividend. Despite \
50 * the overflow, no exception occurs". \
51 \
52 * We handle this by inspecting the instruction which generated the \
53 * signal and advancing eip to point to the following instruction. \
54 * As the instructions are variable length it is necessary to do a \
55 * little calculation to figure out where the following instruction \
56 * actually is. \
57 \
58 */ \
59 \
60 if (_eip[0] == 0xf7) \
61 { \
62 unsigned char _modrm = _eip[1]; \
63 \
64 if (_regs->eax == 0x80000000 \
65 && ((_modrm >> 3) & 7) == 7) /* Signed divide */ \
66 { \
67 _regs->edx = 0; /* the remainder is zero */ \
68 switch (_modrm >> 6) \
69 { \
70 case 0: \
71 if ((_modrm & 7) == 5) \
72 _eip += 4; \
73 break; \
74 case 1: \
75 _eip += 1; \
76 break; \
77 case 2: \
78 _eip += 4; \
79 break; \
80 case 3: \
81 break; \
82 } \
83 _eip += 2; \
84 _regs->eip = (unsigned long)_eip; \
85 return; \
86 } \
87 else \
88 { \
89 /* Advance the program counter so that it is after the start \
90 of the instruction: this is because the x86 exception \
91 handler expects the PC to point to the instruction after a \
92 call. */ \
93 _regs->eip += 2; \
94 } \
95 } \
96} \
97while (0)
98
99/* We use old_kernel_sigaction here because we're calling the kernel
100 directly rather than via glibc. The sigaction structure that the
101 syscall uses is a different shape from the one in userland and not
102 visible to us in a header file so we define it here. */
103
104struct old_i386_kernel_sigaction {
105 void (*k_sa_handler) (int);
106 unsigned long k_sa_mask;
107 unsigned long k_sa_flags;
108 void (*sa_restorer) (void);
109};
110
111#define RESTORE(name, syscall) RESTORE2 (name, syscall)
112# define RESTORE2(name, syscall) \
113asm \
114 ( \
115 ".text\n" \
116 ".byte 0 # Yes, this really is necessary\n" \
117 " .align 8\n" \
118 "__" #name ":\n" \
119 " popl %eax\n" \
120 " movl $" #syscall ", %eax\n" \
121 " int $0x80" \
122 );
123
124RESTORE (restore, __NR_sigreturn)
125static void restore (void) asm ("__restore");
126
127#define INIT_SEGV \
128do \
129 { \
130 nullp = new java::lang::NullPointerException (); \
131 struct old_i386_kernel_sigaction kact; \
132 kact.k_sa_handler = catch_segv; \
133 kact.k_sa_mask = 0; \
134 kact.k_sa_flags = 0x4000000; \
135 kact.sa_restorer = restore; \
136 syscall (SYS_sigaction, SIGSEGV, &kact, NULL); \
137 } \
138while (0)
139
140#define INIT_FPE \
141do \
142 { \
143 arithexception = new java::lang::ArithmeticException \
144 (JvNewStringLatin1 ("/ by zero")); \
145 struct old_i386_kernel_sigaction kact; \
146 kact.k_sa_handler = catch_fpe; \
147 kact.k_sa_mask = 0; \
148 kact.k_sa_flags = 0x4000000; \
149 kact.sa_restorer = restore; \
150 syscall (SYS_sigaction, SIGFPE, &kact, NULL); \
151 } \
152while (0)
153
154/* You might wonder why we use syscall(SYS_sigaction) in INIT_FPE
155 * instead of the standard sigaction(). This is necessary because of
156 * the shenanigans above where we increment the PC saved in the
157 * context and then return. This trick will only work when we are
158 * called _directly_ by the kernel, because linuxthreads wraps signal
159 * handlers and its wrappers do not copy the sigcontext struct back
160 * when returning from a signal handler. If we return from our divide
161 * handler to a linuxthreads wrapper, we will lose the PC adjustment
162 * we made and return to the faulting instruction again. Using
163 * syscall(SYS_sigaction) causes our handler to be called directly
164 * by the kernel, bypassing any wrappers.
165
166 * Also, there is at the present time no unwind info in the
167 * linuxthreads library's signal handlers and so we can't unwind
168 * through them anyway. */
169
170#endif /* JAVA_SIGNAL_H */
171
Note: See TracBrowser for help on using the repository browser.