From: Rainer Orth Date: Thu, 24 Sep 2015 08:51:39 +0000 (+0000) Subject: Use CRTs provided by Solaris X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=2d11044217edd9168eafea1c8c60603f87b0e00d;p=gcc.git Use CRTs provided by Solaris gcc: * configure.ac (gcc_cv_solaris_crts): New test. * configure. Regenerate. * config.in: Regenerate. * config/sol2.h (STARTFILE_SPEC): Simplify, provide HAVE_SOLARIS_CRTS variant. libgcc: * configure.ac (libgcc_cv_solaris_crts): New test. * configure: Regenerate. * config.in: Regenerate. * config/sol2/crtp.c, config/sol2/crtpg.c: New files. * config/gmon-sol2.c: Rename to ... * config/sol2/gmon.c: ... this. Include auto-target.h. (internal_mcount): Wrap setup handling in !HAVE_SOLARIS_CRTS. * config/t-sol2: Rename to ... * config/sol2/t-sol2: ... this. (gmon.o): Reflect renaming. (crtp.o, crtpg.o): New rules. * config.host (*-*-solaris2*): Reflect renaming. Use system CRTs if present. Remove default CRT case. From-SVN: r228077 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index e3120f30d20..e549506e6a9 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,11 @@ +2015-09-24 Rainer Orth + + * configure.ac (gcc_cv_solaris_crts): New test. + * configure. Regenerate. + * config.in: Regenerate. + * config/sol2.h (STARTFILE_SPEC): Simplify, provide + HAVE_SOLARIS_CRTS variant. + 2015-09-24 Kyrylo Tkachov * tree-inline.h (count_insns_seq): Delete prototype. diff --git a/gcc/config.in b/gcc/config.in index c5c1be4e488..a1987cc9bd9 100644 --- a/gcc/config.in +++ b/gcc/config.in @@ -1631,6 +1631,12 @@ #endif +/* Define if the system-provided CRTs are present on Solaris. */ +#ifndef USED_FOR_TARGET +#undef HAVE_SOLARIS_CRTS +#endif + + /* Define to 1 if you have the header file. */ #ifndef USED_FOR_TARGET #undef HAVE_STDDEF_H diff --git a/gcc/config/sol2.h b/gcc/config/sol2.h index adf6f3b9fbe..d31a2513376 100644 --- a/gcc/config/sol2.h +++ b/gcc/config/sol2.h @@ -156,14 +156,24 @@ along with GCC; see the file COPYING3. If not see /* We don't use the standard svr4 STARTFILE_SPEC because it's wrong for us. */ #undef STARTFILE_SPEC -#define STARTFILE_SPEC "%{!shared: \ - %{!symbolic: \ - %{p:mcrt1.o%s} \ - %{!p: \ - %{pg:gcrt1.o%s gmon.o%s} \ - %{!pg:crt1.o%s}}}} \ +#ifdef HAVE_SOLARIS_CRTS +/* Since Solaris 11.x and Solaris 12, the OS delivers crt1.o, crti.o, and + crtn.o, with a hook for compiler-dependent stuff like profile handling. */ +#define STARTFILE_SPEC "%{!shared:%{!symbolic: \ + crt1.o%s \ + %{p:%e-p is not supported; \ + pg:crtpg.o%s gmon.o%s; \ + :crtp.o%s}}} \ crti.o%s %(startfile_arch) \ crtbegin.o%s" +#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" +#endif #undef ENDFILE_SPEC #define ENDFILE_SPEC \ diff --git a/gcc/configure b/gcc/configure index 7493c800f48..a32bb64948d 100755 --- a/gcc/configure +++ b/gcc/configure @@ -28025,6 +28025,44 @@ $as_echo "#define HAVE_LD_SYSROOT 1" >>confdefs.h fi +case $target in +*-*-solaris2*) + # Check for system-provided CRTs on Solaris 11.x and Solaris 12. + { $as_echo "$as_me:${as_lineno-$LINENO}: checking system-provided CRTs on Solaris" >&5 +$as_echo_n "checking system-provided CRTs on Solaris... " >&6; } +if test "${gcc_cv_solaris_crts+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + gcc_cv_solaris_crts=no + if test x$host != x$target; then + if test "x$with_sysroot" = xyes; then + target_sysroot="${test_exec_prefix}/${target_noncanonical}/sys-root" + else + target_sysroot="${with_sysroot}" + fi + fi + target_libdir="$target_sysroot/usr/lib" + # At the time they were added, gcrt1.o became a symlink for backwards + # compatibility on x86, while crt1.o was added on sparc, so check for that. + case $target in + i?86-*-solaris2* | x86_64-*-solaris2*) + if test -h "$target_libdir/gcrt1.o"; then gcc_cv_solaris_crts=yes; fi + ;; + sparc*-*-solaris2*) + if test -f "$target_libdir/crt1.o"; then gcc_cv_solaris_crts=yes; fi + ;; + esac +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_solaris_crts" >&5 +$as_echo "$gcc_cv_solaris_crts" >&6; } + ;; +esac +if test x$gcc_cv_solaris_crts = xyes; then + +$as_echo "#define HAVE_SOLARIS_CRTS 1" >>confdefs.h + +fi + # Test for stack protector support in target C library. { $as_echo "$as_me:${as_lineno-$LINENO}: checking __stack_chk_fail in target C library" >&5 $as_echo_n "checking __stack_chk_fail in target C library... " >&6; } diff --git a/gcc/configure.ac b/gcc/configure.ac index 9d1f6f18eba..4f8a44e51f1 100644 --- a/gcc/configure.ac +++ b/gcc/configure.ac @@ -5281,6 +5281,37 @@ if test x"$gcc_cv_ld_sysroot" = xyes; then [Define if your linker supports --sysroot.]) fi +case $target in +*-*-solaris2*) + # Check for system-provided CRTs on Solaris 11.x and Solaris 12. + AC_CACHE_CHECK([system-provided CRTs on Solaris], + gcc_cv_solaris_crts, + [gcc_cv_solaris_crts=no + if test x$host != x$target; then + if test "x$with_sysroot" = xyes; then + target_sysroot="${test_exec_prefix}/${target_noncanonical}/sys-root" + else + target_sysroot="${with_sysroot}" + fi + fi + target_libdir="$target_sysroot/usr/lib" + # At the time they were added, gcrt1.o became a symlink for backwards + # compatibility on x86, while crt1.o was added on sparc, so check for that. + case $target in + i?86-*-solaris2* | x86_64-*-solaris2*) + if test -h "$target_libdir/gcrt1.o"; then gcc_cv_solaris_crts=yes; fi + ;; + sparc*-*-solaris2*) + if test -f "$target_libdir/crt1.o"; then gcc_cv_solaris_crts=yes; fi + ;; + esac]) + ;; +esac +if test x$gcc_cv_solaris_crts = xyes; then + AC_DEFINE(HAVE_SOLARIS_CRTS, 1, + [Define if the system-provided CRTs are present on Solaris.]) +fi + # Test for stack protector support in target C library. AC_CACHE_CHECK(__stack_chk_fail in target C library, gcc_cv_libc_provides_ssp, diff --git a/libgcc/ChangeLog b/libgcc/ChangeLog index f4c13aa0077..559f7726f7f 100644 --- a/libgcc/ChangeLog +++ b/libgcc/ChangeLog @@ -1,3 +1,21 @@ +2015-09-24 Rainer Orth + + * configure.ac (libgcc_cv_solaris_crts): New test. + * configure: Regenerate. + * config.in: Regenerate. + * config/sol2/crtp.c, config/sol2/crtpg.c: New files. + * config/gmon-sol2.c: Rename to ... + * config/sol2/gmon.c: ... this. + Include auto-target.h. + (internal_mcount): Wrap setup handling in !HAVE_SOLARIS_CRTS. + * config/t-sol2: Rename to ... + * config/sol2/t-sol2: ... this. + (gmon.o): Reflect renaming. + (crtp.o, crtpg.o): New rules. + * config.host (*-*-solaris2*): Reflect renaming. + Use system CRTs if present. + Remove default CRT case. + 2015-09-23 John David Anglin * config/pa/linux-atomic.c (__kernel_cmpxchg2): Reorder error checks. diff --git a/libgcc/config.host b/libgcc/config.host index 140aa227c49..6c8b97bfc01 100644 --- 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 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-libgcc-pic t-slibgcc t-slibgcc-elf-ver" if test $with_gnu_ld = yes; then tmake_file="$tmake_file t-slibgcc-gld" else @@ -276,19 +276,22 @@ case ${host} in # Add cpu-specific t-sol2 after t-slibgcc-* so it can augment SHLIB_MAPFILES. tmake_file="$tmake_file $cpu_type/t-sol2" extra_parts="gmon.o crtbegin.o crtend.o" - case ${host} in - i?86-*-solaris2.1[0-9]* | x86_64-*-solaris2.1[0-9]*) - # Solaris 10+/x86 provides crt1.o, crti.o, crtn.o, and gcrt1.o as - # part of the base system. - ;; - sparc*-*-solaris2.1[0-9]*) - # Solaris 10+/SPARC lacks crt1.o and gcrt1.o. - extra_parts="$extra_parts crt1.o gcrt1.o" - ;; - *) - extra_parts="$extra_parts crt1.o crti.o crtn.o gcrt1.o" - ;; - esac + if test "${libgcc_cv_solaris_crts}" = yes; then + # 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" + else + case ${host} in + i?86-*-solaris2.1[0-9]* | x86_64-*-solaris2.1[0-9]*) + # Solaris 10+/x86 provides crt1.o, crti.o, crtn.o, and gcrt1.o as + # part of the base system. + ;; + sparc*-*-solaris2.1[0-9]*) + # Solaris 10+/SPARC lacks crt1.o and gcrt1.o. + extra_parts="$extra_parts crt1.o gcrt1.o" + ;; + esac + fi ;; *-*-uclinux*) extra_parts="crtbegin.o crtend.o" diff --git a/libgcc/config.in b/libgcc/config.in index 59a79618c0e..25aa0d93bab 100644 --- a/libgcc/config.in +++ b/libgcc/config.in @@ -18,6 +18,9 @@ /* Define to 1 if you have the header file. */ #undef HAVE_MEMORY_H +/* Define if the system-provided CRTs are present on Solaris. */ +#undef HAVE_SOLARIS_CRTS + /* Define to 1 if you have the header file. */ #undef HAVE_STDINT_H diff --git a/libgcc/config/gmon-sol2.c b/libgcc/config/gmon-sol2.c deleted file mode 100644 index 7d6149665d0..00000000000 --- a/libgcc/config/gmon-sol2.c +++ /dev/null @@ -1,444 +0,0 @@ -/*- - * Copyright (c) 1991 The Regents of the University of California. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. [rescinded 22 July 1999] - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -/* Mangled into a form that works on Solaris 2/SPARC by Mark Eichin - * for Cygnus Support, July 1992. - * - * Modified to support Solaris 2/x86 by J.W.Hawtin , 14/8/96. - * - * It must be used in conjunction with sol2-gc1.S, which is used to start - * and stop process monitoring. - */ - -#include "tconfig.h" -#include "tsystem.h" -#include /* For creat. */ - -extern void monstartup (char *, char *); -extern void _mcleanup (void); -#ifdef __i386__ -static void internal_mcount (void) __attribute__ ((used)); -#else -static void internal_mcount (char *, unsigned short *) __attribute__ ((used)); -#endif -static void moncontrol (int); - -struct phdr { - char *lpc; - char *hpc; - int ncnt; -}; - -#define HISTFRACTION 2 -#define HISTCOUNTER unsigned short -#define HASHFRACTION 1 -#define ARCDENSITY 2 -#define MINARCS 50 - -struct tostruct { - char *selfpc; - long count; - unsigned short link; -}; - -struct rawarc { - unsigned long raw_frompc; - unsigned long raw_selfpc; - long raw_count; -}; - -#define ROUNDDOWN(x, y) (((x) / (y)) * (y)) -#define ROUNDUP(x, y) ((((x) + (y) - 1) / (y)) * (y)) - -/* froms is actually a bunch of unsigned shorts indexing tos. */ -static int profiling = 3; -static unsigned short *froms; -static struct tostruct *tos = NULL; -static long tolimit = 0; -static char *s_lowpc = NULL; -static char *s_highpc = NULL; -static size_t s_textsize = 0; - -static int ssiz; -static char *sbuf; -static int s_scale; -/* See profil(2) where this is describe (incorrectly). */ -#define SCALE_1_TO_1 0x10000L - -#define MSG "No space for profiling buffer(s)\n" - -void -monstartup (char *lowpc, char *highpc) -{ - size_t monsize; - char *buffer; - size_t o; - - /* Round lowpc and highpc to multiples of the density we're using - so the rest of the scaling (here and in gprof) stays in ints. */ - lowpc = (char *) ROUNDDOWN ((size_t) lowpc, - HISTFRACTION * sizeof (HISTCOUNTER)); - s_lowpc = lowpc; - highpc = (char *) ROUNDUP ((size_t) highpc, - HISTFRACTION * sizeof (HISTCOUNTER)); - s_highpc = highpc; - s_textsize = highpc - lowpc; - monsize = (s_textsize / HISTFRACTION) + sizeof (struct phdr); - buffer = sbrk (monsize); - if (buffer == (void *) -1) { - write (STDERR_FILENO, MSG, sizeof (MSG)); - return; - } - froms = sbrk (s_textsize / HASHFRACTION); - if (froms == (void *) -1) { - write (STDERR_FILENO, MSG, sizeof (MSG)); - froms = NULL; - return; - } - tolimit = s_textsize * ARCDENSITY / 100; - if (tolimit < MINARCS) { - tolimit = MINARCS; - } else if (tolimit > 65534) { - tolimit = 65534; - } - tos = sbrk (tolimit * sizeof (struct tostruct)); - if (tos == (void *) -1) { - write (STDERR_FILENO, MSG, sizeof (MSG)); - froms = NULL; - tos = NULL; - return; - } - tos[0].link = 0; - sbuf = buffer; - ssiz = monsize; - ((struct phdr *) buffer)->lpc = lowpc; - ((struct phdr *) buffer)->hpc = highpc; - ((struct phdr *) buffer)->ncnt = ssiz; - monsize -= sizeof (struct phdr); - if (monsize <= 0) - return; - o = highpc - lowpc; - if(monsize < o) - s_scale = ((float) monsize / o) * SCALE_1_TO_1; - else - s_scale = SCALE_1_TO_1; - moncontrol (1); -} - -void -_mcleanup (void) -{ - int fd; - int fromindex; - int endfrom; - char *frompc; - int toindex; - struct rawarc rawarc; - char *profdir; - const char *proffile; - char *progname; - char buf[PATH_MAX]; - extern char **___Argv; - - moncontrol (0); - - if ((profdir = getenv ("PROFDIR")) != NULL) { - /* If PROFDIR contains a null value, no profiling output is produced. */ - if (*profdir == '\0') { - return; - } - - progname = strrchr (___Argv[0], '/'); - if (progname == NULL) - progname = ___Argv[0]; - else - progname++; - - sprintf (buf, "%s/%ld.%s", profdir, (long) getpid (), progname); - proffile = buf; - } else { - proffile = "gmon.out"; - } - - fd = creat (proffile, 0666); - if (fd < 0) { - perror (proffile); - return; - } -#ifdef DEBUG - fprintf (stderr, "[mcleanup] sbuf %#x ssiz %d\n", sbuf, ssiz); -#endif /* DEBUG */ - - write (fd, sbuf, ssiz); - endfrom = s_textsize / (HASHFRACTION * sizeof (*froms)); - for (fromindex = 0; fromindex < endfrom; fromindex++) { - if (froms[fromindex] == 0) { - continue; - } - frompc = s_lowpc + (fromindex * HASHFRACTION * sizeof (*froms)); - for (toindex = froms[fromindex]; - toindex != 0; - toindex = tos[toindex].link) { -#ifdef DEBUG - fprintf (stderr, "[mcleanup] frompc %#x selfpc %#x count %d\n", - frompc, tos[toindex].selfpc, tos[toindex].count); -#endif /* DEBUG */ - rawarc.raw_frompc = (unsigned long) frompc; - rawarc.raw_selfpc = (unsigned long) tos[toindex].selfpc; - rawarc.raw_count = tos[toindex].count; - write (fd, &rawarc, sizeof (rawarc)); - } - } - close (fd); -} - -/* Solaris 2 libraries use _mcount. */ -#if defined __i386__ -asm(".globl _mcount\n" - "_mcount:\n" - " jmp internal_mcount\n"); -#elif defined __x86_64__ -/* See GLIBC for additional information about this technique. */ -asm(".globl _mcount\n" - " .type _mcount, @function\n" - "_mcount:\n" - /* The compiler calls _mcount after the prologue, and does not - save any of the registers. Therefore we must preserve all - seven registers which may contain function arguments. */ - " subq $0x38, %rsp\n" - " movq %rax, (%rsp)\n" - " movq %rcx, 0x08(%rsp)\n" - " movq %rdx, 0x10(%rsp)\n" - " movq %rsi, 0x18(%rsp)\n" - " movq %rdi, 0x20(%rsp)\n" - " movq %r8, 0x28(%rsp)\n" - " movq %r9, 0x30(%rsp)\n" - /* Get SELFPC (pushed by the call to this function) and - FROMPCINDEX (via the frame pointer). */ - " movq 0x38(%rsp), %rdi\n" - " movq 0x8(%rbp), %rsi\n" - " call internal_mcount\n" - /* Restore the saved registers. */ - " movq 0x30(%rsp), %r9\n" - " movq 0x28(%rsp), %r8\n" - " movq 0x20(%rsp), %rdi\n" - " movq 0x18(%rsp), %rsi\n" - " movq 0x10(%rsp), %rdx\n" - " movq 0x08(%rsp), %rcx\n" - " movq (%rsp), %rax\n" - " addq $0x38, %rsp\n" - " retq\n"); -#elif defined __sparc__ -/* The SPARC stack frame is only held together by the frame pointers - in the register windows. According to the SVR4 SPARC ABI - Supplement, Low Level System Information/Operating System - Interface/Software Trap Types, a type 3 trap will flush all of the - register windows to the stack, which will make it possible to walk - the frames and find the return addresses. - However, it seems awfully expensive to incur a trap (system - call) for every function call. It turns out that "call" simply puts - the return address in %o7 expecting the "save" in the procedure to - shift it into %i7; this means that before the "save" occurs, %o7 - contains the address of the call to mcount, and %i7 still contains - the caller above that. The asm mcount here simply saves those - registers in argument registers and branches to internal_mcount, - simulating a call with arguments. - Kludges: - 1) the branch to internal_mcount is hard coded; it should be - possible to tell asm to use the assembler-name of a symbol. - 2) in theory, the function calling mcount could have saved %i7 - somewhere and reused the register; in practice, I *think* this will - break longjmp (and maybe the debugger) but I'm not certain. (I take - some comfort in the knowledge that it will break the native mcount - as well.) - 3) if builtin_return_address worked, this could be portable. - However, it would really have to be optimized for arguments of 0 - and 1 and do something like what we have here in order to avoid the - trap per function call performance hit. - 4) the atexit and monsetup calls prevent this from simply - being a leaf routine that doesn't do a "save" (and would thus have - access to %o7 and %i7 directly) but the call to write() at the end - would have also prevented this. - - -- [eichin:19920702.1107EST] */ -asm(".global _mcount\n" - "_mcount:\n" - /* i7 == last ret, -> frompcindex. */ - " mov %i7, %o1\n" - /* o7 == current ret, -> selfpc. */ - " mov %o7, %o0\n" - " b,a internal_mcount\n"); -#endif - -static void -#ifdef __i386__ -internal_mcount (void) -#else -internal_mcount (char *selfpc, unsigned short *frompcindex) -#endif -{ - struct tostruct *top; - struct tostruct *prevtop; - long toindex; - static char already_setup; - -#ifdef __i386__ - char *selfpc; - unsigned short *frompcindex; - - /* Find the return address for mcount and the return address for mcount's - caller. */ - - /* selfpc = pc pushed by mcount call. - This identifies the function that was just entered. */ - selfpc = (void *) __builtin_return_address (0); - /* frompcindex = pc in preceding frame. - This identifies the caller of the function just entered. */ - frompcindex = (void *) __builtin_return_address (1); -#endif - - if(!already_setup) { - extern char etext[]; - - already_setup = 1; - -#if defined __i386__ - /* USERSTACK. */ - monstartup ((char *) 0x8048000, etext); -#elif defined __x86_64__ - monstartup (NULL, etext); -#elif defined __sparc__ - { - extern char _start[]; - extern char _init[]; - - monstartup (_start < _init ? _start : _init, etext); - } -#endif - atexit (_mcleanup); - } - /* Check that we are profiling and that we aren't recursively invoked. */ - if (profiling) { - goto out; - } - profiling++; - /* Check that frompcindex is a reasonable pc value. For example: signal - catchers get called from the stack, not from text space. too bad. */ - frompcindex = (unsigned short *) ((long) frompcindex - (long) s_lowpc); - if ((unsigned long) frompcindex > s_textsize) { - goto done; - } - frompcindex = &froms[((long) frompcindex) / (HASHFRACTION * sizeof (*froms))]; - toindex = *frompcindex; - if (toindex == 0) { - /* First time traversing this arc. */ - toindex = ++tos[0].link; - if (toindex >= tolimit) { - goto overflow; - } - *frompcindex = toindex; - top = &tos[toindex]; - top->selfpc = selfpc; - top->count = 1; - top->link = 0; - goto done; - } - top = &tos[toindex]; - if (top->selfpc == selfpc) { - /* arc at front of chain; usual case. */ - top->count++; - goto done; - } - /* Have to go looking down chain for it. Top points to what we are - looking at, prevtop points to previous top. We know it is not at the - head of the chain. */ - for (; /* goto done */; ) { - if (top->link == 0) { - /* top is end of the chain and none of the chain had top->selfpc == - selfpc, so we allocate a new tostruct and link it to the head of - the chain. */ - toindex = ++tos[0].link; - if (toindex >= tolimit) { - goto overflow; - } - top = &tos[toindex]; - top->selfpc = selfpc; - top->count = 1; - top->link = *frompcindex; - *frompcindex = toindex; - goto done; - } - /* Otherwise, check the next arc on the chain. */ - prevtop = top; - top = &tos[top->link]; - if (top->selfpc == selfpc) { - /* There it is. Increment its count move it to the head of the - chain. */ - top->count++; - toindex = prevtop->link; - prevtop->link = top->link; - top->link = *frompcindex; - *frompcindex = toindex; - goto done; - } - - } - done: - profiling--; - /* ... and fall through. */ - out: - /* Normal return restores saved registers. */ - return; - - overflow: - /* Halt further profiling. */ - profiling++; - -#define TOLIMIT "mcount: tos overflow\n" - write (STDERR_FILENO, TOLIMIT, sizeof (TOLIMIT)); - goto out; -} - -/* Control profiling. Profiling is what mcount checks to see if all the - data structures are ready. */ -static void -moncontrol (int mode) -{ - if (mode) { - /* Start. */ - profil ((unsigned short *) (sbuf + sizeof (struct phdr)), - ssiz - sizeof (struct phdr), (size_t) s_lowpc, s_scale); - profiling = 0; - } else { - /* Stop. */ - profil ((unsigned short *) 0, 0, 0, 0); - profiling = 3; - } -} diff --git a/libgcc/config/sol2/crtp.c b/libgcc/config/sol2/crtp.c new file mode 100644 index 00000000000..8b79c55eb90 --- /dev/null +++ b/libgcc/config/sol2/crtp.c @@ -0,0 +1,33 @@ +/* Dummy _mcount when mixing profiling and non-profiling objects. + Copyright (C) 2015 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 +. */ + +void _mcount (void); + +/* A dummy profiling support routine for non-profiling executables, + in case we link in some objects that have been compiled for profiling. */ + +void __attribute__((weak)) +_mcount (void) +{ +} diff --git a/libgcc/config/sol2/crtpg.c b/libgcc/config/sol2/crtpg.c new file mode 100644 index 00000000000..e07a36af937 --- /dev/null +++ b/libgcc/config/sol2/crtpg.c @@ -0,0 +1,47 @@ +/* Register profiling startup and cleanup with Solaris CRTs. + Copyright (C) 2015 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 +. */ + +#include + +extern void monstartup (char *, char *); +extern void _mcleanup (void); + +extern char _start[], _etext[]; + +int __start_crt_compiler (int, char **); + +/* Since Solaris 11.x and Solaris 12, the system-provided CRTs provide a + hook to invoke initialization code early during process startup. + __start_crt_compiler is documented in crt1.o(5). We use it to perform + initialization for profiling as a substitute for the earlier separate + gcrt1.o. */ + +int +__start_crt_compiler (int argc __attribute__ ((unused)), + char **argv __attribute__ ((unused))) +{ + monstartup (_start, _etext); + atexit (_mcleanup); + return 0; +} diff --git a/libgcc/config/sol2/gmon.c b/libgcc/config/sol2/gmon.c new file mode 100644 index 00000000000..f6419580a96 --- /dev/null +++ b/libgcc/config/sol2/gmon.c @@ -0,0 +1,451 @@ +/*- + * Copyright (c) 1991 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. [rescinded 22 July 1999] + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* Mangled into a form that works on Solaris 2/SPARC by Mark Eichin + * for Cygnus Support, July 1992. + * + * Modified to support Solaris 2/x86 by J.W.Hawtin , 14/8/96. + * + * It must be used in conjunction with sol2-gc1.S, which is used to start + * and stop process monitoring. + */ + +#include "tconfig.h" +#include "tsystem.h" +#include "auto-target.h" +#include /* For creat. */ + +extern void monstartup (char *, char *); +extern void _mcleanup (void); +#ifdef __i386__ +static void internal_mcount (void) __attribute__ ((used)); +#else +static void internal_mcount (char *, unsigned short *) __attribute__ ((used)); +#endif +static void moncontrol (int); + +struct phdr { + char *lpc; + char *hpc; + int ncnt; +}; + +#define HISTFRACTION 2 +#define HISTCOUNTER unsigned short +#define HASHFRACTION 1 +#define ARCDENSITY 2 +#define MINARCS 50 + +struct tostruct { + char *selfpc; + long count; + unsigned short link; +}; + +struct rawarc { + unsigned long raw_frompc; + unsigned long raw_selfpc; + long raw_count; +}; + +#define ROUNDDOWN(x, y) (((x) / (y)) * (y)) +#define ROUNDUP(x, y) ((((x) + (y) - 1) / (y)) * (y)) + +/* froms is actually a bunch of unsigned shorts indexing tos. */ +static int profiling = 3; +static unsigned short *froms; +static struct tostruct *tos = NULL; +static long tolimit = 0; +static char *s_lowpc = NULL; +static char *s_highpc = NULL; +static size_t s_textsize = 0; + +static int ssiz; +static char *sbuf; +static int s_scale; +/* See profil(2) where this is describe (incorrectly). */ +#define SCALE_1_TO_1 0x10000L + +#define MSG "No space for profiling buffer(s)\n" + +void +monstartup (char *lowpc, char *highpc) +{ + size_t monsize; + char *buffer; + size_t o; + + /* Round lowpc and highpc to multiples of the density we're using + so the rest of the scaling (here and in gprof) stays in ints. */ + lowpc = (char *) ROUNDDOWN ((size_t) lowpc, + HISTFRACTION * sizeof (HISTCOUNTER)); + s_lowpc = lowpc; + highpc = (char *) ROUNDUP ((size_t) highpc, + HISTFRACTION * sizeof (HISTCOUNTER)); + s_highpc = highpc; + s_textsize = highpc - lowpc; + monsize = (s_textsize / HISTFRACTION) + sizeof (struct phdr); + buffer = sbrk (monsize); + if (buffer == (void *) -1) { + write (STDERR_FILENO, MSG, sizeof (MSG)); + return; + } + froms = sbrk (s_textsize / HASHFRACTION); + if (froms == (void *) -1) { + write (STDERR_FILENO, MSG, sizeof (MSG)); + froms = NULL; + return; + } + tolimit = s_textsize * ARCDENSITY / 100; + if (tolimit < MINARCS) { + tolimit = MINARCS; + } else if (tolimit > 65534) { + tolimit = 65534; + } + tos = sbrk (tolimit * sizeof (struct tostruct)); + if (tos == (void *) -1) { + write (STDERR_FILENO, MSG, sizeof (MSG)); + froms = NULL; + tos = NULL; + return; + } + tos[0].link = 0; + sbuf = buffer; + ssiz = monsize; + ((struct phdr *) buffer)->lpc = lowpc; + ((struct phdr *) buffer)->hpc = highpc; + ((struct phdr *) buffer)->ncnt = ssiz; + monsize -= sizeof (struct phdr); + if (monsize <= 0) + return; + o = highpc - lowpc; + if(monsize < o) + s_scale = ((float) monsize / o) * SCALE_1_TO_1; + else + s_scale = SCALE_1_TO_1; + moncontrol (1); +} + +void +_mcleanup (void) +{ + int fd; + int fromindex; + int endfrom; + char *frompc; + int toindex; + struct rawarc rawarc; + char *profdir; + const char *proffile; + char *progname; + char buf[PATH_MAX]; + extern char **___Argv; + + moncontrol (0); + + if ((profdir = getenv ("PROFDIR")) != NULL) { + /* If PROFDIR contains a null value, no profiling output is produced. */ + if (*profdir == '\0') { + return; + } + + progname = strrchr (___Argv[0], '/'); + if (progname == NULL) + progname = ___Argv[0]; + else + progname++; + + sprintf (buf, "%s/%ld.%s", profdir, (long) getpid (), progname); + proffile = buf; + } else { + proffile = "gmon.out"; + } + + fd = creat (proffile, 0666); + if (fd < 0) { + perror (proffile); + return; + } +#ifdef DEBUG + fprintf (stderr, "[mcleanup] sbuf %#x ssiz %d\n", sbuf, ssiz); +#endif /* DEBUG */ + + write (fd, sbuf, ssiz); + endfrom = s_textsize / (HASHFRACTION * sizeof (*froms)); + for (fromindex = 0; fromindex < endfrom; fromindex++) { + if (froms[fromindex] == 0) { + continue; + } + frompc = s_lowpc + (fromindex * HASHFRACTION * sizeof (*froms)); + for (toindex = froms[fromindex]; + toindex != 0; + toindex = tos[toindex].link) { +#ifdef DEBUG + fprintf (stderr, "[mcleanup] frompc %#x selfpc %#x count %d\n", + frompc, tos[toindex].selfpc, tos[toindex].count); +#endif /* DEBUG */ + rawarc.raw_frompc = (unsigned long) frompc; + rawarc.raw_selfpc = (unsigned long) tos[toindex].selfpc; + rawarc.raw_count = tos[toindex].count; + write (fd, &rawarc, sizeof (rawarc)); + } + } + close (fd); +} + +/* Solaris 2 libraries use _mcount. */ +#if defined __i386__ +asm(".globl _mcount\n" + "_mcount:\n" + " jmp internal_mcount\n"); +#elif defined __x86_64__ +/* See GLIBC for additional information about this technique. */ +asm(".globl _mcount\n" + " .type _mcount, @function\n" + "_mcount:\n" + /* The compiler calls _mcount after the prologue, and does not + save any of the registers. Therefore we must preserve all + seven registers which may contain function arguments. */ + " subq $0x38, %rsp\n" + " movq %rax, (%rsp)\n" + " movq %rcx, 0x08(%rsp)\n" + " movq %rdx, 0x10(%rsp)\n" + " movq %rsi, 0x18(%rsp)\n" + " movq %rdi, 0x20(%rsp)\n" + " movq %r8, 0x28(%rsp)\n" + " movq %r9, 0x30(%rsp)\n" + /* Get SELFPC (pushed by the call to this function) and + FROMPCINDEX (via the frame pointer). */ + " movq 0x38(%rsp), %rdi\n" + " movq 0x8(%rbp), %rsi\n" + " call internal_mcount\n" + /* Restore the saved registers. */ + " movq 0x30(%rsp), %r9\n" + " movq 0x28(%rsp), %r8\n" + " movq 0x20(%rsp), %rdi\n" + " movq 0x18(%rsp), %rsi\n" + " movq 0x10(%rsp), %rdx\n" + " movq 0x08(%rsp), %rcx\n" + " movq (%rsp), %rax\n" + " addq $0x38, %rsp\n" + " retq\n"); +#elif defined __sparc__ +/* The SPARC stack frame is only held together by the frame pointers + in the register windows. According to the SVR4 SPARC ABI + Supplement, Low Level System Information/Operating System + Interface/Software Trap Types, a type 3 trap will flush all of the + register windows to the stack, which will make it possible to walk + the frames and find the return addresses. + However, it seems awfully expensive to incur a trap (system + call) for every function call. It turns out that "call" simply puts + the return address in %o7 expecting the "save" in the procedure to + shift it into %i7; this means that before the "save" occurs, %o7 + contains the address of the call to mcount, and %i7 still contains + the caller above that. The asm mcount here simply saves those + registers in argument registers and branches to internal_mcount, + simulating a call with arguments. + Kludges: + 1) the branch to internal_mcount is hard coded; it should be + possible to tell asm to use the assembler-name of a symbol. + 2) in theory, the function calling mcount could have saved %i7 + somewhere and reused the register; in practice, I *think* this will + break longjmp (and maybe the debugger) but I'm not certain. (I take + some comfort in the knowledge that it will break the native mcount + as well.) + 3) if builtin_return_address worked, this could be portable. + However, it would really have to be optimized for arguments of 0 + and 1 and do something like what we have here in order to avoid the + trap per function call performance hit. + 4) the atexit and monsetup calls prevent this from simply + being a leaf routine that doesn't do a "save" (and would thus have + access to %o7 and %i7 directly) but the call to write() at the end + would have also prevented this. + + -- [eichin:19920702.1107EST] */ +asm(".global _mcount\n" + "_mcount:\n" + /* i7 == last ret, -> frompcindex. */ + " mov %i7, %o1\n" + /* o7 == current ret, -> selfpc. */ + " mov %o7, %o0\n" + " b,a internal_mcount\n"); +#endif + +static void +#ifdef __i386__ +internal_mcount (void) +#else +internal_mcount (char *selfpc, unsigned short *frompcindex) +#endif +{ + struct tostruct *top; + struct tostruct *prevtop; + long toindex; + static char already_setup; + +#ifdef __i386__ + char *selfpc; + unsigned short *frompcindex; + + /* Find the return address for mcount and the return address for mcount's + caller. */ + + /* selfpc = pc pushed by mcount call. + This identifies the function that was just entered. */ + selfpc = (void *) __builtin_return_address (0); + /* frompcindex = pc in preceding frame. + This identifies the caller of the function just entered. */ + frompcindex = (void *) __builtin_return_address (1); +#endif + +/* Only necessary without the Solaris CRTs or a proper gcrt1.o, otherwise + crtpg.o or gcrt1.o take care of that. + + FIXME: What about _init vs. _start on sparc? */ +#ifndef HAVE_SOLARIS_CRTS + if(!already_setup) { + extern char etext[]; + + already_setup = 1; + +#if defined __i386__ + /* USERSTACK. */ + monstartup ((char *) 0x8048000, etext); +#elif defined __x86_64__ + monstartup (NULL, etext); +#elif defined __sparc__ + { + extern char _start[]; + extern char _init[]; + + monstartup (_start < _init ? _start : _init, etext); + } +#endif + atexit (_mcleanup); + } +#endif /* !HAVE_SOLARIS_CRTS */ + /* Check that we are profiling and that we aren't recursively invoked. */ + if (profiling) { + goto out; + } + profiling++; + /* Check that frompcindex is a reasonable pc value. For example: signal + catchers get called from the stack, not from text space. too bad. */ + frompcindex = (unsigned short *) ((long) frompcindex - (long) s_lowpc); + if ((unsigned long) frompcindex > s_textsize) { + goto done; + } + frompcindex = &froms[((long) frompcindex) / (HASHFRACTION * sizeof (*froms))]; + toindex = *frompcindex; + if (toindex == 0) { + /* First time traversing this arc. */ + toindex = ++tos[0].link; + if (toindex >= tolimit) { + goto overflow; + } + *frompcindex = toindex; + top = &tos[toindex]; + top->selfpc = selfpc; + top->count = 1; + top->link = 0; + goto done; + } + top = &tos[toindex]; + if (top->selfpc == selfpc) { + /* arc at front of chain; usual case. */ + top->count++; + goto done; + } + /* Have to go looking down chain for it. Top points to what we are + looking at, prevtop points to previous top. We know it is not at the + head of the chain. */ + for (; /* goto done */; ) { + if (top->link == 0) { + /* top is end of the chain and none of the chain had top->selfpc == + selfpc, so we allocate a new tostruct and link it to the head of + the chain. */ + toindex = ++tos[0].link; + if (toindex >= tolimit) { + goto overflow; + } + top = &tos[toindex]; + top->selfpc = selfpc; + top->count = 1; + top->link = *frompcindex; + *frompcindex = toindex; + goto done; + } + /* Otherwise, check the next arc on the chain. */ + prevtop = top; + top = &tos[top->link]; + if (top->selfpc == selfpc) { + /* There it is. Increment its count move it to the head of the + chain. */ + top->count++; + toindex = prevtop->link; + prevtop->link = top->link; + top->link = *frompcindex; + *frompcindex = toindex; + goto done; + } + + } + done: + profiling--; + /* ... and fall through. */ + out: + /* Normal return restores saved registers. */ + return; + + overflow: + /* Halt further profiling. */ + profiling++; + +#define TOLIMIT "mcount: tos overflow\n" + write (STDERR_FILENO, TOLIMIT, sizeof (TOLIMIT)); + goto out; +} + +/* Control profiling. Profiling is what mcount checks to see if all the + data structures are ready. */ +static void +moncontrol (int mode) +{ + if (mode) { + /* Start. */ + profil ((unsigned short *) (sbuf + sizeof (struct phdr)), + ssiz - sizeof (struct phdr), (size_t) s_lowpc, s_scale); + profiling = 0; + } else { + /* Stop. */ + profil ((unsigned short *) 0, 0, 0, 0); + profiling = 3; + } +} diff --git a/libgcc/config/sol2/t-sol2 b/libgcc/config/sol2/t-sol2 new file mode 100644 index 00000000000..1f7324af21b --- /dev/null +++ b/libgcc/config/sol2/t-sol2 @@ -0,0 +1,33 @@ +# Copyright (C) 2004-2015 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. +# +# You should have received a copy of the GNU General Public License +# along with GCC; see the file COPYING3. If not see +# . + +# crtp, crtpg build rules +crtp.o: $(srcdir)/config/sol2/crtp.c + $(gcc_compile) -c $< +crtpg.o: $(srcdir)/config/sol2/crtpg.c + $(gcc_compile) -c $< + +# gmon build rule +gmon.o: $(srcdir)/config/sol2/gmon.c + $(gcc_compile) -c $< + +# Assemble startup files. +crt1.o: $(srcdir)/config/$(cpu_type)/sol2-c1.S + $(crt_compile) -c $< +gcrt1.o: $(srcdir)/config/$(cpu_type)/sol2-c1.S + $(crt_compile) -c -DGCRT1 $< diff --git a/libgcc/config/t-sol2 b/libgcc/config/t-sol2 deleted file mode 100644 index 85eddb23635..00000000000 --- a/libgcc/config/t-sol2 +++ /dev/null @@ -1,27 +0,0 @@ -# Copyright (C) 2004-2015 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. -# -# You should have received a copy of the GNU General Public License -# along with GCC; see the file COPYING3. If not see -# . - -# gmon build rule: -gmon.o: $(srcdir)/config/gmon-sol2.c - $(gcc_compile) -c $< - -# Assemble startup files. -crt1.o: $(srcdir)/config/$(cpu_type)/sol2-c1.S - $(crt_compile) -c $< -gcrt1.o: $(srcdir)/config/$(cpu_type)/sol2-c1.S - $(crt_compile) -c -DGCRT1 $< diff --git a/libgcc/configure b/libgcc/configure index e22cbcb872a..78708c7f407 100644 --- a/libgcc/configure +++ b/libgcc/configure @@ -4665,6 +4665,38 @@ fi $as_echo "$libgcc_cv_mips_hard_float" >&6; } esac +case ${host} in +*-*-solaris2*) + # Check for system-provided CRTs on Solaris 11.x and Solaris 12. + { $as_echo "$as_me:${as_lineno-$LINENO}: checking system-provided CRTs on Solaris" >&5 +$as_echo_n "checking system-provided CRTs on Solaris... " >&6; } +if test "${libgcc_cv_solaris_crts+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + libgcc_cv_solaris_crts=no + libgcc_sysroot="`${CC} -print-sysroot`" + libgcc_libdir="$libgcc_sysroot/usr/lib" + # At the time they were added, gcrt1.o became a symlink for backwards + # compatibility on x86, while crt1.o was added on sparc, so check for that. + case ${host} in + i?86-*-solaris2* | x86_64-*-solaris2*) + if test -h "$libgcc_libdir/gcrt1.o"; then libgcc_cv_solaris_crts=yes; fi + ;; + sparc*-*-solaris2*) + if test -f "$libgcc_libdir/crt1.o"; then libgcc_cv_solaris_crts=yes; fi + ;; + esac +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libgcc_cv_solaris_crts" >&5 +$as_echo "$libgcc_cv_solaris_crts" >&6; } + if test $libgcc_cv_solaris_crts = yes; then + +$as_echo "#define HAVE_SOLARIS_CRTS 1" >>confdefs.h + + fi + ;; +esac + # Determine the version of glibc, if any, used on the target. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for target glibc version" >&5 $as_echo_n "checking for target glibc version... " >&6; } diff --git a/libgcc/configure.ac b/libgcc/configure.ac index dfabd808d11..9d831a76997 100644 --- a/libgcc/configure.ac +++ b/libgcc/configure.ac @@ -292,6 +292,31 @@ mips*-*-*) [libgcc_cv_mips_hard_float=no])]) esac +case ${host} in +*-*-solaris2*) + # Check for system-provided CRTs on Solaris 11.x and Solaris 12. + AC_CACHE_CHECK([system-provided CRTs on Solaris], + [libgcc_cv_solaris_crts], + [libgcc_cv_solaris_crts=no + libgcc_sysroot="`${CC} -print-sysroot`" + libgcc_libdir="$libgcc_sysroot/usr/lib" + # At the time they were added, gcrt1.o became a symlink for backwards + # compatibility on x86, while crt1.o was added on sparc, so check for that. + case ${host} in + i?86-*-solaris2* | x86_64-*-solaris2*) + if test -h "$libgcc_libdir/gcrt1.o"; then libgcc_cv_solaris_crts=yes; fi + ;; + sparc*-*-solaris2*) + if test -f "$libgcc_libdir/crt1.o"; then libgcc_cv_solaris_crts=yes; fi + ;; + esac]) + if test $libgcc_cv_solaris_crts = yes; then + AC_DEFINE(HAVE_SOLARIS_CRTS, 1, + [Define if the system-provided CRTs are present on Solaris.]) + fi + ;; +esac + # Determine the version of glibc, if any, used on the target. AC_MSG_CHECKING([for target glibc version]) AC_ARG_WITH([glibc-version],