dynamically written code problem
Jakub Jelinek
jakub@redhat.com
Mon Oct 11 07:48:00 GMT 2004
On Mon, Oct 11, 2004 at 09:21:36AM +0200, Paolo Bonzini wrote:
> static void
> jit_flush_code(void *dest, void *end)
> {
> /* On the x86, the PROT_EXEC bits are not handled by the MMU.
> However, the kernel can emulate this by setting the code
> segment's limit to the end address of the highest page
> whose PROT_EXEC bit is set.
>
> Linux kernels that do so and that disable by default the
> execution of the data and stack segment are becoming more
> and more common (Fedora, for example), so we implement our
> jit_flush_code as an mprotect. */
> #ifdef __linux__
> static unsigned long prev_page = 0, prev_length = 0;
> int page, length;
> #ifdef PAGESIZE
> const int page_size = PAGESIZE;
> #else
> static int page_size = -1;
> if (page_size == -1)
> page_size = sysconf (_SC_PAGESIZE);
> #endif
>
> page = (long) dest & ~(page_size - 1);
> length = ((char *) end - (char *) page + page_size - 1)
> & ~(page_size - 1);
>
> /* Simple-minded attempt at optimizing the common case where a single
> chunk of memory is used to compile multiple times. */
> if (page >= prev_page && page + length <= prev_page + prev_length)
> return;
>
> mprotect ((void *) page, length, PROT_READ | PROT_WRITE | PROT_EXEC);
1) it is better IMHO to use sysconf (_SC_PAGESIZE) always
2) doing mmap (..., | PROT_EXEC, ...) is preferrable to allocating elsewhere
and then mprotecting when using exec-shield - otherwise you lose
execute protection for too many pages where it is not desirable
Jakub
More information about the Gcc
mailing list