This is the mail archive of the libc-alpha@sources.redhat.com mailing list for the glibc 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]

Re: PATCH: Treat RTLD_LOCAL like Solaris (Re: Duplicate dataobjects in shared libraries)


>>>>> "David" == David Abrahams <david.abrahams@rcn.com> writes:

> From: "H . J . Lu" <hjl@lucon.org>
>> This patch makes glibc more like Solaris for RTLD_LOCAL. It also passed
>> "make check" in glibc. Any comments?

> It's not clear to me that working "more like Solaris" was what we were
> after

No; Solaris' behavior is no more helpful for real-world C++ examples.
Sorry I didn't emphasize this more when you (H.J.) started talking about
doing this.

Is there any kind of a standard for ld.so symbol resolution behavior?  I've
tried looking at the ELF spec, and didn't notice anything, but I haven't
read very closely yet.

A simple ~80% solution for C++ problems with RTLD_LOCAL would be:

1) Always prefer the last weak definition if no strong definition is seen.

   So if an RTLD_LOCAL DSO and a library it uses both provide weak
   definitions of a type_info node, the version from the library will be
   used in both objects; as a result, another DSO linked against the same
   library can use the same definition.

Implementation of this is extremely simple; an untested patch is attached
below.  Comments?  I think something like this is necessary to get
reasonable plugin semantics from C++, where the barrier between library and
user is much more porous, especially with templates.

An additional modification, inspired by a suggestion of David's:

2) If a DSO A has two unrelated dependencies B and C which both define (and
   use) the same weak symbol, add C to the dependency list of this loaded
   copy of B.

   So if we load (with RTLD_LOCAL) A, which depends on B and C, we would
   add C to B's dependency list, and all references to a symbol would use
   the version from C.  If we then load D, which only depends on B, we
   would get C as well, so references in D can also use that definition.

   This depends on #1 above to be useful; without that change, references
   would use the definition in D regardless of what other versions were
   available.  It might, however, still be useful to avoid unloading C
   while B is still pointing at one of its symbols; do we already protect
   against that somehow?

#1 would fix C++ vague linkage semantics in plugins for ~80% (arbitrary
estimate) of cases.  #2 would fix it for another ~10% (such as the case
described), but seems somewhat inelegant; I'd be happy with just #1.

A further case that David described, whereby B and C are first loaded
separately, seems intractable without re-resolving relocations, which I
don't think we want to get into.

Another suggestion, which is independent of the above, but seems to me like
The Right Thing for strong definitions in the presence of RTLD_LOCAL:

3) When resolving a relocation from a DSO loaded with RTLD_LOCAL, start
   looking from the DSO itself; do not consider other RTLD_LOCAL objects
   which depend on it.

   This would allow a plugin to override operator new without affecting the
   definition used by the standard library and messing up other users.

Thoughts?

2002-05-30  Jason Merrill  <jason@redhat.com>

	* elf/do-lookup.h (FCT): Use the last weak definition if we don't
	see a strong one.

*** do-lookup.h.~1~	Wed Jun  7 23:31:03 2000
--- do-lookup.h	Thu May 30 13:11:46 2002
*************** FCT (const char *undef_name, struct link
*** 158,171 ****
  	  switch (ELFW(ST_BIND) (sym->st_info))
  	    {
  	    case STB_WEAK:
! 	      /* Weak definition.  Use this value if we don't find another.  */
  	      if (__builtin_expect (_dl_dynamic_weak, 0))
  		{
! 		  if (! result->s)
! 		    {
! 		      result->s = sym;
! 		      result->m = map;
! 		    }
  		  break;
  		}
  	      /* FALLTHROUGH */
--- 158,169 ----
  	  switch (ELFW(ST_BIND) (sym->st_info))
  	    {
  	    case STB_WEAK:
! 	      /* Weak definition.  Use the last one encountered if we don't
! 		 find a strong definition.  */
  	      if (__builtin_expect (_dl_dynamic_weak, 0))
  		{
! 		  result->s = sym;
! 		  result->m = map;
  		  break;
  		}
  	      /* FALLTHROUGH */

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