[Mono-list] help needed
Dietmar Maurer
dietmar@ximian.com
26 Nov 2001 10:31:44 +0100
On Fri, 2001-11-23 at 22:37, Serge wrote:
> > I don't have the sources right now so can't
> > point to the exact location, but something like signals-x86.h
>
> I looked it up, the file is gcc/libjava/include/i386-signal.h
> see HANDLE_DIVIDE_OVERFLOW macro
> Note that this code is for 32-bit DIVs only (0xF7 prefix)
Ok, many thanks for that hint. There code contains the explanation why
my code failed:
/* You might wonder why we use syscall(SYS_sigaction) in INIT_SEGV and
* INIT_FPE instead of the standard sigaction(). This is necessary
* because of the shenanigans above where we increment the PC saved in
* the context and then return. This trick will only work when we are
* called _directly_ by the kernel, because linuxthreads wraps signal
* handlers and its wrappers do not copy the sigcontext struct back when
* returning from a signal handler. If we return from our divide handler
* to a linuxthreads wrapper, we will lose the PC adjustment we made and
* return to the faulting instruction again. Using syscall(SYS_sigaction)
* causes our handler to be called directly by the kernel, bypassing
* any wrappers. This is a kludge, and a future version of this handler
* will do something better. */
What I still not understand why the following code does not work (I do
not use linuxthreads or any other library beside libc):
static void
normal_fp_signal_handler (int sig, siginfo_t *si, struct sigcontext *ctx)
{
/* ctx->eip and ctx->ebp are always zero ?? */
printf ("TEST %08x %08x\n", ctx->eip, ctx->ebp);
exit (0);
}
int
main ()
{
int a = 5, b = 0;
struct sigaction sa;
sa.sa_sigaction = normal_fp_signal_handler;
sigemptyset (&sa.sa_mask);
sa.sa_flags = SA_SIGINFO;
sigaction (SIGFPE, &sa, NULL);
return a/b;
}
It work when I use the libjava approach:
static void
strange_fp_signal_handler (int _dummy)
{
void **_p = (void **)&_dummy;
struct sigcontext_struct *ctx = (struct sigcontext_struct *)++_p;
printf ("TEST %08x %08x\n", ctx->eip, ctx->ebp);
exit (0);
}
int
main ()
{
int a = 5, b = 0;
struct sigaction sa;
sa.sa_handler = strange_fp_signal_handler;
sigemptyset (&sa.sa_mask);
sa.sa_flags = 0;
syscall (SYS_sigaction, SIGFPE, &sa, NULL);
return a/b;
}
I just wonder why it does not work - maybe someone knows it?
- Dietmar