[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