The testsuite program gcc.c-torture/execute/nestfunc-3.c crashes with a bus error on i686-apple-darwin8. Tried it with gcc-3.4.4, gcc-4.0.2 and gcc-4.1-20051112.
Subject: Trampolines fail on i686-apple-darwin Note the gcc.c-torture/execute/nestfunc-5.c fails also (with a bus error). Adriaan van Os
Subject: Trampolines fail on i686-apple-darwin On closer inspection, the problem is that the stack is non-executable. Adding the following code (borrowed from gcc/config/netbsd.h) to darwin.h fixes the problem Adriaan van Os /* Attempt to turn on execute permission for the stack. This may be used by INITIALIZE_TRAMPOLINE of the target needs it (that is, if the target machine can change execute permissions on a page). There is no way to query the execute permission of the stack, so we always issue the mprotect() call. Note that we go out of our way to use namespace-non-invasive calls here. Unfortunately, there is no libc-internal name for mprotect(). Also note that no errors should be emitted by this code; it is considered dangerous for library calls to send messages to stdout/stderr. */ #define ENABLE_EXECUTE_STACK \ extern void __enable_execute_stack (void *); \ void \ __enable_execute_stack (void *addr) \ { \ extern int mprotect (void *, size_t, int); \ extern int __sysctl (int *, unsigned int, void *, size_t *, \ void *, size_t); \ \ static int size; \ static long mask; \ \ char *page, *end; \ \ if (size == 0) \ { \ int mib[2]; \ size_t len; \ \ mib[0] = 6; /* CTL_HW */ \ mib[1] = 7; /* HW_PAGESIZE */ \ len = sizeof (size); \ (void) __sysctl (mib, 2, &size, &len, NULL, 0); \ mask = ~((long) size - 1); \ } \ \ page = (char *) (((long) addr) & mask); \ end = (char *) ((((long) (addr + TRAMPOLINE_SIZE)) & mask) + size); \ \ /* 7 == PROT_READ | PROT_WRITE | PROT_EXEC */ \ (void) mprotect (page, end - page, 7); \ }
I should note that in Apple's GCC for i686-darwin, they warn about this. I think they should look into fixing the issue here. Anyways confirmed.
Subject: Trampolines fail on i686-apple-darwin because stack is not executable Clarification - I forgot to mention that the code above (the ENABLE_EXECUTE_STACK macro) must be added to gcc/config/i386/darwin.h not to gcc/config/darwin.h. It works also for gcc-3.4.4. Adriaan van Os
gcc.c-torture/execute/20000822-1.c fails the same way.
I will submit this.
I think this should be done for both PowerPC and x86 targets for Darwin. The vendor compiler rejects nested functions for both targets presumably because of this, and so trampolines should enable stack execution for both targets
Subject: Re: Trampolines fail on i686-apple-darwin because stack is not executable Currently it is not necessary for powerpc, but Apple may indeed change this in a future version of powerpc-darwin.
(In reply to comment #8) > Currently it is not necessary for powerpc, but Apple may indeed change > this in a future version of powerpc-darwin. In a way it is already needed for powerpc-darwin.
No longer working on this, too much troubles are causing to me to fix Darwin bugs.
There are two ways to fix this, the easiest way is to pass -allow_stack_execute through to the linker when we want an executable stack. This is problematic since we'll not be specifying it on the command line. We can turn on an allowable stack at all times, but this is less safe than turning it on only when necessary. The other way is to use mprotect like the patch has below.
Subject: Re: Trampolines fail on i686-apple-darwin because stack is not executable I agree that calling mprotect is the best fix. Adriaan van Os
Patch in testing.
Fixed.