bfd_boolean provide)
{
struct elf_link_hash_entry *h;
+ struct elf_link_hash_table *htab;
if (!is_elf_hash_table (info->hash))
return TRUE;
- h = elf_link_hash_lookup (elf_hash_table (info), name, TRUE, TRUE, FALSE);
+ htab = elf_hash_table (info);
+ h = elf_link_hash_lookup (htab, name, !provide, TRUE, FALSE);
if (h == NULL)
- return FALSE;
+ return provide;
/* Since we're defining the symbol, don't let it seem to have not
been defined. record_dynamic_symbol and size_dynamic_sections
if (h->root.type == bfd_link_hash_undefweak
|| h->root.type == bfd_link_hash_undefined)
{
- struct elf_link_hash_table *htab = elf_hash_table (info);
-
+ h->root.type = bfd_link_hash_new;
if (h->root.u.undef.next != NULL || htab->root.undefs_tail == &h->root)
bfd_link_repair_undef_list (&htab->root);
- h->root.type = bfd_link_hash_new;
}
if (h->root.type == bfd_link_hash_new)
/* Called via elf_link_hash_traverse, elf_smash_syms sets all symbols
belonging to NOT_NEEDED to bfd_link_hash_new. We know there are no
- references to these symbols. */
+ references from regular objects to these symbols.
+
+ ??? Should we do something about references from other dynamic
+ obects? If not, we potentially lose some warnings about undefined
+ symbols. But how can we recover the initial undefined / undefweak
+ state? */
struct elf_smash_syms_data
{
return TRUE;
case bfd_link_hash_undefined:
+ if (h->root.u.undef.abfd != inf->not_needed)
+ return TRUE;
+ if (h->root.u.undef.weak != NULL
+ && h->root.u.undef.weak != inf->not_needed)
+ {
+ /* Symbol was undefweak in u.undef.weak bfd, and has become
+ undefined in as-needed lib. Restore weak. */
+ h->root.type = bfd_link_hash_undefweak;
+ h->root.u.undef.abfd = h->root.u.undef.weak;
+ if (h->root.u.undef.next != NULL
+ || inf->htab->root.undefs_tail == &h->root)
+ inf->twiddled = TRUE;
+ return TRUE;
+ }
+ break;
+
case bfd_link_hash_undefweak:
if (h->root.u.undef.abfd != inf->not_needed)
return TRUE;
break;
}
+ /* There is no way we can undo symbol table state from defined or
+ defweak back to undefined. */
+ if (h->ref_regular)
+ abort ();
+
/* Set sym back to newly created state, but keep undefs list pointer. */
bh = h->root.u.undef.next;
if (bh != NULL || inf->htab->root.undefs_tail == &h->root)
free (isymbuf);
isymbuf = NULL;
- if (!add_needed)
+ if (!add_needed
+ && (elf_dyn_lib_class (abfd) & DYN_AS_NEEDED) != 0)
{
+ /* Remove symbols defined in an as-needed shared lib that wasn't
+ needed. */
struct elf_smash_syms_data inf;
inf.not_needed = abfd;
inf.htab = hash_table;