Beyond the reasons for the bundled Solaris CRTs already cited in https://gcc.gnu.org/ml/gcc-patches/2015-09/msg01638.html
they need to be PIC to support position independent executables (PIE). While linker support for PIE has existed in Solaris ld since at least Solaris 11.2 and GNU ld has just gotten the last (mostly cosmetic) bit for binutils 2.26, there were no usable CRTs before. Now those pieces are in place, this patch enables PIE if the necessary support (linker and CRTs) is detected. It's mostly straightforward, adapting specs changes in gnu-user.h and allowing for differences in linker options. crtp.o, crtpg.o, and gmon.o are now compiled as PIC to also work with PIE. I don't thing there's any point to have separate PIC and non-PIC versions here. During early development of the patch, I found that gmon.c includes the trailing NULs in error messages it prints. Now corrected, though not strictly related to the patch. Contrary to other targets, where -pie seems to be silently ignored if PIE support is missing, I've decided to have gcc error out on Solaris in this situation. This also allows to easily distinguish between configurations with and without PIE support in the testsuite. Tested on i386-pc-solaris2.1[012] and sparc-sun-solaris2.1[012] with both as/ld and gas/gld, and x86_64-unknown-linux-gnu. I've also bootstrapped on i386-pc-solaris2.12 and sparc-sun-solaris2.12 with --enable-default-pie. There are a couple of new failures, but they also occur on Linux/x86_64 and I've already filed PRs for (most of?) them. Again, perhaps with exception of the obvious hunk in gcc.c, this patch is purely Solaris-specific, so I'll commit it in a couple of days. I'd also like to backport it to the gcc-5 branch after some soak time on mainline. Rainer 2015-02-10 Rainer Orth <r...@cebitec.uni-bielefeld.de> gcc/testsuite: * lib/target-supports.exp (check_effective_target_pie): Check for PIE support on Solaris 11.x and 12. libgcc: * config.host (*-*-solaris2*): Add t-crtstuff-pic to tmake_file. Add crtbeginS.o, crtendS.o to extra_parts if libgcc_cv_solaris_crts. * config/sol2/gmon.c: (monstartup): Don't write trailing NUL of messages. (internal_mcount): Likewise. * config/sol2/t-sol2 (crtp.o, crtpg.o, gmon.o): Compile with crt_compile, add CRTSTUFF_T_CFLAGS_S. gcc: * configure.ac (gcc_cv_ld_pie): Check for -type pie on Solaris 11.x and 12. * configure: Regenerate. * gcc.c (LD_PIE_SPEC): Allow redefinition. * config/sol2.h (STARTFILE_CRTBEGIN_SPEC): Define. (STARTFILE_SPEC): Use it. (ENDFILE_CRTEND_SPEC): Define. (ENDFILE_SPEC): Use it and ENDFILE_ARCH_SPEC. (SUBTARGET_EXTRA_SPECS): Add STARTFILE_CRTBEGIN_SPEC, ENDFILE_ARCH_SPEC, ENDFILE_CRTEND_SPEC. [HAVE_LD_PIE && HAVE_SOLARIS_CRTS] (LD_PIE_SPEC): Define. (!(HAVE_LD_PIE && HAVE_SOLARIS_CRTS)] (LINK_PIE_SPEC): Define. * config/i386/sol2.h (ENDFILE_SPEC): Remove. (ENDFILE_ARCH_SPEC): Define. * config/sparc/sol2.h (ENDFILE_ARCH_SPEC): Define.
# HG changeset patch # Parent 0b3199bc12392bf6e18f8e0824ae4d8d98439b6f # Parent f47ad8903880217392a02a0126dcd9b68264c5b7 Support PIE on Solaris 12 diff --git a/gcc/config/i386/sol2.h b/gcc/config/i386/sol2.h --- a/gcc/config/i386/sol2.h +++ b/gcc/config/i386/sol2.h @@ -86,13 +86,10 @@ along with GCC; see the file COPYING3. #endif #endif -#undef ENDFILE_SPEC -#define ENDFILE_SPEC \ - "%{Ofast|ffast-math|funsafe-math-optimizations:crtfastmath.o%s} \ - %{mpc32:crtprec32.o%s} \ +#define ENDFILE_ARCH_SPEC \ + "%{mpc32:crtprec32.o%s} \ %{mpc64:crtprec64.o%s} \ - %{mpc80:crtprec80.o%s} \ - crtend.o%s crtn.o%s" + %{mpc80:crtprec80.o%s}" #define SUBTARGET_CPU_EXTRA_SPECS \ { "cpp_subtarget", CPP_SUBTARGET_SPEC }, \ diff --git a/gcc/config/sol2.h b/gcc/config/sol2.h --- a/gcc/config/sol2.h +++ b/gcc/config/sol2.h @@ -154,6 +154,14 @@ along with GCC; see the file COPYING3. #define STARTFILE_ARCH_SPEC "%{ansi:values-Xc.o%s} \ %{!ansi:values-Xa.o%s}" +#if defined(HAVE_LD_PIE) && defined(HAVE_SOLARIS_CRTS) +#define STARTFILE_CRTBEGIN_SPEC "%{shared:crtbeginS.o%s} \ + %{" PIE_SPEC ":crtbeginS.o%s} \ + %{" NO_PIE_SPEC ":crtbegin.o%s}" +#else +#define STARTFILE_CRTBEGIN_SPEC "crtbegin.o%s" +#endif + /* We don't use the standard svr4 STARTFILE_SPEC because it's wrong for us. */ #undef STARTFILE_SPEC #ifdef HAVE_SOLARIS_CRTS @@ -164,21 +172,27 @@ along with GCC; see the file COPYING3. %{p:%e-p is not supported; \ pg:crtpg.o%s gmon.o%s; \ :crtp.o%s}}} \ - crti.o%s %(startfile_arch) \ - crtbegin.o%s" + crti.o%s %(startfile_arch) %(startfile_crtbegin)" #else #define STARTFILE_SPEC "%{!shared:%{!symbolic: \ %{p:mcrt1.o%s; \ pg:gcrt1.o%s gmon.o%s; \ :crt1.o%s}}} \ - crti.o%s %(startfile_arch) \ - crtbegin.o%s" + crti.o%s %(startfile_arch) %(startfile_crtbegin)" +#endif + +#if defined(HAVE_LD_PIE) && defined(HAVE_SOLARIS_CRTS) +#define ENDFILE_CRTEND_SPEC "%{shared:crtendS.o%s;: \ + %{" PIE_SPEC ":crtendS.o%s} \ + %{" NO_PIE_SPEC ":crtend.o%s}}" +#else +#define ENDFILE_CRTEND_SPEC "crtend.o%s" #endif #undef ENDFILE_SPEC #define ENDFILE_SPEC \ "%{Ofast|ffast-math|funsafe-math-optimizations:crtfastmath.o%s} \ - crtend.o%s crtn.o%s" + %(endfile_arch) %(endfile_crtend) crtn.o%s" #undef LINK_ARCH32_SPEC_BASE #define LINK_ARCH32_SPEC_BASE \ @@ -251,11 +265,14 @@ along with GCC; see the file COPYING3. #undef SUBTARGET_EXTRA_SPECS #define SUBTARGET_EXTRA_SPECS \ - { "startfile_arch", STARTFILE_ARCH_SPEC }, \ - { "link_arch32", LINK_ARCH32_SPEC }, \ - { "link_arch64", LINK_ARCH64_SPEC }, \ - { "link_arch_default", LINK_ARCH_DEFAULT_SPEC }, \ - { "link_arch", LINK_ARCH_SPEC }, \ + { "startfile_arch", STARTFILE_ARCH_SPEC }, \ + { "startfile_crtbegin", STARTFILE_CRTBEGIN_SPEC }, \ + { "link_arch32", LINK_ARCH32_SPEC }, \ + { "link_arch64", LINK_ARCH64_SPEC }, \ + { "link_arch_default", LINK_ARCH_DEFAULT_SPEC }, \ + { "link_arch", LINK_ARCH_SPEC }, \ + { "endfile_arch", ENDFILE_ARCH_SPEC }, \ + { "endfile_crtend", ENDFILE_CRTEND_SPEC }, \ SUBTARGET_CPU_EXTRA_SPECS /* C++11 programs need -lrt for nanosleep. */ @@ -310,6 +327,20 @@ along with GCC; see the file COPYING3. #endif /* HAVE_LD_EH_FRAME && TARGET_DL_ITERATE_PHDR */ #endif +#if defined(HAVE_LD_PIE) && defined(HAVE_SOLARIS_CRTS) +#ifdef USE_GLD +/* Assert -z text by default to match Solaris ld. */ +#define LD_PIE_SPEC "-pie %{!mimpure-text:-z text}" +#else +/* Solaris ld needs -z type=pie instead of -pie. */ +#define LD_PIE_SPEC "-z type=pie %{mimpure-text:-z textoff}" +#endif +#else +/* Error out if some part of PIE support is missing. */ +#define LINK_PIE_SPEC \ + "%{no-pie:} %{pie:%e-pie is not supported in this configuration} " +#endif + /* collect2.c can only parse GNU nm -n output. Solaris nm needs -png to produce the same format. */ #define NM_FLAGS "-png" diff --git a/gcc/config/sparc/sol2.h b/gcc/config/sparc/sol2.h --- a/gcc/config/sparc/sol2.h +++ b/gcc/config/sparc/sol2.h @@ -280,6 +280,8 @@ extern const char *host_detect_local_cpu #define SUBTARGET_CPU_EXTRA_SPECS +#define ENDFILE_ARCH_SPEC "" + /* Register the Solaris-specific #pragma directives. */ diff --git a/gcc/configure.ac b/gcc/configure.ac --- a/gcc/configure.ac +++ b/gcc/configure.ac @@ -4756,10 +4756,19 @@ if test $in_tree_ld = yes ; then gcc_cv_ld_pie=yes fi elif test x$gcc_cv_ld != x; then - # Check if linker supports -pie option - if $gcc_cv_ld --help 2>/dev/null | grep -- -pie > /dev/null; then - gcc_cv_ld_pie=yes + # Check if linker supports -pie option + if $gcc_cv_ld --help 2>/dev/null | grep -- -pie > /dev/null; then + gcc_cv_ld_pie=yes + else + case "$target" in + *-*-solaris2.1[[1-9]]*) + # Solaris 11.x and Solaris 12 added PIE support. + if $gcc_cv_ld -z help 2>&1 | grep -- type.*pie > /dev/null; then + gcc_cv_ld_pie=yes fi + ;; + esac + fi fi if test x"$gcc_cv_ld_pie" = xyes; then AC_DEFINE(HAVE_LD_PIE, 1, diff --git a/gcc/gcc.c b/gcc/gcc.c --- a/gcc/gcc.c +++ b/gcc/gcc.c @@ -908,7 +908,9 @@ proper position among the other output f #ifndef LINK_PIE_SPEC #ifdef HAVE_LD_PIE +#ifndef LD_PIE_SPEC #define LD_PIE_SPEC "-pie" +#endif #else #define LD_PIE_SPEC "" #endif diff --git a/gcc/testsuite/lib/target-supports.exp b/gcc/testsuite/lib/target-supports.exp --- a/gcc/testsuite/lib/target-supports.exp +++ b/gcc/testsuite/lib/target-supports.exp @@ -1046,6 +1046,13 @@ proc check_effective_target_pie { } { || [istarget *-*-gnu*] } { return 1; } + if { [istarget *-*-solaris2.1\[1-9\]*] } { + # Full PIE support was added in Solaris 11.x and Solaris 12, but gcc + # errors out if missing, so check for that. + return [check_no_compiler_messages pie executable { + int main (void) { return 0; } + } "-pie -fpie"] + } return 0 } diff --git a/libgcc/config.host b/libgcc/config.host --- a/libgcc/config.host +++ b/libgcc/config.host @@ -267,7 +267,7 @@ case ${host} in *-*-solaris2*) # Unless linker support and dl_iterate_phdr are present, # unwind-dw2-fde-dip.c automatically falls back to unwind-dw2-fde.c. - tmake_file="$tmake_file sol2/t-sol2 t-eh-dw2-dip t-libgcc-pic t-slibgcc t-slibgcc-elf-ver" + tmake_file="$tmake_file sol2/t-sol2 t-eh-dw2-dip t-crtstuff-pic t-libgcc-pic t-slibgcc t-slibgcc-elf-ver" if test $with_gnu_ld = yes; then tmake_file="$tmake_file t-slibgcc-gld" else @@ -280,6 +280,8 @@ case ${host} in # Solaris 11.x and 12 provide crt1.o, crti.o, and crtn.o as part of the # base system. crtp.o and crtpg.o implement the compiler-dependent parts. extra_parts="$extra_parts crtp.o crtpg.o" + # If the Solaris CRTs are present, both ld and gld will have PIE support. + extra_parts="$extra_parts crtbeginS.o crtendS.o" else case ${host} in i?86-*-solaris2.1[0-9]* | x86_64-*-solaris2.1[0-9]*) diff --git a/libgcc/config/sol2/gmon.c b/libgcc/config/sol2/gmon.c --- a/libgcc/config/sol2/gmon.c +++ b/libgcc/config/sol2/gmon.c @@ -114,12 +114,12 @@ monstartup (char *lowpc, char *highpc) monsize = (s_textsize / HISTFRACTION) + sizeof (struct phdr); buffer = sbrk (monsize); if (buffer == (void *) -1) { - write (STDERR_FILENO, MSG, sizeof (MSG)); + write (STDERR_FILENO, MSG, sizeof (MSG) - 1); return; } froms = sbrk (s_textsize / HASHFRACTION); if (froms == (void *) -1) { - write (STDERR_FILENO, MSG, sizeof (MSG)); + write (STDERR_FILENO, MSG, sizeof (MSG) - 1); froms = NULL; return; } @@ -131,7 +131,7 @@ monstartup (char *lowpc, char *highpc) } tos = sbrk (tolimit * sizeof (struct tostruct)); if (tos == (void *) -1) { - write (STDERR_FILENO, MSG, sizeof (MSG)); + write (STDERR_FILENO, MSG, sizeof (MSG) - 1); froms = NULL; tos = NULL; return; @@ -429,7 +429,7 @@ internal_mcount (char *selfpc, unsigned profiling++; #define TOLIMIT "mcount: tos overflow\n" - write (STDERR_FILENO, TOLIMIT, sizeof (TOLIMIT)); + write (STDERR_FILENO, TOLIMIT, sizeof (TOLIMIT) - 1); goto out; } diff --git a/libgcc/config/sol2/t-sol2 b/libgcc/config/sol2/t-sol2 --- a/libgcc/config/sol2/t-sol2 +++ b/libgcc/config/sol2/t-sol2 @@ -18,13 +18,13 @@ # crtp, crtpg build rules crtp.o: $(srcdir)/config/sol2/crtp.c - $(gcc_compile) -c $< + $(crt_compile) $(CRTSTUFF_T_CFLAGS_S) -c $< crtpg.o: $(srcdir)/config/sol2/crtpg.c - $(gcc_compile) -c $< + $(crt_compile) $(CRTSTUFF_T_CFLAGS_S) -c $< # gmon build rule gmon.o: $(srcdir)/config/sol2/gmon.c - $(gcc_compile) -c $< + $(crt_compile) $(CRTSTUFF_T_CFLAGS_S) -c $< # Assemble startup files. crt1.o: $(srcdir)/config/$(cpu_type)/sol2-c1.S
-- ----------------------------------------------------------------------------- Rainer Orth, Center for Biotechnology, Bielefeld University