aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRyan Arnold <ryanarn@etna.rchland.ibm.com>2010-11-01 15:38:51 -0500
committerRyan Arnold <ryanarn@etna.rchland.ibm.com>2010-11-01 15:38:51 -0500
commitac02cf3af6f46706a29f21fc762f7099a7a546cc (patch)
tree24db7cec0b9a210d3c7c80716b295a35bd91e720
parentfbe0f55169e6ce50fd2eef1a84f64bbe7aa0592d (diff)
downloadglibc-ac02cf3af6f46706a29f21fc762f7099a7a546cc.tar
glibc-ac02cf3af6f46706a29f21fc762f7099a7a546cc.tar.gz
glibc-ac02cf3af6f46706a29f21fc762f7099a7a546cc.tar.bz2
glibc-ac02cf3af6f46706a29f21fc762f7099a7a546cc.zip
PowerPC64 doesn't need an executable stack and therefore doesn't need
PT_GNU_STACK to make the stack no-exec. This change abstracts the stack permissions settings into a macro defined in a header.
-rw-r--r--ChangeLog32
-rw-r--r--config.h.in3
-rw-r--r--elf/Makefile7
-rw-r--r--elf/dl-load.c6
-rw-r--r--elf/dl-support.c6
-rw-r--r--elf/rtld.c6
-rw-r--r--sysdeps/generic/stackinfo.h16
-rw-r--r--sysdeps/i386/stackinfo.h6
-rw-r--r--sysdeps/ia64/stackinfo.h6
-rw-r--r--sysdeps/powerpc/powerpc64/check-execstack.c195
-rw-r--r--sysdeps/powerpc/powerpc64/configure58
-rw-r--r--sysdeps/powerpc/powerpc64/configure.in19
-rw-r--r--sysdeps/powerpc/stackinfo.h11
-rw-r--r--sysdeps/s390/stackinfo.h6
-rw-r--r--sysdeps/sh/stackinfo.h6
-rw-r--r--sysdeps/sparc/stackinfo.h6
-rw-r--r--sysdeps/x86_64/stackinfo.h6
17 files changed, 359 insertions, 36 deletions
diff --git a/ChangeLog b/ChangeLog
index dd1cbecc0c..93f6ed4ec9 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,35 @@
+2010-10-26 Ryan S. Arnold <rsa@us.ibm.com>
+
+ * config.h.in: Added HAVE_PPC64_PT_GNU_STACK which is set during a
+ configure test to determine whether the the $(CC) compiler defaults to
+ PT_GNU_STACK support for PPC64.
+ * elf/Makefile (($objpfx)check-execstac:): Replaced $(native-compile)
+ with an operation which does the same thing but searches sysdeps/ for
+ the testcase before settling on elf/check-execstack.c. This allows
+ overriding in sysdeps/powerpc/powerpc64/check-execstack.c.
+ * elf/dl-load.c (_dl_map_object_from_fd): Replace PF_R|RF_W|PF_X with
+ _STACK_FLAGS, defined in stackinfo.h.
+ * elf/dl-support.c (_dl_stack_flags): Likewise.
+ * elf/rtld.c (_rtld_global): Likewise.
+ * sysdeps/generic/stackinfo.h: Define _STACK_FLAGS = PF_R|PF_W|PF_X.
+ Define _STACKINFO_H.
+ * sysdeps/i386/stackinfo.h: Include <sysdeps/generic/stackinfo.h> and
+ remove #define _STACKINFO_H.
+ * sysdeps/ia64/stackinfo.h: Likewise.
+ * sysdeps/s390/stackinfo.h: Likewise.
+ * sysdeps/sh/stackinfo.h: Likewise.
+ * sysdeps/sparc/stackinfo.h: Likewise.
+ * sysdeps/x86_64/stackinfo.h: Likewise.
+ * sysdeps/powerpc/stackinfo.h: Define _STACK_FLAGS as PF_R|PF_W, i.e.,
+ nonexecutable, on PowerPC64, but PF_R|PF_W|PF_X on PowerPC32.
+ * sysdeps/powerpc/powerpc64/check-execstack.c: New file which checks
+ the test executable to make sure it doesn't have PT_GNU_STACK set and
+ then checks the executable to see if the mapfile indicates that
+ the [stack] is nonexecutable.
+ * sysdeps/powerpc/powerpc64/configure: Regenerated.
+ * sysdeps/powerpc/powerpc64/configure.in: Added fragment to test for
+ PT_GNU_STACK default in the compiler. It sets HAVE_PPC64_PT_GNU_STACK.
+
2010-10-16 Jakub Jelinek <jakub@redhat.com>
[BZ #3268]
diff --git a/config.h.in b/config.h.in
index 18bf01a38c..6cd3dc1743 100644
--- a/config.h.in
+++ b/config.h.in
@@ -195,6 +195,9 @@
/* Define if your compiler defaults to -msecure-plt mode on ppc. */
#undef HAVE_PPC_SECURE_PLT
+/* Define if your compiler emits a PT_GNU_STACK header for ppc64. */
+#undef HAVE_PPC64_PT_GNU_STACK
+
/* Define if __stack_chk_guard canary should be randomized at program startup. */
#undef ENABLE_STACKGUARD_RANDOMIZE
diff --git a/elf/Makefile b/elf/Makefile
index e600cc3982..50c46c6de2 100644
--- a/elf/Makefile
+++ b/elf/Makefile
@@ -899,8 +899,13 @@ $(objpfx)check-textrel: check-textrel.c
$(native-compile)
check-execstack-CFLAGS = -O -Wall -D_XOPEN_SOURCE=600 -D_BSD_SOURCE -std=gnu99
+# Perform the same operation as $(native-compile) but search sysdeps/ for a
+# matching testcase file before settling for the testcase in elf/.
$(objpfx)check-execstack: check-execstack.c
- $(native-compile)
+ $(make-target-directory)
+ $(patsubst %/,cd % &&,$(objpfx)) \
+ $(BUILD_CC) $($(basename $(<F))-CFLAGS) $(ALL_BUILD_CFLAGS) \
+ $(firstword $(wildcard $(addsuffix /$<,$(addprefix $(shell pwd)/,$(sysdirs)) $(shell pwd)))) -o $(@F)
check-localplt-CFLAGS = -O -Wall -D_GNU_SOURCE -std=gnu99
$(objpfx)check-localplt: check-localplt.c
diff --git a/elf/dl-load.c b/elf/dl-load.c
index 0adddf5aaa..899973c24c 100644
--- a/elf/dl-load.c
+++ b/elf/dl-load.c
@@ -999,8 +999,10 @@ _dl_map_object_from_fd (const char *name, int fd, struct filebuf *fbp,
}
}
- /* Presumed absent PT_GNU_STACK. */
- uint_fast16_t stack_flags = PF_R|PF_W|PF_X;
+ /* On most architectures presume that PT_GNU_STACK is absent and the stack is
+ * executable. Other architectures default to a nonexecutable stack and don't
+ * need PT_GNU_STACK to do so. */
+ uint_fast16_t stack_flags = _STACK_FLAGS;
{
/* Scan the program header table, collecting its load commands. */
diff --git a/elf/dl-support.c b/elf/dl-support.c
index f94d2c4c6e..0e2cccfecd 100644
--- a/elf/dl-support.c
+++ b/elf/dl-support.c
@@ -32,6 +32,7 @@
#include <dl-procinfo.h>
#include <unsecvars.h>
#include <hp-timing.h>
+#include <stackinfo.h>
extern char *__progname;
char **_dl_argv = &__progname; /* This is checked for some error messages. */
@@ -134,8 +135,9 @@ uint64_t _dl_hwcap __attribute__ ((nocommon));
setting _dl_hwcap nonzero below, but we do anyway. */
uint64_t _dl_hwcap_mask __attribute__ ((nocommon));
-/* Prevailing state of the stack, PF_X indicating it's executable. */
-ElfW(Word) _dl_stack_flags = PF_R|PF_W|PF_X;
+/* Prevailing state of the stack. Generally this includes PF_X, indicating it's
+ * executable but this isn't true for all architectures. */
+ElfW(Word) _dl_stack_flags = _STACK_FLAGS;
/* If loading a shared object requires that we make the stack executable
when it was not, we do it by calling this function.
diff --git a/elf/rtld.c b/elf/rtld.c
index d03aa04f33..f03c6c0057 100644
--- a/elf/rtld.c
+++ b/elf/rtld.c
@@ -40,6 +40,7 @@
#include <dl-osinfo.h>
#include <dl-procinfo.h>
#include <tls.h>
+#include <stackinfo.h>
#include <assert.h>
@@ -122,8 +123,9 @@ INTVARDEF(_dl_starting_up)
(except those which cannot be added for some reason). */
struct rtld_global _rtld_global =
{
- /* Default presumption without further information is executable stack. */
- ._dl_stack_flags = PF_R|PF_W|PF_X,
+ /* Generally the default presumption without further information is an
+ * executable stack but this is not true on all architectures. */
+ ._dl_stack_flags = _STACK_FLAGS,
#ifdef _LIBC_REENTRANT
._dl_load_lock = _RTLD_LOCK_RECURSIVE_INITIALIZER,
._dl_load_write_lock = _RTLD_LOCK_RECURSIVE_INITIALIZER,
diff --git a/sysdeps/generic/stackinfo.h b/sysdeps/generic/stackinfo.h
index 7c43801e63..af613f99b1 100644
--- a/sysdeps/generic/stackinfo.h
+++ b/sysdeps/generic/stackinfo.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 1999 Free Software Foundation, Inc.
+/* Copyright (C) 1999, 2010 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -16,6 +16,14 @@
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
-/* This file contains a bit of information about the stack allocation
- of the processor. Since there is no general truth we can't say
- anything here. */
+/* This file contains generic information about the stack allocation. */
+
+#ifndef _STACKINFO_H
+#define _STACKINFO_H 1
+#include <elf.h>
+
+/* Default to an executable stack. PF_X can be overridden if PT_GNU_STACK is
+ * present, but it is presumed absent. */
+#define _STACK_FLAGS (PF_R|PF_W|PF_X)
+
+#endif /* stackinfo.h */
diff --git a/sysdeps/i386/stackinfo.h b/sysdeps/i386/stackinfo.h
index 2530ea7234..38fd1f1cfd 100644
--- a/sysdeps/i386/stackinfo.h
+++ b/sysdeps/i386/stackinfo.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 1999, 2009 Free Software Foundation, Inc.
+/* Copyright (C) 1999, 2009, 2010 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -20,7 +20,9 @@
of the processor. */
#ifndef _STACKINFO_H
-#define _STACKINFO_H 1
+
+/* Pick up the default definition for _STACK_FLAGS and define _STACKINFO_H. */
+#include <sysdeps/generic/stackinfo.h>
/* On x86 the stack grows down. */
#define _STACK_GROWS_DOWN 1
diff --git a/sysdeps/ia64/stackinfo.h b/sysdeps/ia64/stackinfo.h
index b7dc5d91dd..4d3f827b01 100644
--- a/sysdeps/ia64/stackinfo.h
+++ b/sysdeps/ia64/stackinfo.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001 Free Software Foundation, Inc.
+/* Copyright (C) 2001, 2010 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -20,7 +20,9 @@
of the processor. */
#ifndef _STACKINFO_H
-#define _STACKINFO_H 1
+
+/* Pick up the default definition for _STACK_FLAGS and define _STACKINFO_H. */
+#include <sysdeps/generic/stackinfo.h>
/* On IA-64 the stack grows down. The register stack is of no concern
here. */
diff --git a/sysdeps/powerpc/powerpc64/check-execstack.c b/sysdeps/powerpc/powerpc64/check-execstack.c
new file mode 100644
index 0000000000..81947894cc
--- /dev/null
+++ b/sysdeps/powerpc/powerpc64/check-execstack.c
@@ -0,0 +1,195 @@
+/* Verify nonexecutable stack in test app when linked against GLIBC.
+ Copyright (C) 2010 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contribute by Ryan S. Arnold <rsa@us.ibm.com>. 2010.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#if defined HAVE_PPC64_PT_GNU_STACK
+
+/* If the compiler defaults to emitting PT_GNU_STACK for PPC64 then we should
+ * use the standard check-execstack.c test case which checks the shared objects
+ * generated by GLIBC for the GNU_STACK header. */
+#include "../../../elf/check-execstack.c"
+
+#else
+
+/* The original test in elf/check-execstack.c supposedly checks for no-exec
+ * stack but what it really does is check if the compiler used to to build GLIBC
+ * creates a PT_GNU_STACK header in the elf info for each shared object. The
+ * only way to check whether the stack is executable is to build and link an app
+ * with the recently built GLIBC and check the exec bits. */
+
+#include <stdio.h>
+#include <byteswap.h>
+#include <elf.h>
+#include <endian.h>
+#include <linux/limits.h> /* Pick up PATH_MAX. */
+#include <string.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <alloca.h>
+
+/* Macros taken from elf/check-execstack.c because it works. */
+# define BITS 64
+# define E(name) _E (name, BITS)
+# define _E(name, bits) __E (name, bits)
+# define __E(name, bits) Elf##bits##_##name
+# define SWAP(val) \
+ ({ __typeof (val) __res; \
+ if (((ehdr.e_ident[EI_DATA] == ELFDATA2MSB \
+ && BYTE_ORDER == LITTLE_ENDIAN) \
+ || (ehdr.e_ident[EI_DATA] == ELFDATA2LSB \
+ && BYTE_ORDER == BIG_ENDIAN)) \
+ && sizeof (val) != 1) \
+ { \
+ if (sizeof (val) == 2) \
+ __res = bswap_16 (val); \
+ else if (sizeof (val) == 4) \
+ __res = bswap_32 (val); \
+ else \
+ __res = bswap_64 (val); \
+ } \
+ else \
+ __res = (val); \
+ __res; })
+
+/* Make sure this binary doesn't have PT_GNU_STACK set (which it shouldn't if
+ * the configure test which left HAVE_PPC64_PT_GNU_STACK unset was correct) and
+ * make sure that this test case didn't inherit PT_GNU_STACK, and that the stack
+ * defaults to non-executable anyway. */
+
+int
+main (int argc, char *argv[])
+{
+
+ char *argv0 = argv[0]; /* testcase binary. */
+ int fd = open (argv0, O_RDONLY);
+
+ if (fd == -1)
+ {
+ printf("Cannot open file image %s for reading.\n", argv0);
+ }
+
+ /* Read whats is supposed to be the ELF header. Read the initial
+ bytes to determine whether this is a 32 or 64 bit file. */
+ char ident[EI_NIDENT];
+ if (read (fd, ident, EI_NIDENT) != EI_NIDENT)
+ {
+ read_error:
+ printf("%s: read error\n", argv0);
+ close (fd);
+ return 1;
+ }
+
+ if (memcmp (&ident[EI_MAG0], ELFMAG, SELFMAG) != 0)
+ {
+ printf("%s: not an ELF file\n", argv0);
+ close (fd);
+ return 1;
+ }
+
+ /* Only operate on a 64-bit file. */
+ if (ident[EI_CLASS] == ELFCLASS32)
+ {
+ printf("%s is not a 64-bit binary.\n",argv0);
+ close (fd);
+ return 1;
+ }
+
+ /* Now verify that this binary doesn't have a PT_GNU_STACK header. */
+ E(Ehdr) ehdr;
+
+ if (pread (fd, &ehdr, sizeof (ehdr), 0) != sizeof (ehdr))
+ goto read_error;
+
+ const size_t phnum = SWAP (ehdr.e_phnum);
+ const size_t phentsize = SWAP (ehdr.e_phentsize);
+
+ /* Read the program header. */
+ E(Phdr) *phdr = alloca (phentsize * phnum);
+ if (pread (fd, phdr, phentsize * phnum, SWAP (ehdr.e_phoff))
+ != phentsize * phnum)
+ goto read_error;
+
+ /* Search for an unwanted PT_GNU_STACK entry. */
+ for (size_t cnt = 0; cnt < phnum; ++cnt)
+ if (SWAP (phdr[cnt].p_type) == PT_GNU_STACK)
+ {
+ printf("%s: Found unwanted PT_GNU_STACK header.\n", argv0);
+ close (fd);
+ return 1;
+ }
+
+ close(fd);
+
+ /* Now make sure the stack is marked non-executable by reading
+ * /proc/self/maps and looking for the memory permissions on the [stack]
+ * region. */
+
+ FILE *mapfd = fopen ("/proc/self/maps", "r");
+ if (mapfd == NULL)
+ {
+ /* We don't have a solution for older systems that don't support
+ * /proc/self/maps. Just return a false success since the situation is
+ * kind of ridiculous (really old kernel + glibc 2.13+). */
+ printf("fopen of /proc/self/maps failed.\n");
+ return 0;
+ }
+
+ char line[PATH_MAX + 128];
+ const char delimiters[] = " ";
+ char *token;
+ const char stack[] = "[stack]";
+ while ((fgets(line, PATH_MAX + 128, mapfd)) != NULL)
+ {
+ char *perms = NULL;
+ int field = 0;
+ token = strtok(line,delimiters);
+ while(token != NULL) {
+ if (field == 1) /* The second field is the perms field. */
+ perms = token; /* Save this until we find [stack]. */
+ if (field == 5) /* The sixth field is the pathname field. */
+ {
+ /* If we find "[stack]" as the pathname check the permissions. */
+ if (!strncmp(stack,token,strlen(stack)))
+ {
+ if (perms[2] == 'x')
+ {
+ printf("found executable stack for %s.\n", argv0);
+ printf("%s %s %s\n",line,perms,token);
+ fclose(mapfd);
+ return 1;
+ }
+ else
+ {
+ printf("found noexec stack in:\n");
+ printf("%s %s %s\n",line,perms,token);
+ fclose(mapfd);
+ return 0;
+ }
+ }
+ break;
+ }
+ token = strtok(NULL,delimiters);
+ field++;
+ }
+ }
+ printf("didn't find [stack] pathname for %s in /proc/self/maps.\n", argv0);
+ fclose(mapfd);
+ return 1;
+}
+#endif
diff --git a/sysdeps/powerpc/powerpc64/configure b/sysdeps/powerpc/powerpc64/configure
index a9b6722c11..8976d34ca0 100644
--- a/sysdeps/powerpc/powerpc64/configure
+++ b/sysdeps/powerpc/powerpc64/configure
@@ -3,10 +3,10 @@
# The Aix ld uses global .symbol_names instead of symbol_names
# and unfortunately early Linux PPC64 linkers use it as well.
-{ $as_echo "$as_me:$LINENO: checking for support for omitting dot symbols" >&5
-$as_echo_n "checking for support for omitting dot symbols... " >&6; }
+{ echo "$as_me:$LINENO: checking for support for omitting dot symbols" >&5
+echo $ECHO_N "checking for support for omitting dot symbols... $ECHO_C" >&6; }
if test "${libc_cv_omit_dot_syms+set}" = set; then
- $as_echo_n "(cached) " >&6
+ echo $ECHO_N "(cached) $ECHO_C" >&6
else
libc_cv_omit_dot_syms=no
echo 'void foo (void) {}' > conftest.c
@@ -14,7 +14,7 @@ if { ac_try='${CC-cc} $CFLAGS $CPPFLAGS -S conftest.c -o conftest.s 1>&5'
{ (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
(eval $ac_try) 2>&5
ac_status=$?
- $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
(exit $ac_status); }; }; then
if grep -w '\.foo' conftest.s > /dev/null; then
:
@@ -25,8 +25,8 @@ fi
rm -f conftest.c conftest.s
fi
-{ $as_echo "$as_me:$LINENO: result: $libc_cv_omit_dot_syms" >&5
-$as_echo "$libc_cv_omit_dot_syms" >&6; }
+{ echo "$as_me:$LINENO: result: $libc_cv_omit_dot_syms" >&5
+echo "${ECHO_T}$libc_cv_omit_dot_syms" >&6; }
if test x$libc_cv_omit_dot_syms != xyes; then
cat >>confdefs.h <<\_ACEOF
#define HAVE_ASM_GLOBAL_DOT_NAME 1
@@ -34,10 +34,10 @@ _ACEOF
fi
-{ $as_echo "$as_me:$LINENO: checking for linker support for overlapping .opd entries" >&5
-$as_echo_n "checking for linker support for overlapping .opd entries... " >&6; }
+{ echo "$as_me:$LINENO: checking for linker support for overlapping .opd entries" >&5
+echo $ECHO_N "checking for linker support for overlapping .opd entries... $ECHO_C" >&6; }
if test "${libc_cv_overlapping_opd+set}" = set; then
- $as_echo_n "(cached) " >&6
+ echo $ECHO_N "(cached) $ECHO_C" >&6
else
libc_cv_overlapping_opd=no
echo 'void foo (void) {}' > conftest.c
@@ -45,7 +45,7 @@ if { ac_try='${CC-cc} $CFLAGS $CPPFLAGS -S conftest.c -o conftest.s 1>&5'
{ (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
(eval $ac_try) 2>&5
ac_status=$?
- $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
(exit $ac_status); }; }; then
if grep '\.TOC\.@tocbase' conftest.s > /dev/null; then
if grep '\.TOC\.@tocbase[ ]*,[ ]*0' conftest.s > /dev/null; then
@@ -58,11 +58,45 @@ fi
rm -f conftest.c conftest.s
fi
-{ $as_echo "$as_me:$LINENO: result: $libc_cv_overlapping_opd" >&5
-$as_echo "$libc_cv_overlapping_opd" >&6; }
+{ echo "$as_me:$LINENO: result: $libc_cv_overlapping_opd" >&5
+echo "${ECHO_T}$libc_cv_overlapping_opd" >&6; }
if test x$libc_cv_overlapping_opd = xyes; then
cat >>confdefs.h <<\_ACEOF
#define USE_PPC64_OVERLAPPING_OPD 1
_ACEOF
fi
+
+# Some compilers have been configured to emit PT_GNU_STACK on PowerPC64 even
+# though this isn't necessary. If it is present then which check-execstack is
+# tested should be changed.
+{ echo "$as_me:$LINENO: checking if PT_GNU_STACK ELF program header is emitted by the compiler on PowerPC64" >&5
+echo $ECHO_N "checking if PT_GNU_STACK ELF program header is emitted by the compiler on PowerPC64... $ECHO_C" >&6; }
+if test "${libc_cv_ppc64_pt_gnu_stack+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ echo 'int main (void) { return 0; }' > conftest.c
+libc_cv_ppc64_pt_gnu_stack=no
+ if { ac_try='${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS -o conftest
+ conftest.c 1>&5'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }
+ then
+ if readelf -l conftest | fgrep GNU_STACK > /dev/null; then
+ libc_cv_ppc64_pt_gnu_stack=yes
+ fi
+ fi
+ rm -f conftest*
+fi
+{ echo "$as_me:$LINENO: result: $libc_cv_ppc64_pt_gnu_stack" >&5
+echo "${ECHO_T}$libc_cv_ppc64_pt_gnu_stack" >&6; }
+#AC_SUBST(libc_cv_ppc64_pt_gnu_stack)
+if test $libc_cv_ppc64_pt_gnu_stack = yes; then
+ cat >>confdefs.h <<\_ACEOF
+#define HAVE_PPC64_PT_GNU_STACK 1
+_ACEOF
+
+fi
diff --git a/sysdeps/powerpc/powerpc64/configure.in b/sysdeps/powerpc/powerpc64/configure.in
index 67aac663d8..9c236adbc4 100644
--- a/sysdeps/powerpc/powerpc64/configure.in
+++ b/sysdeps/powerpc/powerpc64/configure.in
@@ -40,3 +40,22 @@ rm -f conftest.c conftest.s
if test x$libc_cv_overlapping_opd = xyes; then
AC_DEFINE(USE_PPC64_OVERLAPPING_OPD)
fi
+
+# Some compilers have been configured to emit PT_GNU_STACK on PowerPC64 even
+# though this isn't necessary. If it is present then which check-execstack is
+# tested should be changed.
+AC_CACHE_CHECK(if PT_GNU_STACK ELF program header is emitted by the compiler on PowerPC64, libc_cv_ppc64_pt_gnu_stack, [dnl
+echo 'int main (void) { return 0; }' > conftest.c
+libc_cv_ppc64_pt_gnu_stack=no
+ if AC_TRY_COMMAND([${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS -o conftest
+ conftest.c 1>&AS_MESSAGE_LOG_FD])
+ then
+ if readelf -l conftest | fgrep GNU_STACK > /dev/null; then
+ libc_cv_ppc64_pt_gnu_stack=yes
+ fi
+ fi
+ rm -f conftest*])
+#AC_SUBST(libc_cv_ppc64_pt_gnu_stack)
+if test $libc_cv_ppc64_pt_gnu_stack = yes; then
+ AC_DEFINE(HAVE_PPC64_PT_GNU_STACK)
+fi
diff --git a/sysdeps/powerpc/stackinfo.h b/sysdeps/powerpc/stackinfo.h
index 839758a4e3..c46ec7cc52 100644
--- a/sysdeps/powerpc/stackinfo.h
+++ b/sysdeps/powerpc/stackinfo.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 1999 Free Software Foundation, Inc.
+/* Copyright (C) 1999, 2010 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -25,4 +25,13 @@
/* On PPC the stack grows down. */
#define _STACK_GROWS_DOWN 1
+#if __WORDSIZE == 64
+/* PPC64 doesn't need an executable stack and doesn't need PT_GNU_STACK
+ * to make the stack nonexecutable. */
+# define _STACK_FLAGS (PF_R|PF_W)
+#else
+/* PF_X can be overridden if PT_GNU_STACK is present but is presumed absent. */
+# define _STACK_FLAGS (PF_R|PF_W|PF_X)
+#endif
+
#endif /* stackinfo.h */
diff --git a/sysdeps/s390/stackinfo.h b/sysdeps/s390/stackinfo.h
index 7e09c85b9b..b41a6f487b 100644
--- a/sysdeps/s390/stackinfo.h
+++ b/sysdeps/s390/stackinfo.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2000 Free Software Foundation, Inc.
+/* Copyright (C) 2000, 2010 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -20,7 +20,9 @@
of the processor. */
#ifndef _STACKINFO_H
-#define _STACKINFO_H 1
+
+/* Pick up the default definition for _STACK_FLAGS and define _STACKINFO_H. */
+#include <sysdeps/generic/stackinfo.h>
/* On s390 the stack grows down. */
#define _STACK_GROWS_DOWN 1
diff --git a/sysdeps/sh/stackinfo.h b/sysdeps/sh/stackinfo.h
index e65338f256..4b0eb9599d 100644
--- a/sysdeps/sh/stackinfo.h
+++ b/sysdeps/sh/stackinfo.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001 Free Software Foundation, Inc.
+/* Copyright (C) 2001, 2010 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -20,7 +20,9 @@
of the processor. */
#ifndef _STACKINFO_H
-#define _STACKINFO_H 1
+
+/* Pick up the default definition for _STACK_FLAGS and define _STACKINFO_H. */
+#include <sysdeps/generic/stackinfo.h>
/* On SH the stack grows down. */
#define _STACK_GROWS_DOWN 1
diff --git a/sysdeps/sparc/stackinfo.h b/sysdeps/sparc/stackinfo.h
index fd34e2deb0..5f02a2b04f 100644
--- a/sysdeps/sparc/stackinfo.h
+++ b/sysdeps/sparc/stackinfo.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001 Free Software Foundation, Inc.
+/* Copyright (C) 2001, 2010 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -20,7 +20,9 @@
of the processor. */
#ifndef _STACKINFO_H
-#define _STACKINFO_H 1
+
+/* Pick up the default definition for _STACK_FLAGS and define _STACKINFO_H. */
+#include <sysdeps/generic/stackinfo.h>
/* On sparc the stack grows down. */
#define _STACK_GROWS_DOWN 1
diff --git a/sysdeps/x86_64/stackinfo.h b/sysdeps/x86_64/stackinfo.h
index b11849d9ab..3f09019658 100644
--- a/sysdeps/x86_64/stackinfo.h
+++ b/sysdeps/x86_64/stackinfo.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001, 2009 Free Software Foundation, Inc.
+/* Copyright (C) 2001, 2009, 2010 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -20,7 +20,9 @@
of the processor. */
#ifndef _STACKINFO_H
-#define _STACKINFO_H 1
+
+/* Pick up the default definition for _STACK_FLAGS and define _STACKINFO_H. */
+#include <sysdeps/generic/stackinfo.h>
/* On x86_64 the stack grows down. */
#define _STACK_GROWS_DOWN 1