Examine the following code:
#if defined (WIN32_NATIVE) || defined (CYGWIN)
/* Return whether all bytes in the specified memory block can be read. */
int
debug_can_access_memory (void *ptr, Memory_Count len)
{
return !IsBadReadPtr (ptr, len);
}
#else /* !(defined (WIN32_NATIVE) || defined (CYGWIN)) */
/* #### There must be a better way!!!! */
static JMP_BUF memory_error_jump;
static SIGTYPE
debug_memory_error (int signum)
{
EMACS_REESTABLISH_SIGNAL (signum, debug_memory_error);
EMACS_UNBLOCK_SIGNAL (signum);
LONGJMP (memory_error_jump, 1);
}
/* Return whether all bytes in the specified memory block can be read. */
int
debug_can_access_memory (void *ptr, Memory_Count len)
{
/* Use volatile to protect variables from being clobbered by longjmp. */
SIGTYPE (*volatile old_sigbus) (int);
SIGTYPE (*volatile old_sigsegv) (int);
volatile int old_errno = errno;
volatile int retval = 1;
if (!SETJMP (memory_error_jump))
{
old_sigbus =
(SIGTYPE (*) (int)) EMACS_SIGNAL (SIGBUS, debug_memory_error);
old_sigsegv =
(SIGTYPE (*) (int)) EMACS_SIGNAL (SIGSEGV, debug_memory_error);
if (len > 1)
/* If we can, try to avoid problems with super-optimizing compilers
that might decide that memcmp (ptr, ptr, len) can be optimized
away since its result is always 1. */
memcmp (ptr, (char *) ptr + 1, len - 1);
else
memcmp (ptr, ptr, len);
}
else
retval = 0;
EMACS_SIGNAL (SIGBUS, old_sigbus);
EMACS_SIGNAL (SIGSEGV, old_sigsegv);
errno = old_errno;
return retval;
}
#endif /* defined (WIN32_NATIVE) || defined (CYGWIN) */
My general solution for Unix, while [hopefully, i.e. i haven't tested it]
something that actually works, is clearly pretty clunky. Can anyone suggest a
better way, even if it only works on some systems?
I notice, for example, that there's an mprotect[] system call under Linux and
others that lets you change the protections of a page of memory; but there's no
corresponding call I could find to retrieve the current memory settings.
ben