This is the mail archive of the mailing list for the binutils project.

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

weak references and --as-needed

I'm struggling with a bit of a problem when using the GNU toolchain
for a solaris target. This seems to be a fairly well known issue as
it's the basis for the USE_LD_AS_NEEDED thing in gcc. Unfortunately the
problem still isn't fully solved, so I was hoping to get some input and
hopefully progress this further.

The basic problem is:

 - On non-glibc systems, crtbegin.o (from gcc) references
   __register_frame_info. It does this always, even though it's only
   really needed for exception handling. To alleviate this, the
   references are marked as weak and the code is written to handle
   these not getting resolved by the linker.

 - When linking together a DSO, gcc will always add -lgcc_s and ld will
   (correctly) add this as a dependency and will satisfy the
   __register_frame_info references. Let's call this DSO libfoo.

 - Linking a program does _not_ make gcc append -lgcc_s, so normally
   you wouldn't get that unnecessary dependency. But linking a program
   that uses libfoo makes ld follow the DT_NEEDED of it and put up
   libgcc_s on the list of DSOs to check. Since the program will also
   have crtbegin.o, with the weak __register_frame_info reference in
   it, ld will add libgcc_s to the program as DT_NEEDED.

End result is that you have programs depending on libgcc_s even though
they do not use exception handling, complicating the deployment to
non-glibc systems.

This wasn't really acceptable to us, so we/I started looking at how to
make binutils and gcc do the correct thing. Since libgcc_s is needed in
some cases (like with g++), the key issue seem to be to make the
toolchain better respect the weak references. Two things are needed

 - gcc uses --as-needed on Linux systems around -lgcc_s, hoping that ld
   would do the right thing<tm>. Unfortunately it didn't for non-glibc
   systems, so these days only glibc 2.2+ systems get this flag. My
   first step was reinstating this flag for every system that supported

 - The wrong thing<tm> that ld did was to consided libgcc_s as needed,
   even though it only satisfied weak references. After a lot of
   horrifying digging through binutils internals, I managed to make it
   not consider DSOs with only weak references to it as needed.

Now this is now well behaved for this scenario, but is there some other
scenario that will break because of this? The documentation doesn't
mention how --as-needed and weak symbols interact, so it's currently
somewhat undefined. If not then I'd really appreciate if the patch
below could get merged.

There is a fixme in there about references from DSOs that I'm not sure
what's implied. I'm also not entirely clear on why ld's adding
DT_NEEDED to the program to satisfy unresolved symbols from a DSO.
Shouldn't it be up to the DSO to have whatever DT_NEEDED it requires to
fix up its dependencies?

Here's the patch (done against 2.20):

diff -upr binutils-2.20.orig/bfd/elf-bfd.h binutils-2.20/bfd/elf-bfd.h
--- binutils-2.20.orig/bfd/elf-bfd.h	2009-09-10 13:47:12.000000000 +0200
+++ binutils-2.20/bfd/elf-bfd.h	2010-04-20 13:33:30.106351955 +0200
@@ -165,6 +165,8 @@ struct elf_link_hash_entry
   /* Symbol has a non-weak reference from a non-shared object (other than
      the object in which it is defined).  */
   unsigned int ref_regular_nonweak : 1;
+  /* Symbol has a non-weak reference from a shared object */
+  unsigned int ref_dynamic_nonweak : 1;
   /* Dynamic symbol has been adjustd.  */
   unsigned int dynamic_adjusted : 1;
   /* Symbol needs a copy reloc.  */
diff -upr binutils-2.20.orig/bfd/elflink.c binutils-2.20/bfd/elflink.c
--- binutils-2.20.orig/bfd/elflink.c	2009-09-10 13:47:12.000000000 +0200
+++ binutils-2.20/bfd/elflink.c	2010-04-20 13:34:46.973288359 +0200
@@ -4336,7 +4336,9 @@ error_free_dyn:
 		  if (h->def_dynamic)
 		      h->def_dynamic = 0;
+		      /* FIXME: How does the assumption here work? */
 		      h->ref_dynamic = 1;
+		      h->ref_dynamic_nonweak = 1;
 		      h->dynamic_def = 1;
@@ -4348,9 +4350,15 @@ error_free_dyn:
 	      if (! definition)
-		h->ref_dynamic = 1;
+	        {
+		  h->ref_dynamic = 1;
+		  if (bind != STB_WEAK)
+		    h->ref_dynamic_nonweak = 1;
+		}
-		h->def_dynamic = 1;
+	        {
+		  h->def_dynamic = 1;
+		}
 	      if (h->def_regular
 		  || h->ref_regular
 		  || (h->u.weakdef != NULL
@@ -4422,8 +4430,8 @@ error_free_dyn:
 	  if (!add_needed
 	      && definition
 	      && ((dynsym
-		   && h->ref_regular)
-		  || (h->ref_dynamic
+		   && h->ref_regular_nonweak)
+		  || (h->ref_dynamic_nonweak
 		      && (elf_dyn_lib_class (abfd) & DYN_AS_NEEDED) != 0
 		      && !on_needed_list (elf_dt_name (abfd), htab->needed))))

Pierre Ossman            OpenSource-based Thin Client Technology
System Developer         Telephone: +46-13-21 46 00
Cendio AB                Web:

Attachment: signature.asc
Description: PGP signature

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]