Bug 24959 - Trampolines fail on i686-apple-darwin because stack is not executable
Summary: Trampolines fail on i686-apple-darwin because stack is not executable
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: target (show other bugs)
Version: 4.1.0
: P3 major
Target Milestone: 4.2.0
Assignee: Eric Christopher
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2005-11-20 16:19 UTC by Adriaan van Os
Modified: 2007-01-10 19:27 UTC (History)
3 users (show)

See Also:
Host:
Target: i686-apple-darwin
Build:
Known to work:
Known to fail:
Last reconfirmed: 2006-02-27 08:35:11


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Adriaan van Os 2005-11-20 16:19:03 UTC
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.
Comment 1 Adriaan van Os 2005-11-20 21:17:15 UTC
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

Comment 2 Adriaan van Os 2005-11-21 19:28:11 UTC
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);				\
}

Comment 3 Andrew Pinski 2005-11-21 20:43:26 UTC
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.
Comment 4 Adriaan van Os 2005-11-22 09:12:34 UTC
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

Comment 5 Andrew Pinski 2006-01-12 01:56:29 UTC
gcc.c-torture/execute/20000822-1.c fails the same way.
Comment 6 Andrew Pinski 2006-01-12 01:57:37 UTC
I will submit this.
Comment 7 Shantonu Sen 2006-01-17 15:15:13 UTC
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
Comment 8 Adriaan van Os 2006-01-17 15:30:16 UTC
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.

Comment 9 Andrew Pinski 2006-01-25 18:35:30 UTC
(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.
Comment 10 Andrew Pinski 2006-02-20 23:53:53 UTC
No longer working on this, too much troubles are causing to me to fix Darwin bugs.
Comment 11 Eric Christopher 2006-02-27 08:35:11 UTC
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.
Comment 12 Adriaan van Os 2006-02-27 12:03:40 UTC
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

Comment 13 Eric Christopher 2006-02-28 01:48:33 UTC
Patch in testing.
Comment 14 Eric Christopher 2006-03-03 20:17:59 UTC
Fixed.