[build] Move ENABLE_EXECUTE_STACK to toplevel libgcc

Rainer Orth ro@CeBiTec.Uni-Bielefeld.DE
Mon Jun 6 09:18:00 GMT 2011


Paolo Bonzini <bonzini@gnu.org> writes:

>> * Except for Darwin, the code uses TRAMPOLINE_SIZE.  This only exists in
>>    the backend headers.  While it could be duplicated somewhere in the
>>    libgcc configury, I'd rather propose that gcc define
>>    __TRAMPOLINE_SIZE__ (in gcc/c-family/c-cppbuiltin.c (c_cpp_builtins)
>>    to avoid this.  On PowerPC Darwin, one cannot use TRAMPOLINE_SIZE
>>    definition right now since the macro calls the rs6000_trampoline_size
>>    function in rs6000/rs6000.c.  This would be solved nicely by
>>    __TRAMPOLINE_SIZE__.
>
> Good idea.

Included in the revised patch below.  This part will need Joseph's approval.

>> * FreeBSD and Solaris use a check_enabling function to check if
>>    __enable_execute_stack needs to run at all.  Initially, I had
>>    enable-execute-stack-{freebsd, netbsd, sol2}.c, all including a common
>>    enable-execute-stack-mprotect.c to avoid code duplication.  I now
>>    consider that ugly and hard to read, and merged everything into a
>>    common enable-execute-stack-mprotect.c below.  Right now, the file
>>    uses __FreeBSD__, __NetBSD__, and __sun__&&  __svr4__ to select the
>>    right code, but this could be autoconf'ed if desired.  There are a
>>    couple of FIXME comments in the code.
>
> Please avoid putting the ((constructor)) in common code.  You can put
>
> static int i = 1;
>
> in the #else case, and leave
>
> static int i;
>
> in common code.

Ok, done.

>> * NetBSD is extremely careful to avoid namespace pollution and uses
>>    private __sysctl (declared privately) to avoid using getpagesize.
>>    Either this is an issue, and we might do something similar on all
>>    platforms, or it's not and we should avoid special-casing NetBSD
>>    here.
>
> Perhaps it has to do with getpagesize not being available for old versions
> of NetBSD.  No idea, but I'd leave it as is.

I've now included the relevant comments from the old
ENABLE_EXECUTE_STACK definitions where it's claimed this is done for
namespace cleanliness.

>> * Windows32 calls abort when VirtualProtect fails.  With the exception
>>    of Darwin and NetBSD, all others call perror, which seems to be
>>    frowned upon.  We should be consistent here.
>
> I think it should either abort() or do nothing, consistently across all
> platforms.

I'm going for abort then.  Silently failing here is bad IMO since the
user will have to debug an issue in the runtime library.  libgcc2.c is
already using abort in a couple of places, so there's a precedent.

>> * gcc/config/i386/mingw32.h has
>>
>> #ifdef IN_LIBGCC2
>> #include<windows.h>
>> #endif
>>
>>    I strongly suspect that this is only to declare VirtualQuery and
>>    VirtualProtect and can go if ENABLE_EXECUTE_STACK is removed?
>
> Yes, it should go.

Done.

>> * Finally, __enable_execute_stack is only used on those NetBSD targets
>> that actually define HAVE_ENABLE_EXECUTE_STACK, while OpenBSD uses it
>> everywhere.  config.host could be simplyfied if NetBSD behaved the
>> same.
>
> I would add it to all NetBSDs, and perhaps all FreeBSDs too?  Do you know
> why SPARC is special?

I've no idea.  Given that OpenBSD uses the same implementation across
all targets, I'm treating the two other BSDs the same now, unless the
maintainers objects.

I've removed a couple of FIXME comments I had in the last version:

* Instead of __FreeBSD__, one could use HAVE_SYSCTLBYNAME instead, but
  that would need a new libgcc config.h header.  In addition, we might
  have to check for kern.stackprot to make sure the code really works.

* Similarly, instead of testing __sun__ && __svr4__, one could check
  _SC_STACK_PROT.

* Last, rather than checking __NetBSD__, one could go for HAVE___SYSCTL.

* __sysctl is currently declared manully.  AFAICS there's no header for
  that.  At least the FreeBSD libc declares it itself in two places:
  lib/libc/sys/stack_protector.c and lib/libc/gen/sysctl.c.

Given that this is closely tied to the various platforms, it seems
appropriate to continue to use the OS defines.

Here's the full patch, regtested without regressions on
i386-pc-solaris2.11.

Ok for mainline?

	Rainer


2011-05-29  Rainer Orth  <ro@CeBiTec.Uni-Bielefeld.DE>

	gcc:
	* config/alpha/netbsd.h (ENABLE_EXECUTE_STACK): Remove.
	(HAVE_ENABLE_EXECUTE_STACK): Define.
	* config/alpha/osf5.h (ENABLE_EXECUTE_STACK): Remove.
	(HAVE_ENABLE_EXECUTE_STACK): Define.
	* config/darwin.h (ENABLE_EXECUTE_STACK): Remove.
	(HAVE_ENABLE_EXECUTE_STACK): Define.
	* config/i386/mingw32.h (MINGW_ENABLE_EXECUTE_STACK): Remove.
	(ENABLE_EXECUTE_STACK): Remove.
	(HAVE_ENABLE_EXECUTE_STACK): Define.
	[IN_LIBGCC2]: Don't include <windows.h>.
	* config/i386/netbsd-elf.h (ENABLE_EXECUTE_STACK): Remove.
	(HAVE_ENABLE_EXECUTE_STACK): Define.
	* config/i386/netbsd64.h (ENABLE_EXECUTE_STACK): Remove.
	(HAVE_ENABLE_EXECUTE_STACK): Define.
	* config/netbsd.h (NETBSD_ENABLE_EXECUTE_STACK): Remove.
	* config/openbsd.h (ENABLE_EXECUTE_STACK): Remove.
	(HAVE_ENABLE_EXECUTE_STACK): Define.
	* config/sol2.h (ENABLE_EXECUTE_STACK): Remove.
	(HAVE_ENABLE_EXECUTE_STACK): Define.
	* config/sparc/freebsd.h (ENABLE_EXECUTE_STACK): Remove.
	(HAVE_ENABLE_EXECUTE_STACK): Define.
	* config/sparc/netbsd-elf.h (ENABLE_EXECUTE_STACK): Remove.
	(HAVE_ENABLE_EXECUTE_STACK): Define.
	* config/alpha/alpha.c (alpha_trampoline_init): Test
	HAVE_ENABLE_EXECUTE_STACK.
	* config/i386/i386.c (ix86_trampoline_init): Likewise.
	* config/sparc/sparc.c (sparc32_initialize_trampoline): Likewise.
	(sparc64_initialize_trampoline): Likewise.
	* libgcc2.c [L_enable_execute_stack]: Remove.
	* system.h (ENABLE_EXECUTE_STACK): Poison.
	* doc/tm.texi.in (Trampolines, HAVE_ENABLE_EXECUTE_STACK): Document.
	(Trampolines, ENABLE_EXECUTE_STACK): Remove.
	* doc/tm.texi: Regenerate.

	gcc/c-family:
	* c-cppbuiltin.c (c_cpp_builtins): Define __TRAMPOLINE_SIZE__.

	libgcc:
	* enable-execute-stack-empty.c: New file.
	* enable-execute-stack-mprotect.c: New file.
	* config/i386/enable-execute-stack-mingw32.c: New file.
	* config.host (enable_execute_stack): New variable.
	Select appropriate variants.
	* configure.ac: Link enable-execute-stack.c to
	$enable_execute_stack.
	* configure: Regenerate.
	* Makefile.in (LIB2ADD): Add enable-execute-stack.c.
	(lib2funcs): Remove _enable_execute_stack.

diff --git a/gcc/c-family/c-cppbuiltin.c b/gcc/c-family/c-cppbuiltin.c
--- a/gcc/c-family/c-cppbuiltin.c
+++ b/gcc/c-family/c-cppbuiltin.c
@@ -1,5 +1,5 @@
 /* Define builtin-in macros for the C family front ends.
-   Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
+   Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
    Free Software Foundation, Inc.
 
 This file is part of GCC.
@@ -727,6 +727,9 @@ c_cpp_builtins (cpp_reader *pfile)
       builtin_define_fixed_point_constants ("UTA", "", uta_type_node);
     }
 
+  /* For libgcc enable-execute-stack.c.  */
+  builtin_define_with_int_value ("__TRAMPOLINE_SIZE__", TRAMPOLINE_SIZE);
+
   /* For use in assembly language.  */
   builtin_define_with_value ("__REGISTER_PREFIX__", REGISTER_PREFIX, 0);
   builtin_define_with_value ("__USER_LABEL_PREFIX__", user_label_prefix, 0);
diff --git a/gcc/config/alpha/alpha.c b/gcc/config/alpha/alpha.c
--- a/gcc/config/alpha/alpha.c
+++ b/gcc/config/alpha/alpha.c
@@ -5395,7 +5395,7 @@ alpha_trampoline_init (rtx m_tramp, tree
   if (TARGET_ABI_OSF)
     {
       emit_insn (gen_imb ());
-#ifdef ENABLE_EXECUTE_STACK
+#ifdef HAVE_ENABLE_EXECUTE_STACK
       emit_library_call (init_one_libfunc ("__enable_execute_stack"),
 			 LCT_NORMAL, VOIDmode, 1, XEXP (m_tramp, 0), Pmode);
 #endif
diff --git a/gcc/config/alpha/netbsd.h b/gcc/config/alpha/netbsd.h
--- a/gcc/config/alpha/netbsd.h
+++ b/gcc/config/alpha/netbsd.h
@@ -73,7 +73,4 @@ along with GCC; see the file COPYING3.  
   "%{Ofast|ffast-math|funsafe-math-optimizations:crtfm%O%s} \
    %(netbsd_endfile_spec)"
 
-
-/* Attempt to enable execute permissions on the stack.  */
-
-#define ENABLE_EXECUTE_STACK NETBSD_ENABLE_EXECUTE_STACK
+#define HAVE_ENABLE_EXECUTE_STACK
diff --git a/gcc/config/alpha/osf5.h b/gcc/config/alpha/osf5.h
--- a/gcc/config/alpha/osf5.h
+++ b/gcc/config/alpha/osf5.h
@@ -165,22 +165,7 @@ along with GCC; see the file COPYING3.  
 #define HAVE_STAMP_H 1
 #endif
 
-/* Attempt to turn on access permissions for the stack.  */
-
-#define ENABLE_EXECUTE_STACK						\
-void									\
-__enable_execute_stack (void *addr)					\
-{									\
-  extern int mprotect (const void *, size_t, int);			\
-  long size = getpagesize ();						\
-  long mask = ~(size-1);						\
-  char *page = (char *) (((long) addr) & mask);				\
-  char *end  = (char *) ((((long) (addr + TRAMPOLINE_SIZE)) & mask) + size); \
-									\
-  /* 7 is PROT_READ | PROT_WRITE | PROT_EXEC */				\
-  if (mprotect (page, end - page, 7) < 0)				\
-    perror ("mprotect of trampoline code");				\
-}
+#define HAVE_ENABLE_EXECUTE_STACK
 
 /* Digital UNIX V4.0E (1091)/usr/include/sys/types.h 4.3.49.9 1997/08/14 */
 #define SIZE_TYPE	"long unsigned int"
diff --git a/gcc/config/darwin.h b/gcc/config/darwin.h
--- a/gcc/config/darwin.h
+++ b/gcc/config/darwin.h
@@ -919,43 +919,7 @@ void add_framework_path (char *);
 #define TARGET_ASM_OUTPUT_ANCHOR NULL
 #define DARWIN_SECTION_ANCHORS 0
 
-/* Attempt to turn on execute permission for the stack.  This may be
-    used by TARGET_TRAMPOLINE_INIT if 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.
-
-    Unfortunately it is not possible to make this namespace-clean.
-
-    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 getpagesize (void);					\
-   static int size;                                                     \
-   static long mask;                                                    \
-                                                                        \
-   char *page, *end;                                                    \
-                                                                        \
-   if (size == 0)                                                       \
-     {                                                                  \
-       size = getpagesize();						\
-       mask = ~((long) size - 1);                                       \
-     }                                                                  \
-                                                                        \
-   page = (char *) (((long) addr) & mask);                              \
-   end  = (char *) ((((long) (addr + (TARGET_64BIT ? 48 : 40))) & mask) + size); \
-                                                                        \
-   /* 7 == PROT_READ | PROT_WRITE | PROT_EXEC */                        \
-   (void) mprotect (page, end - page, 7);                               \
-}
+#define HAVE_ENABLE_EXECUTE_STACK
 
 /* For Apple KEXTs, we make the constructors return this to match gcc
    2.95.  */
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -23387,7 +23387,7 @@ ix86_trampoline_init (rtx m_tramp, tree 
       gcc_assert (offset <= TRAMPOLINE_SIZE);
     }
 
-#ifdef ENABLE_EXECUTE_STACK
+#ifdef HAVE_ENABLE_EXECUTE_STACK
 #ifdef CHECK_EXECUTE_STACK_ENABLED
   if (CHECK_EXECUTE_STACK_ENABLED)
 #endif
diff --git a/gcc/config/i386/mingw32.h b/gcc/config/i386/mingw32.h
--- a/gcc/config/i386/mingw32.h
+++ b/gcc/config/i386/mingw32.h
@@ -219,28 +219,10 @@ do {						         \
 /* Let defaults.h definition of TARGET_USE_JCR_SECTION apply. */
 #undef TARGET_USE_JCR_SECTION
 
-#undef MINGW_ENABLE_EXECUTE_STACK
-#define MINGW_ENABLE_EXECUTE_STACK     \
-extern void __enable_execute_stack (void *);    \
-void         \
-__enable_execute_stack (void *addr)					\
-{									\
-  MEMORY_BASIC_INFORMATION b;						\
-  if (!VirtualQuery (addr, &b, sizeof(b)))				\
-    abort ();								\
-  VirtualProtect (b.BaseAddress, b.RegionSize, PAGE_EXECUTE_READWRITE,	\
-		  &b.Protect);						\
-}
-
-#undef ENABLE_EXECUTE_STACK
-#define ENABLE_EXECUTE_STACK MINGW_ENABLE_EXECUTE_STACK
+#define HAVE_ENABLE_EXECUTE_STACK
 #undef  CHECK_EXECUTE_STACK_ENABLED
 #define CHECK_EXECUTE_STACK_ENABLED flag_setstackexecutable
 
-#ifdef IN_LIBGCC2
-#include <windows.h>
-#endif
-
 /* This matches SHLIB_SONAME and SHLIB_SOVERSION in t-cygming. */
 /* This matches SHLIB_SONAME and SHLIB_SOVERSION in t-cygwin. */
 #if DWARF2_UNWIND_INFO
diff --git a/gcc/config/i386/netbsd-elf.h b/gcc/config/i386/netbsd-elf.h
--- a/gcc/config/i386/netbsd-elf.h
+++ b/gcc/config/i386/netbsd-elf.h
@@ -118,5 +118,4 @@ along with GCC; see the file COPYING3.  
    we don't care about compatibility with older gcc versions.  */
 #define DEFAULT_PCC_STRUCT_RETURN 1
 
-/* Attempt to enable execute permissions on the stack.  */
-#define ENABLE_EXECUTE_STACK NETBSD_ENABLE_EXECUTE_STACK
+#define HAVE_ENABLE_EXECUTE_STACK
diff --git a/gcc/config/i386/netbsd64.h b/gcc/config/i386/netbsd64.h
--- a/gcc/config/i386/netbsd64.h
+++ b/gcc/config/i386/netbsd64.h
@@ -66,5 +66,4 @@ along with GCC; see the file COPYING3.  
     fprintf (FILE, "\tcall __mcount\n");				\
 }
 
-/* Attempt to enable execute permissions on the stack.  */
-#define ENABLE_EXECUTE_STACK NETBSD_ENABLE_EXECUTE_STACK
+#define HAVE_ENABLE_EXECUTE_STACK
diff --git a/gcc/config/netbsd.h b/gcc/config/netbsd.h
--- a/gcc/config/netbsd.h
+++ b/gcc/config/netbsd.h
@@ -1,6 +1,6 @@
 /* Base configuration file for all NetBSD targets.
    Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
-   2007, 2009, 2010 Free Software Foundation, Inc.
+   2007, 2009, 2010, 2011 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -173,50 +173,3 @@ along with GCC; see the file COPYING3.  
 
 #undef WINT_TYPE
 #define WINT_TYPE "int"
-
-
-/* Attempt to turn on execute permission for the stack.  This may be
-   used by TARGET_TRAMPOLINE_INIT if 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 NETBSD_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);				\
-}
diff --git a/gcc/config/openbsd.h b/gcc/config/openbsd.h
--- a/gcc/config/openbsd.h
+++ b/gcc/config/openbsd.h
@@ -281,20 +281,4 @@ do {									 \
 /* Storage layout.  */
 
 
-/* Stack is explicitly denied execution rights on OpenBSD platforms.  */
-#define ENABLE_EXECUTE_STACK						\
-extern void __enable_execute_stack (void *);				\
-void									\
-__enable_execute_stack (void *addr)					\
-{									\
-  long size = getpagesize ();						\
-  long mask = ~(size-1);						\
-  char *page = (char *) (((long) addr) & mask); 			\
-  char *end  = (char *) ((((long) (addr + TRAMPOLINE_SIZE)) & mask) + size); \
-								      \
-  if (mprotect (page, end - page, PROT_READ | PROT_WRITE | PROT_EXEC) < 0) \
-    perror ("mprotect of trampoline code");				\
-}
-
-#include <sys/types.h>
-#include <sys/mman.h>
+#define HAVE_ENABLE_EXECUTE_STACK
diff --git a/gcc/config/sol2.h b/gcc/config/sol2.h
--- a/gcc/config/sol2.h
+++ b/gcc/config/sol2.h
@@ -207,52 +207,7 @@ along with GCC; see the file COPYING3.  
 
 #define STDC_0_IN_SYSTEM_HEADERS 1
 
-/*
- * Attempt to turn on access permissions for the stack.
- *
- * _SC_STACK_PROT is only defined for post 2.6, but we want this code
- * to run always.  2.6 can change the stack protection but has no way to
- * query it.
- *
- */
-
-/* sys/mman.h is not present on some non-Solaris configurations
-   that use sol2.h, so ENABLE_EXECUTE_STACK must use a magic
-   number instead of the appropriate PROT_* flags.  */
-
-#define ENABLE_EXECUTE_STACK					\
-									\
-/* #define STACK_PROT_RWX (PROT_READ | PROT_WRITE | PROT_EXEC) */	\
-									\
-static int need_enable_exec_stack;					\
-									\
-static void check_enabling(void) __attribute__ ((constructor));		\
-static void check_enabling(void)					\
-{									\
-  extern long sysconf(int);						\
-									\
-  int prot = (int) sysconf(515 /* _SC_STACK_PROT */);			\
-  if (prot != 7 /* STACK_PROT_RWX */)					\
-    need_enable_exec_stack = 1;						\
-}									\
-									\
-extern void __enable_execute_stack (void *);				\
-void									\
-__enable_execute_stack (void *addr)					\
-{									\
-  extern int mprotect(void *, size_t, int);				\
-  if (!need_enable_exec_stack)						\
-    return;								\
-  else {								\
-    long size = getpagesize ();						\
-    long mask = ~(size-1);						\
-    char *page = (char *) (((long) addr) & mask); 			\
-    char *end  = (char *) ((((long) (addr + TRAMPOLINE_SIZE)) & mask) + size); \
-									\
-    if (mprotect (page, end - page, 7 /* STACK_PROT_RWX */) < 0)	\
-      perror ("mprotect of trampoline code");				\
-  }									\
-}
+#define HAVE_ENABLE_EXECUTE_STACK
 
 /* Support Solaris-specific format checking for cmn_err.  */
 #define TARGET_N_FORMAT_TYPES 1
diff --git a/gcc/config/sparc/freebsd.h b/gcc/config/sparc/freebsd.h
--- a/gcc/config/sparc/freebsd.h
+++ b/gcc/config/sparc/freebsd.h
@@ -98,31 +98,7 @@ along with GCC; see the file COPYING3.  
 #undef  SPARC_DEFAULT_CMODEL
 #define SPARC_DEFAULT_CMODEL	CM_MEDLOW
 
-#define ENABLE_EXECUTE_STACK						\
-  static int need_enable_exec_stack;					\
-  static void check_enabling(void) __attribute__ ((constructor));	\
-  static void check_enabling(void)					\
-  {									\
-    extern int sysctlbyname(const char *, void *, size_t *, void *, size_t);\
-    int prot = 0;							\
-    size_t len = sizeof(prot);						\
-									\
-    sysctlbyname ("kern.stackprot", &prot, &len, NULL, 0);		\
-    if (prot != 7)							\
-      need_enable_exec_stack = 1;					\
-  }									\
-  extern void __enable_execute_stack (void *);				\
-  void __enable_execute_stack (void *addr)				\
-  {									\
-    if (!need_enable_exec_stack)					\
-      return;								\
-    else {								\
-      /* 7 is PROT_READ | PROT_WRITE | PROT_EXEC */ 			\
-      if (mprotect (addr, TRAMPOLINE_SIZE, 7) < 0)			\
-        perror ("mprotect of trampoline code");				\
-    }									\
-  }
-
+#define HAVE_ENABLE_EXECUTE_STACK
 
 /************************[  Assembler stuff  ]********************************/
 
diff --git a/gcc/config/sparc/netbsd-elf.h b/gcc/config/sparc/netbsd-elf.h
--- a/gcc/config/sparc/netbsd-elf.h
+++ b/gcc/config/sparc/netbsd-elf.h
@@ -74,8 +74,7 @@ along with GCC; see the file COPYING3.  
 
 #undef STDC_0_IN_SYSTEM_HEADERS
 
-/* Attempt to enable execute permissions on the stack.  */
-#define ENABLE_EXECUTE_STACK NETBSD_ENABLE_EXECUTE_STACK
+#define HAVE_ENABLE_EXECUTE_STACK
 
 /* Below here exists the merged NetBSD/sparc & NetBSD/sparc64 compiler
    description, allowing one to build 32-bit or 64-bit applications
diff --git a/gcc/config/sparc/sparc.c b/gcc/config/sparc/sparc.c
--- a/gcc/config/sparc/sparc.c
+++ b/gcc/config/sparc/sparc.c
@@ -8002,7 +8002,7 @@ sparc32_initialize_trampoline (rtx m_tra
 
   /* Call __enable_execute_stack after writing onto the stack to make sure
      the stack address is accessible.  */
-#ifdef ENABLE_EXECUTE_STACK
+#ifdef HAVE_ENABLE_EXECUTE_STACK
   emit_library_call (gen_rtx_SYMBOL_REF (Pmode, "__enable_execute_stack"),
                      LCT_NORMAL, VOIDmode, 1, XEXP (m_tramp, 0), Pmode);
 #endif
@@ -8045,7 +8045,7 @@ sparc64_initialize_trampoline (rtx m_tra
 
   /* Call __enable_execute_stack after writing onto the stack to make sure
      the stack address is accessible.  */
-#ifdef ENABLE_EXECUTE_STACK
+#ifdef HAVE_ENABLE_EXECUTE_STACK
   emit_library_call (gen_rtx_SYMBOL_REF (Pmode, "__enable_execute_stack"),
                      LCT_NORMAL, VOIDmode, 1, XEXP (m_tramp, 0), Pmode);
 #endif
diff --git a/gcc/doc/tm.texi.in b/gcc/doc/tm.texi.in
--- a/gcc/doc/tm.texi.in
+++ b/gcc/doc/tm.texi.in
@@ -5142,13 +5142,11 @@ typically be a series of @code{asm} stat
 @end defmac
 
 The operating system may also require the stack to be made executable
-before calling the trampoline.  To implement this requirement, define
-the following macro.
-
-@defmac ENABLE_EXECUTE_STACK
+before calling the trampoline.  If so, define the following macro.
+
+@defmac HAVE_ENABLE_EXECUTE_STACK
 Define this macro if certain operations must be performed before executing
-code located on the stack.  The macro should expand to a series of C
-file-scope constructs (e.g.@: functions) and provide a unique entry point
+code located on the stack.  libgcc must provide a unique entry point
 named @code{__enable_execute_stack}.  The target is responsible for
 emitting calls to the entry point in the code, for example from the
 @code{TARGET_TRAMPOLINE_INIT} hook.
diff --git a/gcc/libgcc2.c b/gcc/libgcc2.c
--- a/gcc/libgcc2.c
+++ b/gcc/libgcc2.c
@@ -1,7 +1,7 @@
 /* More subroutines needed by GCC output code on some machines.  */
 /* Compile this one with gcc.  */
 /* Copyright (C) 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
-   2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2009, 2010
+   2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2009, 2010, 2011
    Free Software Foundation, Inc.
 
 This file is part of GCC.
@@ -2027,19 +2027,6 @@ __clear_cache (char *beg __attribute__((
 
 #endif /* L_clear_cache */
 
-#ifdef L_enable_execute_stack
-/* Attempt to turn on execute permission for the stack.  */
-
-#ifdef ENABLE_EXECUTE_STACK
-  ENABLE_EXECUTE_STACK
-#else
-void
-__enable_execute_stack (void *addr __attribute__((__unused__)))
-{}
-#endif /* ENABLE_EXECUTE_STACK */
-
-#endif /* L_enable_execute_stack */
-
 #ifdef L_trampoline
 
 /* Jump to a trampoline, loading the static chain address.  */
diff --git a/gcc/system.h b/gcc/system.h
--- a/gcc/system.h
+++ b/gcc/system.h
@@ -764,7 +764,7 @@ extern void fancy_abort (const char *, i
 /* Target macros only used for code built for the target, that have
    moved to libgcc-tm.h or have never been present elsewhere.  */
  #pragma GCC poison DECLARE_LIBRARY_RENAMES LIBGCC2_GNU_PREFIX		\
-	MD_UNWIND_SUPPORT
+	MD_UNWIND_SUPPORT ENABLE_EXECUTE_STACK
 
 /* Other obsolete target macros, or macros that used to be in target
    headers and were not used, and may be obsolete or may never have
diff --git a/libgcc/Makefile.in b/libgcc/Makefile.in
--- a/libgcc/Makefile.in
+++ b/libgcc/Makefile.in
@@ -313,9 +313,11 @@ ifneq ($(GCC_EXTRA_PARTS),)
 endif
 endif
 
+LIB2ADD += enable-execute-stack.c
+
 # Library members defined in libgcc2.c.
 lib2funcs = _muldi3 _negdi2 _lshrdi3 _ashldi3 _ashrdi3 _cmpdi2 _ucmpdi2	   \
-	    _clear_cache _enable_execute_stack _trampoline __main _absvsi2 \
+	    _clear_cache _trampoline __main _absvsi2 \
 	    _absvdi2 _addvsi3 _addvdi3 _subvsi3 _subvdi3 _mulvsi3 _mulvdi3 \
 	    _negvsi2 _negvdi2 _ctors _ffssi2 _ffsdi2 _clz _clzsi2 _clzdi2  \
 	    _ctzsi2 _ctzdi2 _popcount_tab _popcountsi2 _popcountdi2	   \
diff --git a/libgcc/config.host b/libgcc/config.host
--- a/libgcc/config.host
+++ b/libgcc/config.host
@@ -44,6 +44,8 @@
 #			The default is ".hidden".
 #  cpu_type		The name of the cpu, if different from the first
 #			chunk of the canonical host name.
+#  enable_execute_stack The name of a source file implementing
+#			__enable_execute_stack.
 #  extra_parts		List of extra object files that should be compiled
 #			for this target machine.  This may be overridden
 #			by setting EXTRA_PARTS in a tmake_file fragment.
@@ -57,6 +59,7 @@
 #			"$cpu_type/t-$cpu_type".
 
 asm_hidden_op=.hidden
+enable_execute_stack=
 extra_parts=
 tmake_file=
 md_unwind_header=no-unwind.h
@@ -203,6 +206,19 @@ case ${host} in
 esac
 
 case ${host} in
+*-*-darwin* | *-*-freebsd* | *-*-netbsd* | *-*-openbsd* | *-*-solaris2* | \
+  alpha*-dec-osf5.1*)
+  enable_execute_stack=enable-execute-stack-mprotect.c
+  ;;
+i[34567]86-*-mingw* | x86_64-*-mingw*)
+  enable_execute_stack=config/i386/enable-execute-stack-mingw32.c
+  ;;
+*)
+  enable_execute_stack=enable-execute-stack-empty.c;
+  ;;
+esac
+
+case ${host} in
 # Support site-specific machine types.
 *local*)
 	rest=`echo ${host} | sed -e "s/$cpu_type-//"`
diff --git a/libgcc/config/i386/enable-execute-stack-mingw32.c b/libgcc/config/i386/enable-execute-stack-mingw32.c
new file mode 100644
--- /dev/null
+++ b/libgcc/config/i386/enable-execute-stack-mingw32.c
@@ -0,0 +1,38 @@
+/* Implement __enable_execute_stack for Windows32.
+   Copyright (C) 2011 Free Software Foundation, Inc.
+
+   This file is part of GCC.
+
+   GCC is free software; you can redistribute it and/or modify it under
+   the terms of the GNU General Public License as published by the Free
+   Software Foundation; either version 3, or (at your option) any later
+   version.
+
+   GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+   WARRANTY; without even the implied warranty of MERCHANTABILITY or
+   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+   for more details.
+
+   Under Section 7 of GPL version 3, you are granted additional
+   permissions described in the GCC Runtime Library Exception, version
+   3.1, as published by the Free Software Foundation.
+
+   You should have received a copy of the GNU General Public License and
+   a copy of the GCC Runtime Library Exception along with this program;
+   see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <windows.h>
+
+extern void __enable_execute_stack (void *);
+
+void
+__enable_execute_stack (void *addr)
+{
+  MEMORY_BASIC_INFORMATION b;
+
+  if (!VirtualQuery (addr, &b, sizeof(b)))
+    abort ();
+  VirtualProtect (b.BaseAddress, b.RegionSize, PAGE_EXECUTE_READWRITE,
+		  &b.Protect);
+}
diff --git a/libgcc/configure.ac b/libgcc/configure.ac
--- a/libgcc/configure.ac
+++ b/libgcc/configure.ac
@@ -278,6 +278,7 @@ AC_SUBST(tmake_file)
 AC_SUBST(cpu_type)
 AC_SUBST(extra_parts)
 AC_SUBST(asm_hidden_op)
+AC_CONFIG_LINKS([enable-execute-stack.c:$enable_execute_stack])
 AC_CONFIG_LINKS([md-unwind-support.h:config/$md_unwind_header])
 
 # We need multilib support.
diff --git a/libgcc/enable-execute-stack-empty.c b/libgcc/enable-execute-stack-empty.c
new file mode 100644
--- /dev/null
+++ b/libgcc/enable-execute-stack-empty.c
@@ -0,0 +1,7 @@
+/* Dummy implementation of __enable_execute_stack.  */
+
+/* Attempt to turn on execute permission for the stack.  */
+void
+__enable_execute_stack (void *addr __attribute__((__unused__)))
+{
+}
diff --git a/libgcc/enable-execute-stack-mprotect.c b/libgcc/enable-execute-stack-mprotect.c
new file mode 100644
--- /dev/null
+++ b/libgcc/enable-execute-stack-mprotect.c
@@ -0,0 +1,119 @@
+/* Implement __enable_execute_stack using mprotect(2).
+   Copyright (C) 2011 Free Software Foundation, Inc.
+
+   This file is part of GCC.
+
+   GCC is free software; you can redistribute it and/or modify it under
+   the terms of the GNU General Public License as published by the Free
+   Software Foundation; either version 3, or (at your option) any later
+   version.
+
+   GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+   WARRANTY; without even the implied warranty of MERCHANTABILITY or
+   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+   for more details.
+
+   Under Section 7 of GPL version 3, you are granted additional
+   permissions described in the GCC Runtime Library Exception, version
+   3.1, as published by the Free Software Foundation.
+
+   You should have received a copy of the GNU General Public License and
+   a copy of the GCC Runtime Library Exception along with this program;
+   see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <sys/mman.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+#define STACK_PROT_RWX (PROT_READ | PROT_WRITE | PROT_EXEC)
+
+static int need_enable_exec_stack;
+
+static void check_enabling (void) __attribute__ ((unused));
+extern void __enable_execute_stack (void *);
+
+#if defined __FreeBSD__
+#include <sys/sysctl.h>
+
+static void __attribute__ ((constructor))
+check_enabling (void)
+{
+  int prot = 0;
+  size_t len = sizeof (prot);
+
+  sysctlbyname ("kern.stackprot", &prot, &len, NULL, 0);
+  if (prot != STACK_PROT_RWX)
+    need_enable_exec_stack = 1;
+}
+#elif defined __sun__ && defined __svr4__
+static void __attribute__ ((constructor))
+check_enabling (void)
+{
+  int prot = (int) sysconf (_SC_STACK_PROT);
+
+  if (prot != STACK_PROT_RWX)
+    need_enable_exec_stack = 1;
+}
+#else
+/* There is no way to query the execute permission of the stack, so
+   we always issue the mprotect() call.  */
+
+static int need_enable_exec_stack = 1;
+#endif
+
+#if defined __NetBSD__
+/* Note that we go out of our way to use namespace-non-invasive calls
+   here.  Unfortunately, there is no libc-internal name for mprotect().  */
+
+#include <sys/sysctl.h>
+
+extern int __sysctl (int *, unsigned int, void *, size_t *, void *, size_t);
+
+static int
+getpagesize (void)
+{
+  static int size;
+
+  if (size == 0)
+    {
+      int mib[2];
+      size_t len;
+
+      mib[0] = CTL_HW;
+      mib[1] = HW_PAGESIZE;
+      len = sizeof (size);
+      (void) __sysctl (mib, 2, &size, &len, NULL, 0);
+    }
+  return size;
+}
+#endif /* __NetBSD__ */
+
+/* Attempt to turn on access permissions for the stack.  Unfortunately it
+   is not possible to make this namespace-clean.*/
+
+void
+__enable_execute_stack (void *addr)
+{
+  if (!need_enable_exec_stack)
+    return;
+  else
+    {
+      static long size, mask;
+
+      if (size == 0) {
+	size = getpagesize ();
+	mask = ~(size - 1);
+      }
+
+      char *page = (char *) (((long) addr) & mask);
+      char *end  = (char *) ((((long) (addr + __TRAMPOLINE_SIZE__)) & mask)
+			     + size);
+
+      if (mprotect (page, end - page, STACK_PROT_RWX) < 0)
+	/* Note that no errors should be emitted by this code; it is
+	   considered dangerous for library calls to send messages to
+	   stdout/stderr.  */
+	abort ();
+    }
+}

-- 
-----------------------------------------------------------------------------
Rainer Orth, Center for Biotechnology, Bielefeld University



More information about the Gcc-patches mailing list