Patchwork Use dl_iterate_phdr in Solaris 11+ unwinder

login
register
mail settings
Submitter Rainer Orth
Date Dec. 22, 2010, 2:52 p.m.
Message ID <yddfwtplv0o.fsf@manam.CeBiTec.Uni-Bielefeld.DE>
Download mbox | patch
Permalink /patch/76415/
State New
Headers show

Comments

Rainer Orth - Dec. 22, 2010, 2:52 p.m.
Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE> writes:

> I'm now only waiting for a version of Sun ld on SPARC that creates
> non-empty search tables in .eh_frame_hdr.  Once that is tested as well,
> I plan to commit the patch (provided there are no issues with the build
> changes) unless there are strong objections.

I've now received final test versions of Sun ld that work on both i386
and sparc.  The following patch is currently bootstrapping on both
i386-pc-solaris2.11 and sparc-sun-solaris2.11 with the fixed Sun ld
using either as or gas 2.21, and gld with gas 2.21.  Unless any problems
turn up, I'd like to check it in tomorrow.

I'm not defining USE_LD_AS_NEEDED with gld anymore since it causes every
trivial executable to be linked with libgcc_s.so.1, which cannot be
right.  I've filed binutils PR

ld/12320	ld --as-needed links libgcc_s.so.1 unnecessarily on Solaris 11

for this.

The failure of a few objc tests is due to libobjc.so.2 not being linked
with -shared-libgcc, which is a mistake from what I can see.  I'll
submit a corresponding patch shortly once testing has finished.

Perhaps some build maintainer could comment on the build parts, but I
really think they are either completely Solaris specific or obvious.

Thanks.
	Rainer


2010-01-18  Rainer Orth  <ro@CeBiTec.Uni-Bielefeld.DE>

	gcc:
	* configure.ac (gcc_cv_ld_eh_frame_hdr): Only check GNU ld for
	--eh-frame-hdr.
	Check for working Sun ld version.
	(HAVE_LD_EH_FRAME_HDR): Adapt comment.
	(glibc_header_dir): Set only once.
	Rename to ...
	(target_header_dir): ... this.
	Adapt users.
	(gcc_cv_target_dl_iterate_frame_hdr): Check on *-*-solaris2*.
	(TARGET_DL_ITERATE_PHDR): Define if present.
	* configure: Regenerate.
	* config.in: Likewise.
	* config/t-sol2 (LIB2ADDEH, LIB2ADDEHDEP): Define.
	* crtstuff.c (USE_PT_GNU_EH_FRAME): Define for recent Solaris 11
	with linker support and dl_iterate_phdr.
	* unwind-dw2-fde-glibc.c (USE_PT_GNU_EH_FRAME): Likewise.
	(_Unwind_IteratePhdrCallback) [PT_SUNW_UNWIND]: Also accept
	PT_SUNW_UNWIND .eh_frame_hdr sections.
	[CRT_GET_RFIB_DATA && __i386__ && __sun__ && __svr4__]: Add
	load_base to data->dbase.
	[CRT_GET_RFIB_DATA && __x86_64__ && __sun__ && __svr4__]: Handle
	64-bit Solaris 10+/x86.
	* config/sol2-gld.h [TARGET_DL_ITERATE_PHDR && HAVE_LD_EH_FRAME_HDR]
	(LINK_EH_SPEC): Define.

Patch

diff -r 07fa9ff0fef8 gcc/config/sol2-gld.h
--- a/gcc/config/sol2-gld.h	Mon Dec 13 22:02:01 2010 +0100
+++ b/gcc/config/sol2-gld.h	Fri Dec 17 15:54:27 2010 +0100
@@ -29,3 +29,21 @@ 
 /* GNU ld needs --export-dynamic to implement -rdynamic.  */
 #undef RDYNAMIC_SPEC
 #define RDYNAMIC_SPEC "--export-dynamic"
+
+/* Solaris 11 build 135+ implements dl_iterate_phdr.  */
+#if defined(HAVE_LD_EH_FRAME_HDR) && defined(TARGET_DL_ITERATE_PHDR)
+
+#define LINK_EH_SPEC "%{!static:--eh-frame-hdr} "
+#endif /* HAVE_LD_EH_FRAME && TARGET_DL_ITERATE_PHDR */
diff -r 07fa9ff0fef8 gcc/config/t-sol2
--- a/gcc/config/t-sol2	Mon Dec 13 22:02:01 2010 +0100
+++ b/gcc/config/t-sol2	Fri Dec 17 15:54:27 2010 +0100
@@ -28,3 +28,9 @@ 
   tree.h output.h $(TM_H) target.h $(TM_P_H) $(GGC_H)
 	$(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
 	  $(srcdir)/config/sol2.c
+
+# Use unwind-dw2-fde-glibc.c.  Unless linker support and dl_iterate_phdr
+# are present, automatically falls back to unwind-dw2-fde.c.
+LIB2ADDEH = $(srcdir)/unwind-dw2.c $(srcdir)/unwind-dw2-fde-glibc.c \
+  $(srcdir)/unwind-sjlj.c $(srcdir)/gthr-gnat.c $(srcdir)/unwind-c.c
+LIB2ADDEHDEP = unwind.inc unwind-dw2-fde.h unwind-dw2-fde.c
diff -r 07fa9ff0fef8 gcc/configure.ac
--- a/gcc/configure.ac	Mon Dec 13 22:02:01 2010 +0100
+++ b/gcc/configure.ac	Fri Dec 17 15:54:27 2010 +0100
@@ -3979,15 +3979,26 @@ 
     gcc_cv_ld_eh_frame_hdr=yes
   fi
 elif test x$gcc_cv_ld != x; then
-	# Check if linker supports --eh-frame-hdr option
-	if $gcc_cv_ld --help 2>/dev/null | grep eh-frame-hdr > /dev/null; then
-		gcc_cv_ld_eh_frame_hdr=yes
-	fi
+  if echo "$ld_ver" | grep GNU > /dev/null; then
+    # Check if linker supports --eh-frame-hdr option
+    if $gcc_cv_ld --help 2>/dev/null | grep eh-frame-hdr > /dev/null; then
+      gcc_cv_ld_eh_frame_hdr=yes
+    fi
+  else
+    case "$target" in
+      *-*-solaris2*)
+        # Sun ld has various bugs in .eh_frame_hdr support before version 1.2249.
+        if test "$ld_vers_major" -gt 1 || test "$ld_vers_minor" -ge 2249; then
+          gcc_cv_ld_eh_frame_hdr=yes
+        fi
+        ;;
+    esac
+  fi
 fi
 GCC_TARGET_TEMPLATE([HAVE_LD_EH_FRAME_HDR])
 if test x"$gcc_cv_ld_eh_frame_hdr" = xyes; then
 	AC_DEFINE(HAVE_LD_EH_FRAME_HDR, 1,
-[Define if your linker supports --eh-frame-hdr option.])
+[Define if your linker supports .eh_frame_hdr.])
 fi
 AC_MSG_RESULT($gcc_cv_ld_eh_frame_hdr)
 
@@ -4268,45 +4279,46 @@ 
 [Define to PREFIX/include if cpp should also search that directory.])
 fi
 
+if test x$host != x$target || test "x$TARGET_SYSTEM_ROOT" != x; then
+  if test "x$with_headers" != x; then
+    target_header_dir=$with_headers
+  elif test "x$with_sysroot" = x; then
+    target_header_dir="${exec_prefix}/${target_noncanonical}/sys-include"
+  elif test "x$with_build_sysroot" != "x"; then
+    target_header_dir="${with_build_sysroot}/usr/include"
+  elif test "x$with_sysroot" = xyes; then
+    target_header_dir="${exec_prefix}/${target_noncanonical}/sys-root/usr/include"
+  else
+    target_header_dir="${with_sysroot}/usr/include"
+  fi
+else
+  target_header_dir=/usr/include
+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,
       [gcc_cv_libc_provides_ssp=no
     case "$target" in
        *-*-linux* | *-*-kfreebsd*-gnu | *-*-knetbsd*-gnu)
-      if test x$host != x$target || test "x$TARGET_SYSTEM_ROOT" != x; then
-	if test "x$with_headers" != x; then
-	  glibc_header_dir=$with_headers
-	elif test "x$with_sysroot" = x; then
-	  glibc_header_dir="${exec_prefix}/${target_noncanonical}/sys-include"
-	elif test "x$with_build_sysroot" != "x"; then
-	  glibc_header_dir="${with_build_sysroot}/usr/include"
-	elif test "x$with_sysroot" = xyes; then
-	  glibc_header_dir="${exec_prefix}/${target_noncanonical}/sys-root/usr/include"
-	else
-	  glibc_header_dir="${with_sysroot}/usr/include"
-	fi
-      else
-	glibc_header_dir=/usr/include
-      fi
       [# glibc 2.4 and later provides __stack_chk_fail and
       # either __stack_chk_guard, or TLS access to stack guard canary.
-      if test -f $glibc_header_dir/features.h \
+      if test -f $target_header_dir/features.h \
 	 && $EGREP '^[ 	]*#[ 	]*define[ 	]+__GNU_LIBRARY__[ 	]+([1-9][0-9]|[6-9])' \
-	    $glibc_header_dir/features.h > /dev/null; then
+	    $target_header_dir/features.h > /dev/null; then
 	if $EGREP '^[ 	]*#[ 	]*define[ 	]+__GLIBC__[ 	]+([1-9][0-9]|[3-9])' \
-	   $glibc_header_dir/features.h > /dev/null; then
+	   $target_header_dir/features.h > /dev/null; then
 	  gcc_cv_libc_provides_ssp=yes
 	elif $EGREP '^[ 	]*#[ 	]*define[ 	]+__GLIBC__[ 	]+2' \
-	     $glibc_header_dir/features.h > /dev/null \
+	     $target_header_dir/features.h > /dev/null \
 	     && $EGREP '^[ 	]*#[ 	]*define[ 	]+__GLIBC_MINOR__[ 	]+([1-9][0-9]|[4-9])' \
-	     $glibc_header_dir/features.h > /dev/null; then
+	     $target_header_dir/features.h > /dev/null; then
 	  gcc_cv_libc_provides_ssp=yes
 	elif $EGREP '^[ 	]*#[ 	]*define[ 	]+__UCLIBC__[ 	]+1' \
-	     $glibc_header_dir/features.h > /dev/null && \
-	     test -f $glibc_header_dir/bits/uClibc_config.h && \
+	     $target_header_dir/features.h > /dev/null && \
+	     test -f $target_header_dir/bits/uClibc_config.h && \
 	     $EGREP '^[ 	]*#[ 	]*define[ 	]+__UCLIBC_HAS_SSP__[ 	]+1' \
-	     $glibc_header_dir/bits/uClibc_config.h > /dev/null; then
+	     $target_header_dir/bits/uClibc_config.h > /dev/null; then
 	  gcc_cv_libc_provides_ssp=yes
 	fi
       fi]
@@ -4342,21 +4354,8 @@ 
 [  --with-long-double-128  Use 128-bit long double by default.],
       gcc_cv_target_ldbl128="$with_long_double_128",
       [[gcc_cv_target_ldbl128=no
-      if test x$host != x$target || test "x$TARGET_SYSTEM_ROOT" != x; then
-	if test "x$with_sysroot" = x; then
-	  glibc_header_dir="${exec_prefix}/${target_noncanonical}/sys-include"
-	elif test "x$with_build_sysroot" != "x"; then
-	  glibc_header_dir="${with_build_sysroot}/usr/include"
-	elif test "x$with_sysroot" = xyes; then
-	  glibc_header_dir="${exec_prefix}/${target_noncanonical}/sys-root/usr/include"
-	else
-	  glibc_header_dir="${with_sysroot}/usr/include"
-	fi
-      else
-	glibc_header_dir=/usr/include
-      fi
       grep '^[ 	]*#[ 	]*define[ 	][ 	]*__LONG_DOUBLE_MATH_OPTIONAL' \
-        $glibc_header_dir/bits/wordsize.h > /dev/null 2>&1 \
+        $target_header_dir/bits/wordsize.h > /dev/null 2>&1 \
       && gcc_cv_target_ldbl128=yes
       ]])
     ;;
@@ -4366,6 +4365,27 @@ 
 	    [Define if TFmode long double should be the default])
 fi
 
+AC_MSG_CHECKING(dl_iterate_phdr in target C library)
+gcc_cv_target_dl_iterate_phdr=unknown
+case "$target" in
+  *-*-solaris2*)
+    # <link.h> needs both a dl_iterate_phdr declaration and support for
+    # compilation with largefile support.
+    if grep dl_iterate_phdr $target_header_dir/link.h > /dev/null 2>&1 \
+      && grep 'large file capable' $target_header_dir/link.h > /dev/null 2>&1; then
+      gcc_cv_target_dl_iterate_phdr=yes
+    else
+      gcc_cv_target_dl_iterate_phdr=no
+    fi
+    ;;
+esac
+GCC_TARGET_TEMPLATE([TARGET_DL_ITERATE_PHDR])
+if test x$gcc_cv_target_dl_iterate_phdr = xyes; then
+   AC_DEFINE(TARGET_DL_ITERATE_PHDR, 1,
+[Define if your target C library provides the `dl_iterate_phdr' function.])
+fi
+AC_MSG_RESULT($gcc_cv_target_dl_iterate_phdr)
+
 # Find out what GC implementation we want, or may, use.
 AC_ARG_WITH(gc,
 [  --with-gc={page,zone}   choose the garbage collection mechanism to use
diff -r 07fa9ff0fef8 gcc/crtstuff.c
--- a/gcc/crtstuff.c	Mon Dec 13 22:02:01 2010 +0100
+++ b/gcc/crtstuff.c	Fri Dec 17 15:54:27 2010 +0100
@@ -1,7 +1,7 @@ 
 /* Specialized bits of code needed to support construction and
    destruction of file-scope objects in C++ code.
    Copyright (C) 1991, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
-   2002, 2003, 2004, 2005, 2006, 2007, 2009 Free Software Foundation, Inc.
+   2002, 2003, 2004, 2005, 2006, 2007, 2009, 2010 Free Software Foundation, Inc.
    Contributed by Ron Guilmette (rfg@monkeys.com).
 
 This file is part of GCC.
@@ -90,6 +90,15 @@ 
 
 #if defined(OBJECT_FORMAT_ELF) \
     && !defined(OBJECT_FORMAT_FLAT) \
+    && defined(HAVE_LD_EH_FRAME_HDR) && defined(TARGET_DL_ITERATE_PHDR) \
+    && !defined(inhibit_libc) && !defined(CRTSTUFFT_O) \
+    && defined(__sun__) && defined(__svr4__)
+#include <link.h>
+# define USE_PT_GNU_EH_FRAME
+#endif
+
+#if defined(OBJECT_FORMAT_ELF) \
+    && !defined(OBJECT_FORMAT_FLAT) \
     && defined(HAVE_LD_EH_FRAME_HDR) \
     && !defined(inhibit_libc) && !defined(CRTSTUFFT_O) \
     && defined(__GLIBC__) && __GLIBC__ >= 2
diff -r 07fa9ff0fef8 gcc/unwind-dw2-fde-glibc.c
--- a/gcc/unwind-dw2-fde-glibc.c	Mon Dec 13 22:02:01 2010 +0100
+++ b/gcc/unwind-dw2-fde-glibc.c	Fri Dec 17 15:54:27 2010 +0100
@@ -1,4 +1,5 @@ 
-/* Copyright (C) 2001, 2002, 2003, 2004, 2005, 2009 Free Software Foundation, Inc.
+/* Copyright (C) 2001, 2002, 2003, 2004, 2005, 2009, 2010
+   Free Software Foundation, Inc.
    Contributed by Jakub Jelinek <jakub@redhat.com>.
 
    This file is part of GCC.
@@ -57,6 +58,12 @@ 
 # define USE_PT_GNU_EH_FRAME
 #endif
 
+#if !defined(inhibit_libc) && defined(HAVE_LD_EH_FRAME_HDR) \
+    && defined(TARGET_DL_ITERATE_PHDR) \
+    && defined(__sun__) && defined(__svr4__)
+# define USE_PT_GNU_EH_FRAME
+#endif
+
 #if defined(USE_PT_GNU_EH_FRAME)
 
 #include <link.h>
@@ -256,6 +263,12 @@ 
 	}
       else if (phdr->p_type == PT_GNU_EH_FRAME)
 	p_eh_frame_hdr = phdr;
+#ifdef PT_SUNW_UNWIND
+      /* Sun ld emits PT_SUNW_UNWIND .eh_frame_hdr sections instead of
+	 PT_SUNW_EH_FRAME/PT_GNU_EH_FRAME, so accept them as well.  */
+      else if (phdr->p_type == PT_SUNW_UNWIND)
+	p_eh_frame_hdr = phdr;
+#endif
       else if (phdr->p_type == PT_DYNAMIC)
 	p_dynamic = phdr;
     }
@@ -305,13 +318,22 @@ 
       for (; dyn->d_tag != DT_NULL ; dyn++)
 	if (dyn->d_tag == DT_PLTGOT)
 	  {
-	    /* On IA-32, _DYNAMIC is writable and GLIBC has relocated it.  */
 	    data->dbase = (void *) dyn->d_un.d_ptr;
+#if defined __linux__
+	    /* On IA-32 Linux, _DYNAMIC is writable and GLIBC has
+	       relocated it.  */
+#elif defined __sun__ && defined __svr4__
+	    /* On Solaris 2/x86, we need to do this ourselves.  */
+	    data->dbase += load_base;
+#endif
 	    break;
 	  }
     }
 # elif defined __FRV_FDPIC__ && defined __linux__
   data->dbase = load_base.got_value;
+# elif defined __x86_64__ && defined __sun__ && defined __svr4__
+  /* While CRT_GET_RFIB_DATA is also defined for 64-bit Solaris 10+/x86, it
+     doesn't apply since it uses DW_EH_PE_pcrel encoding.  */
 # else
 #  error What is DW_EH_PE_datarel base on this platform?
 # endif