"Joseph S. Myers" <jos...@codesourcery.com> writes:

> On Tue, 7 Jun 2011, Rainer Orth wrote:
>
>> > So my view is that you should define __LIBGCC_TRAMPOLINE_SIZE__, only if 
>> > -fbuilding-libgcc.
>> 
>> I can give it a try if I can figure out how to define -fbuilding-libgcc
>> via the option handling machinery.  I just want to avoid having to
>
> That should be no more than
>
> ; Define extra predefined macros for use in libgcc.
> fbuilding-libgcc
> C ObjC C++ ObjC++ Undocumented Var(flag_building_libgcc)
>
> in c.opt.

Indeed, that did the trick.  The following revised patch has been
bootstrapped without regressions on i386-pc-solaris2.10.  I've already
got build, Darwin and Mingw approval and can commit the osf and solaris
parts on my own.  If the C parts are ok now, I suppose I still need
approval either from the various *BSD maintainers (who haven't chimed in
yet) of from a global reviewer?

Thanks.
        Rainer


2011-05-29  Rainer Orth  <r...@cebitec.uni-bielefeld.de>
            Joseph Myers  <jos...@codesourcery.com>

        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, ENABLE_EXECUTE_STACK): Remove.
        * doc/tm.texi: Regenerate.
        * Makefile.in (LIBGCC2_CFLAGS): Add -fbuilding-libgcc.

        gcc/c-family:
        * c.opt (fbuilding-libgcc): New option.
        * c-cppbuiltin.c (c_cpp_builtins): Define
        __LIBGCC_TRAMPOLINE_SIZE__ if flag_building_libgcc.

        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/Makefile.in b/gcc/Makefile.in
--- a/gcc/Makefile.in
+++ b/gcc/Makefile.in
@@ -722,7 +722,7 @@ LIBGCC2_DEBUG_CFLAGS = -g
 LIBGCC2_CFLAGS = -O2 $(LIBGCC2_INCLUDES) $(GCC_CFLAGS) 
$(TARGET_LIBGCC2_CFLAGS) \
                 $(LIBGCC2_DEBUG_CFLAGS) $(GTHREAD_FLAGS) \
                 -DIN_LIBGCC2 -D__GCC_FLOAT_NOT_NEEDED \
-                -fno-stack-protector \
+                -fbuilding-libgcc -fno-stack-protector \
                 $(INHIBIT_LIBC_CFLAGS)
 
 # Additional options to use when compiling libgcc2.a.
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,12 @@ c_cpp_builtins (cpp_reader *pfile)
       builtin_define_fixed_point_constants ("UTA", "", uta_type_node);
     }
 
+  /* For libgcc-internal use only.  */
+  if (flag_building_libgcc)
+    /* For libgcc enable-execute-stack.c.  */
+    builtin_define_with_int_value ("__LIBGCC_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/c-family/c.opt b/gcc/c-family/c.opt
--- a/gcc/c-family/c.opt
+++ b/gcc/c-family/c.opt
@@ -700,6 +700,10 @@ fasm
 C ObjC C++ ObjC++ Var(flag_no_asm, 0)
 Recognize the \"asm\" keyword
 
+; Define extra predefined macros for use in libgcc.
+fbuilding-libgcc
+C ObjC C++ ObjC++ Undocumented Var(flag_building_libgcc)
+
 fbuiltin
 C ObjC C++ ObjC++ Var(flag_no_builtin, 0)
 Recognize built-in functions
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
@@ -8004,7 +8004,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
@@ -8047,7 +8047,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
@@ -5141,19 +5141,6 @@ typically be a series of @code{asm} stat
 @var{end} are both pointer expressions.
 @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
-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
-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.
-@end defmac
-
 To use a standard subroutine, define the following macro.  In addition,
 you must make sure that the instructions in a trampoline fill an entire
 cache line with identical instructions, or else ensure that the
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 + __LIBGCC_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

Reply via email to