+/* 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 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
+{
+ bfd *not_needed;
+ struct elf_link_hash_table *htab;
+ bfd_boolean twiddled;
+};
+
+static bfd_boolean
+elf_smash_syms (struct elf_link_hash_entry *h, void *data)
+{
+ struct elf_smash_syms_data *inf = (struct elf_smash_syms_data *) data;
+ struct bfd_link_hash_entry *bh;
+
+ switch (h->root.type)
+ {
+ default:
+ case bfd_link_hash_new:
+ 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;
+
+ case bfd_link_hash_defined:
+ case bfd_link_hash_defweak:
+ if (h->root.u.def.section->owner != inf->not_needed)
+ return TRUE;
+ break;
+
+ case bfd_link_hash_common:
+ if (h->root.u.c.p->section->owner != inf->not_needed)
+ return TRUE;
+ break;
+
+ case bfd_link_hash_warning:
+ case bfd_link_hash_indirect:
+ elf_smash_syms ((struct elf_link_hash_entry *) h->root.u.i.link, data);
+ if (h->root.u.i.link->type != bfd_link_hash_new)
+ return TRUE;
+ if (h->root.u.i.link->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)
+ inf->twiddled = TRUE;
+ (*inf->htab->root.table.newfunc) (&h->root.root,
+ &inf->htab->root.table,
+ h->root.root.string);
+ h->root.u.undef.next = bh;
+ h->root.u.undef.abfd = inf->not_needed;
+ h->non_elf = 0;
+ return TRUE;
+}
+