Subject: Why SIGBUS vs. SIGSEGV?
To: None <current-users@NetBSD.ORG>
From: Mike Long <mike.long@analog.com>
List: current-users
Date: 10/07/1996 21:49:00
I'd like to know why this bit of code raises SIGBUS under NetSD/i386
1.2, instead of the expected SIGSEGV.  It's originally from Berkeley
SPICE 3F4, file src/lib/fte/resource.c.

------------------------------------------------------------------------
#include <sys/types.h>
#include <signal.h>
#include <setjmp.h>

/*
 * baseaddr( ) returns the base address of the data segment on most Unix
 * systems.  It's an ugly hack for info that should be provided by the OS.
 */

/* Does anyone use a pagesize < 256 bytes??  I'll bet not;
 * too small doesn't hurt
 */

#define LOG2_PAGESIZE	8

static jmp_buf	env;

static void
fault( )
{
	signal(SIGSEGV, (void (*)()) fault);	/* SysV style */
	longjmp(env, 1);
}

static void *
baseaddr( )
{
	char *low, *high, *at;
	char *sbrk( );
	long x;
	void	(*orig_signal)( );

	low = 0;
	high = (char *) ((unsigned long) sbrk(0) & ~((1 << LOG2_PAGESIZE) - 1));

	orig_signal = signal(SIGSEGV, (void (*)()) fault);

	do {

		at = (char *) ((((long)low >> LOG2_PAGESIZE)
			+ ((long)high >> LOG2_PAGESIZE))
			<< (LOG2_PAGESIZE - 1));

		if (at == low || at == high) {
			break;
		}

		if (setjmp(env)) {
			low = at;
			continue;
		} else
			x = *at;

		if (setjmp(env)) {
			low = at;
			continue;
		} else
			*at = x;

		high = at;

	} while (1);

	(void) signal(SIGSEGV, (void (*)()) orig_signal);
	return (void *) high;
}

main( )
{
	printf("testing\n");
	printf("baseaddr: %#8x  topaddr: %#8x\n", baseaddr( ), sbrk(0));
}
------------------------------------------------------------------------

-- 
Mike Long <mike.long@analog.com>     <URL:http://www.shore.net/~mikel>
VLSI Design Engineer         finger mikel@shore.net for PGP public key
Analog Devices, CPD Division          CCBF225E7D3F7ECB2C8F7ABB15D9BE7B
Norwood, MA 02062 USA       (eq (opinion 'ADI) (opinion 'mike)) -> nil