This is the mail archive of the
binutils@sourceware.cygnus.com
mailing list for the binutils project.
shared libs: is it (whose?) bug?
- To: binutils <binutils@sourceware.cygnus.com>
- Subject: shared libs: is it (whose?) bug?
- From: Donn Terry <donn@interix.com>
- Date: Thu, 09 Sep 1999 10:25:35 -0600
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