This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
weak defined symbols in shared object lost by dynamic link?
- From: sbalfour at cisco dot com
- To: binutils at sourceware dot org
- Cc: sbalfour at cisco dot com
- Date: Tue, 8 Aug 2006 18:24:37 -0700 (PDT)
- Subject: weak defined symbols in shared object lost by dynamic link?
- Authentication-results: sj-dkim-4.cisco.com; header.From=sbalfour@cisco.com; dkim=pass ( sig from cisco.com verified; );
- Dkim-signature: a=rsa-sha1; q=dns; l=3415; t=1155086677; x=1155950677; c=relaxed/simple; s=sjdkim4002; h=Content-Type:From:Subject:Content-Transfer-Encoding:MIME-Version; d=cisco.com; i=sbalfour@cisco.com; z=From:sbalfour@cisco.com |Subject:weak=20defined=20symbols=20in=20shared=20object=20lost=20by=20dynamic=20 link?; X=v=3Dcisco.com=3B=20h=3DSMFO5pXbyXZH+4WsR0VPseykF0k=3D; b=ZxLA/SdVc8VTqsumamk5cTVCUd9NhCy9O20b3JsddAPfvmSKBTZgh9WQO7UF/Is2fwuc3Txz 0DZ7aAyqgBwHLlS7yLAYOCBRm+4r4rdZBL9rd77OQY5MRRGX3YhO17lp;
Folks,
I have a case where I'm linking a dynamic executable. One of the link objects
is a shared object which defines and uses the symbols "etext", "edata" and
"end". They got to be defined by that shared object via a PROVIDE in the
linker script used to produce the shared object. They show up in the .so
dynamic symbol table as type "V" and have non-zero values. In the linked
executable, these same symbols are again supplied by the default linker
script, and they show up as type "A" with zero values. The resulting
executable crashes because of it. During linking of the executable, I get
three of these:
ld: BFD 2.14 20030612 assertion fail ../srcgcc/bfd/elflink.h:4168
The problem also occurs on binutils-2.15. The problem occurs here in elflink.c
in binutils-2.15 (the code looks the same in binutils-2.16):
/* If this symbol is being provided by the linker script, and it is
currently defined by a dynamic object, but not by a regular
object, then mark it as undefined so that the generic linker will
force the correct value. */
if (provide
&& (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC) != 0
&& (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0)
{
h->root.type = bfd_link_hash_undefined;
}
The symbols come in as bfd_link_hash_defweak and in a related case,
bfd_link_hash_defined, with h->weakdef non-zero. The first
obvious problem is that if we here pretend they're actually undefined,
we must zero h->weakdef. That's the direct cause of the BFD ASSERTS.
But the executable is still wrong - the definitions of these symbols
supplied by the shared object have been thrown away. Since the linker
script crafted for the shared object had these definitions placed there
because specific values were needed, the values obtained from the default
linker script used to link the executable are just wrong (they shouldn't
be zero, in any case).
I don't think either the comment or code are right. At a minimum, I
propose this:
/* If this symbol is being provided by the linker script, and it is
currently weak undefined symbol in a dynamic object, and not defined
by a regular object, then mark it as undefined so that the generic
linker will force the correct value. */
if (provide
&& (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC) != 0
&& (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0)
{
if (!(h->root.type == bfd_link_hash_defweak
|| h->root.type == bfd_link_hash_defined))
h->root.type = bfd_link_hash_undefined;
}
That's a minimalist pastiche, but it solves the problem. What we really appear
to want to catch here are the bfd_link_hash_new cases created from old
bfd_link_hash_undefweak symbols, created just above:
/* Since we're defining the symbol, don't let it seem to have not
been defined. record_dynamic_symbol and size_dynamic_sections
may depend on this. */
if (h->root.type == bfd_link_hash_undefweak
|| h->root.type == bfd_link_hash_undefined)
h->root.type = bfd_link_hash_new;
If the only effect is to change a weak undefined symbol to a (generic)
undefined symbol, do we need to do anything at all? I.e. is it correct to
just delete the code? I know, hacky-slash. What's really wrong, then?
Stuart