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