+/* This is the condition under which elf_i386_finish_dynamic_symbol
+ will be called from elflink.h. If elflink.h doesn't call our
+ finish_dynamic_symbol routine, we'll need to do something about
+ initializing any .plt and .got entries in elf_i386_relocate_section. */
+#define WILL_CALL_FINISH_DYNAMIC_SYMBOL(DYN, INFO, H) \
+ ((DYN) \
+ && ((INFO)->shared \
+ || ((H)->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0) \
+ && ((H)->dynindx != -1 \
+ || ((H)->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) != 0))
+
+/* Allocate space in .plt, .got and associated reloc sections for
+ global syms. Also discards space allocated for relocs in the
+ check_relocs function that we subsequently have found to be
+ unneeded. */
+
+static boolean
+allocate_plt_and_got_and_discard_relocs (h, inf)
+ struct elf_link_hash_entry *h;
+ PTR inf;
+{
+ struct bfd_link_info *info;
+ struct elf_i386_link_hash_table *htab;
+ asection *s;
+
+ if (h->root.type == bfd_link_hash_indirect
+ || h->root.type == bfd_link_hash_warning)
+ return true;
+
+ info = (struct bfd_link_info *) inf;
+ htab = elf_i386_hash_table (info);
+
+ if (htab->root.dynamic_sections_created
+ && h->plt.refcount > 0)
+ {
+ s = htab->splt;
+ if (s == NULL)
+ abort ();
+
+ /* If this is the first .plt entry, make room for the special
+ first entry. */
+ if (s->_raw_size == 0)
+ s->_raw_size += PLT_ENTRY_SIZE;
+
+ h->plt.offset = s->_raw_size;
+
+ /* If this symbol is not defined in a regular file, and we are
+ not generating a shared library, then set the symbol to this
+ location in the .plt. This is required to make function
+ pointers compare as equal between the normal executable and
+ the shared library. */
+ if (! info->shared
+ && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0)
+ {
+ h->root.u.def.section = s;
+ h->root.u.def.value = h->plt.offset;
+ }
+
+ /* Make room for this entry. */
+ s->_raw_size += PLT_ENTRY_SIZE;
+
+ /* We also need to make an entry in the .got.plt section, which
+ will be placed in the .got section by the linker script. */
+ s = htab->sgotplt;
+ if (s == NULL)
+ abort ();
+ s->_raw_size += 4;
+
+ if (WILL_CALL_FINISH_DYNAMIC_SYMBOL (1, info, h))
+ {
+ /* We also need to make an entry in the .rel.plt section. */
+ s = htab->srelplt;
+ if (s == NULL)
+ abort ();
+ s->_raw_size += sizeof (Elf32_External_Rel);
+ }
+ }
+ else
+ {
+ h->plt.offset = (bfd_vma) -1;
+ h->elf_link_hash_flags &= ~ELF_LINK_HASH_NEEDS_PLT;
+ }
+
+ if (h->got.refcount > 0)
+ {
+ boolean dyn;
+
+ s = htab->sgot;
+ h->got.offset = s->_raw_size;
+ s->_raw_size += 4;
+ dyn = htab->root.dynamic_sections_created;
+ if (WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, info, h))
+ htab->srelgot->_raw_size += sizeof (Elf32_External_Rel);
+ }
+ else
+ h->got.offset = (bfd_vma) -1;
+
+ /* In the shared -Bsymbolic case, discard space allocated to copy
+ PC relative relocs against symbols which turn out to be defined
+ in regular objects. For the normal shared case, discard space
+ for relocs that have become local due to symbol visibility
+ changes. For the non-shared case, discard space for symbols
+ which turn out to need copy relocs or are not dynamic. */
+
+ if ((info->shared
+ && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) != 0
+ && ((h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) != 0
+ || info->symbolic))
+ || (!info->shared
+ && ((h->elf_link_hash_flags & ELF_LINK_NON_GOT_REF) != 0
+ || h->dynindx == -1)))
+ {
+ struct elf_i386_link_hash_entry *eh;
+ struct elf_i386_dyn_relocs *c;
+
+ eh = (struct elf_i386_link_hash_entry *) h;
+ for (c = eh->dyn_relocs; c != NULL; c = c->next)
+ c->section->_raw_size -= c->count * sizeof (Elf32_External_Rel);
+ }
+
+ return true;
+}
+