Use dl_iterate_phdr in Solaris 11+ unwinder

Rainer Orth ro@CeBiTec.Uni-Bielefeld.DE
Mon Nov 29 13:36:00 GMT 2010


Solaris 11 gained support for dl_iterate_phdr in build 135, and I've
lately been working to use it in the libgcc unwinder.

The patch itself is fairly trivial, and will further be simplified
before final submission.  I'd like to post the current state of affairs
to get comments on a couple of issues:

* A considerable part of the patch consists of workarounds for Sun ld
  bugs:

** ld currently interprets DW_EH_PE_datarel relative to .eh_frame_hdr
   instead of .got.  Unfortunately the LSB is unspecific about this, and
   I've still not found a proper specification, but this is going to be
   fixed.

** On SPARC, the search table in .eh_frame_hdr is always empty, so I'm
   ignoring it right now.

** I also ran into a GNU ld bug that broke libffi unwind and libjava
   testing:

   ld/12253	.eh_frame_hdr not properly sorted with mixed .eh_frame encodings

   This is now fixed for binutils 2.22 and will be worked around in
   libffi.

** The DT_PLTGOT entry in .dynamic on 32-bit x86 is relocated in glibc
   (ld-linux.so) by adding the load base, but not by either Solaris or
   FreeBSD ld.so.  FreeBSD is unaffected, though, since they use the
   default encoding, DW_EH_PE_absptr.  I don't know if this is specified
   anywhere.

  All those workarounds (i.e. support for USE_EH_FRAME_HDR) will be
  removed before the patch goes in and replaced by a check for a Sun ld
  version without the bugs.

* I'm using config/t-sol2-eh to set LIB2ADDEH and LIB2ADDEHDEP.  The
  same snippet is used in three other places: config/{t-freebsd,
  t-libunwind-elf, t-linux} and it might be useful to move this into a
  separate file included everywhere.  Perhaps config/t-glibc-eh,
  although this is a misnomer now that FreeBSD and Solaris libc also
  provide dl_iterate_phdr.  t-dip-eh?

* Along the same line, unwind-dw2-fde-glibc.c is misnamed, too.
  Probably not worthwhile changing, though?

* Until Solaris 11 build 154, <link.h> cannot be used with largefile
  support.  This is tracked as

  6997934	<link.h> cannot be used in largefile-aware program
  http://bugs.opensolaris.org/bugdatabase/view_bug.do?bug_id=6997934

  and the workarounds can probably go before the final patch goes in.

With the patch below, I've successfully bootstrapped mainline on both
i386-pc-solaris2.11 and sparc-sun-solaris2.11 with Sun ld and CVS GNU
ld.  There's only a single regression right now where a couple of objc
tests fail with gld:

+FAIL: objc.dg/lto/trivial-1 objc_lto_trivial-1_0.o-objc_lto_trivial-1_0.o link, -O0 -fwhopr -fgnu-runtime
+UNRESOLVED: objc.dg/lto/trivial-1 objc_lto_trivial-1_0.o-objc_lto_trivial-1_0.o execute -O0 -fwhopr -fgnu-runtime

/vol/gcc/bin/gld-2.20.51: objc-dg-lto-trivial-1-01: hidden symbol `__gcc_personality_v0' in /vol/gcc/obj/gcc-4.6.0-20101029/11-gcc-gas-gld-cvs/gcc/libgcc_eh.a(unwind-c.o) is referenced by DSO
/vol/gcc/bin/gld-2.20.51: final link failed: Nonrepresentable section on output

They seem ultimately to be due to a misconstructed libobjc.so.2:

$ ldd -d libobjc.so.2
        libc.so.1 =>     /lib/libc.so.1
        symbol not found: __gcc_personality_v0          (../../../i386-pc-solari
s2.11/libobjc/.libs/libobjc.so.2)
        libm.so.2 =>     /lib/libm.so.2

It seems that libobjc.so should be built with -shared-libgcc, but I'm
still investigating.

Given how localized and Solaris-specific this patch is, would an updated
form be ok for mainline despite being in stage 3?

Thanks.
	Rainer


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

	* configure.ac: Check for dl_iterate_phdr.
	* configure: Regenerate.
	* config.in: Likewise.
	* config/t-sol2-eh: New file.
	* config.gcc (i[34567]86-*-solaris2*): Add t-sol2-eh to tmake_file
	if have_dl_iterate_phdr.
	(sparc*-*-solaris2*): Likewise.
	* crtstuff.c (USE_PT_GNU_EH_FRAME): Define for recent Solaris 11
	with 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.
	(USE_EH_FRAME_HDR): Provide default.
	Ignore .eh_frame_hdr unless USE_EH_FRAME_HDR.
	* config/i386/sol2.h [!TARGET_GNU_LD] (USE_EH_FRAME_HDR): Define.
	* config/sparc/sol2.h [!TARGET_GNU_LD] (USE_EH_FRAME_HDR): Define.
	* config/sol2-gld.h [HAVE_DL_ITERATE_PHDR] (LINK_EH_SPEC): Define.
	[HAVE_LD_AS_NEEDED] (USE_LD_AS_NEEDED): Define.

diff -r 523125a49e71 gcc/config.gcc
--- a/gcc/config.gcc	Sat Nov 27 11:35:42 2010 +0100
+++ b/gcc/config.gcc	Mon Nov 29 11:05:51 2010 +0100
@@ -1364,6 +1364,9 @@
 		tm_file="${tm_file} i386/x86-64.h i386/sol2-10.h"
 		tm_defines="${tm_defines} TARGET_BI_ARCH=1"
 		tmake_file="$tmake_file i386/t-sol2-10"
+		if test x$have_dl_iterate_phdr = xyes; then
+			tmake_file="$tmake_file t-sol2-eh"
+		fi
 		# i386/t-crtstuff only affects libgcc.  Its inclusion
 		# depends on a runtime test and is thus performed in
 		# libgcc/configure.ac instead.
@@ -2520,6 +2523,9 @@
 	if test x$gas = xyes; then
 		tm_file="usegas.h ${tm_file}"
 	fi
+	if test x$have_dl_iterate_phdr = xyes; then
+		tmake_file="$tmake_file t-sol2-eh"
+	fi
 	c_target_objs="sol2-c.o"
 	cxx_target_objs="sol2-c.o"
 	extra_objs="sol2.o"
diff -r 523125a49e71 gcc/config/i386/sol2.h
--- a/gcc/config/i386/sol2.h	Sat Nov 27 11:35:42 2010 +0100
+++ b/gcc/config/i386/sol2.h	Mon Nov 29 11:05:51 2010 +0100
@@ -38,6 +38,13 @@
 		  : DW_EH_PE_datarel))					\
    : DW_EH_PE_absptr)
 
+#ifndef TARGET_GNU_LD
+/* The Solaris linker before Solaris 11 build 154? mishandles
+   DW_EH_PE_datarel, so the 32-bit .eh_frame_hdr binary search table
+   doesn't work.  */
+#define USE_EH_FRAME_HDR (sizeof (void *) != 4)
+#endif
+
 /* The Solaris linker will not merge a read-only .eh_frame section
    with a read-write .eh_frame section.  None of the encodings used
    with non-PIC code require runtime relocations.  In 64-bit mode,
diff -r 523125a49e71 gcc/config/sol2-gld.h
--- a/gcc/config/sol2-gld.h	Sat Nov 27 11:35:42 2010 +0100
+++ b/gcc/config/sol2-gld.h	Mon Nov 29 11:05:51 2010 +0100
@@ -29,3 +29,17 @@
 /* GNU ld needs --export-dynamic to implement -rdynamic.  */
 #undef RDYNAMIC_SPEC
 #define RDYNAMIC_SPEC "--export-dynamic"
+
+/* Solaris 11 build 135+ implements dl_iterate_phdr.  */
+#ifdef HAVE_DL_ITERATE_PHDR
+#define LINK_EH_SPEC "%{!static:--eh-frame-hdr} "
+#endif
diff -r 523125a49e71 gcc/config/sparc/sol2.h
--- a/gcc/config/sparc/sol2.h	Sat Nov 27 11:35:42 2010 +0100
+++ b/gcc/config/sparc/sol2.h	Mon Nov 29 11:05:51 2010 +0100
@@ -133,6 +133,11 @@
   ((flag_pic || GLOBAL) ? DW_EH_PE_aligned : DW_EH_PE_absptr)
 #endif
 
+#ifndef TARGET_GNU_LD
+/* The Solaris linker before Solaris 11 build 154? creates empty binary
+   search tables in .eh_frame_hdr, so ignore it.  */
+#define USE_EH_FRAME_HDR 0
+#endif
 
 /* Define for support of TFmode long double.
    SPARC ABI says that long double is 4 words.  */
diff -r 523125a49e71 gcc/config/t-sol2-eh
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gcc/config/t-sol2-eh	Mon Nov 29 11:05:51 2010 +0100
@@ -0,0 +1,4 @@
+# Use unwind-dw2-fde-glibc
+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 523125a49e71 gcc/configure.ac
--- a/gcc/configure.ac	Sat Nov 27 11:35:42 2010 +0100
+++ b/gcc/configure.ac	Mon Nov 29 11:05:51 2010 +0100
@@ -977,6 +977,9 @@
 	gettimeofday mbstowcs wcswidth mmap mincore setlocale \
 	gcc_UNLOCKED_FUNCS)
 
+# Check for dl_iterate_phdr.
+AC_CHECK_FUNCS(dl_iterate_phdr, [have_dl_iterate_phdr=yes])
+
 if test x$ac_cv_func_mbstowcs = xyes; then
   AC_CACHE_CHECK(whether mbstowcs works, gcc_cv_func_mbstowcs_works,
 [    AC_RUN_IFELSE([AC_LANG_SOURCE([[#include <stdlib.h>
diff -r 523125a49e71 gcc/crtstuff.c
--- a/gcc/crtstuff.c	Sat Nov 27 11:35:42 2010 +0100
+++ b/gcc/crtstuff.c	Mon Nov 29 11:05:51 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,19 @@
 
 #if defined(OBJECT_FORMAT_ELF) \
     && !defined(OBJECT_FORMAT_FLAT) \
+    && defined(HAVE_DL_ITERATE_PHDR) \
+    && !defined(inhibit_libc) && !defined(CRTSTUFFT_O) \
+    && defined(__sun__) && defined(__svr4__)
+/* Large file support doesn't work with Solaris 2 libelf and isn't needed
+   here, so disable it.  */
+#undef _FILE_OFFSET_BITS
+#define _FILE_OFFSET_BITS 32
+#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 523125a49e71 gcc/unwind-dw2-fde-glibc.c
--- a/gcc/unwind-dw2-fde-glibc.c	Sat Nov 27 11:35:42 2010 +0100
+++ b/gcc/unwind-dw2-fde-glibc.c	Mon Nov 29 11:05:51 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,18 @@
 # define USE_PT_GNU_EH_FRAME
 #endif
 
+/* The definition of PT_SUNW_EH_FRAME was introduced together with
+   dl_iterate_phdr.  Cannot check for HAVE_DL_ITERATE_PHDR which is not
+   available in target code.  */
+#if !defined(inhibit_libc) && defined(PT_SUNW_EH_FRAME) \
+    && defined(__sun__) && defined(__svr4__)
+/* Large file support doesn't work with Solaris 2 libelf and isn't needed
+   here, so disable it.  */
+#undef _FILE_OFFSET_BITS
+#define _FILE_OFFSET_BITS 32
+# define USE_PT_GNU_EH_FRAME
+#endif
+
 #if defined(USE_PT_GNU_EH_FRAME)
 
 #include <link.h>
@@ -256,6 +269,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 +324,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
@@ -323,10 +351,15 @@
 				    (const unsigned char *) (hdr + 1),
 				    &eh_frame);
 
+#ifndef USE_EH_FRAME_HDR
+#define USE_EH_FRAME_HDR 1
+#endif
+
   /* We require here specific table encoding to speed things up.
      Also, DW_EH_PE_datarel here means using PT_GNU_EH_FRAME start
      as base, not the processor specific DW_EH_PE_datarel.  */
-  if (hdr->fde_count_enc != DW_EH_PE_omit
+  if (USE_EH_FRAME_HDR
+      && hdr->fde_count_enc != DW_EH_PE_omit
       && hdr->table_enc == (DW_EH_PE_datarel | DW_EH_PE_sdata4))
     {
       _Unwind_Ptr fde_count;


-- 
-----------------------------------------------------------------------------
Rainer Orth, Center for Biotechnology, Bielefeld University



More information about the Gcc-patches mailing list