This is the mail archive of the binutils@sourceware.org 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 defined symbols in shared object lost by dynamic link?


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


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