This is the mail archive of the binutils@sourceware.cygnus.com 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]

shared libs: is it (whose?) bug?


I hope this isn't old territory, but I don't even have a clue
for a search key on archives that wouldn't give me too much,
given that I haven't seen this discussed.

I'm not sure whether this even is a bug, and if so, whose.
There definitely is a behavior difference between various
versions of ld, and it's arguable which is "right".

When using shared libraries, and using the Solaris linker,
it is possible for a dynamically loaded (using dlopen())
shared library to call back to the main executable, to an
entry point that was not mentioned as a dynamic symbol
at link time (details below).  Using the gnu ld, this
is not possible due to dynamic symbol table issues.
I've attached a small test case that shows the failure in detail.

Here's what's going on:
  On solaris, it appears that ALL symbols defined in the main
  executable are included in the dynamic symbol table.
  Using the gnu tools (on both Interix and Linux), only those
  symbols explicitly mentioned at link time as dynamic symbols
  get put into the dynamic symbol table.

  In the application, a shared library is created and brought
  into the execution by dlopen(), but is *not* mentioned at link
  time.  It calls an entry point in the main program.  On solaris,
  this works, on Linux and Interix, it fails identically.  On
  Unixware, it fails (rather more obscurely).

In bfd/elflink.h, the critical piece of code is:

          if (! dynamic)
            {
              if (! definition)
                {
                  new_flag = ELF_LINK_HASH_REF_REGULAR;
                  if (bind != STB_WEAK)
                    new_flag |= ELF_LINK_HASH_REF_REGULAR_NONWEAK;
                }
              else
                new_flag = ELF_LINK_HASH_DEF_REGULAR;
              if (info->shared
                  ^^^^^^^^^^^^         <<<<<<<  The critical test
                  || (old_flags & (ELF_LINK_HASH_DEF_DYNAMIC
                                   | ELF_LINK_HASH_REF_DYNAMIC)) != 0)
                dynsym = true;
            }
          else
            {
              if (! definition)
                new_flag = ELF_LINK_HASH_REF_DYNAMIC;
              else
                new_flag = ELF_LINK_HASH_DEF_DYNAMIC;
              if ((old_flags & (ELF_LINK_HASH_DEF_REGULAR
                                | ELF_LINK_HASH_REF_REGULAR)) != 0


If the info->shared clause is deleted, all symbols get exported
and the test case works.

It's easy enough to create a dummy shared library that calls the
entry points (but which is itself never called) that causes the
symbols to be exported, and the application then also works.

Both the X/Open SUS and the Solaris man page have a paragraph about
what symbols are actually exported, and in effect they both say
"you get what you get".  (At least the SUS says "implementation
defined"; Solaris is an implementation and still doesn't say.)
(All the wording in this space is exceptionally vague, and subject
to a lot of varying interpretations.)

Given all that: is this something that should be changed (fixed
is too strong) in the Gnu tools, or is there a reason for this
test (and the use of that "feature" on Solaris is then presumed
to be incorrect).

Donn

-- 

===================================================
Donn Terry                  mailto:donn@interix.com
Softway Systems, Inc.        http://www.interix.com
2850 McClelland Dr, Ste. 1800   Ft.Collins CO 80525
Tel: +1-970-204-9900           Fax: +1-970-204-9951
===================================================

dlopen_test.tar.gz


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