- {
- asection *plt, *gotplt, *relplt;
-
- /* Return and discard space for dynamic relocations against it if
- it is never referenced in a non-shared object. */
- if (!h->ref_regular)
- {
- if (h->plt.refcount > 0
- || h->got.refcount > 0)
- abort ();
- h->got.offset = (bfd_vma) -1;
- eh->dyn_relocs = NULL;
- return TRUE;
- }
-
- /* When building a static executable, use .iplt, .igot.plt and
- .rel.iplt sections for STT_GNU_IFUNC symbols. */
- if (htab->splt != NULL)
- {
- plt = htab->splt;
- gotplt = htab->sgotplt;
- relplt = htab->srelplt;
-
- /* If this is the first .plt entry, make room for the special
- first entry. */
- if (plt->size == 0)
- plt->size += PLT_ENTRY_SIZE;
- }
- else
- {
- plt = htab->iplt;
- gotplt = htab->igotplt;
- relplt = htab->irelplt;
- }
-
- /* Don't update value of STT_GNU_IFUNC symbol to PLT. We need
- the original value for R_386_IRELATIVE. */
- h->plt.offset = plt->size;
-
- /* Make room for this entry in the .plt/.iplt section. */
- plt->size += PLT_ENTRY_SIZE;
-
- /* We also need to make an entry in the .got.plt/.got.iplt
- section, which will be placed in the .got section by the
- linker script. */
- gotplt->size += 4;
-
- /* We also need to make an entry in the .rela.plt/.rela.iplt
- section. */
- relplt->size += sizeof (Elf32_External_Rel);
- relplt->reloc_count++;
-
- /* We need dynamic relocation for STT_GNU_IFUNC symbol only
- when there is a non-GOT reference in a shared object. */
- if (!info->shared
- || !h->non_got_ref)
- eh->dyn_relocs = NULL;
-
- /* Finally, allocate space. */
- for (p = eh->dyn_relocs; p != NULL; p = p->next)
- htab->irelifunc->size += p->count * sizeof (Elf32_External_Rel);
-
- /* For STT_GNU_IFUNC symbol, .got.plt has the real function
- addres and .got has the PLT entry adddress. We will load
- the GOT entry with the PLT entry in finish_dynamic_symbol if
- it is used. For branch, it uses .got.plt. For symbol value,
- 1. Use .got.plt in a shared object if it is forced local or
- not dynamic.
- 2. Use .got.plt in a non-shared object if pointer equality
- isn't needed.
- 3. Use .got.plt if .got isn't used.
- 4. Otherwise use .got so that it can be shared among different
- objects at run-time.
- We only need to relocate .got entry in shared object. */
- if ((info->shared
- && (h->dynindx == -1
- || h->forced_local))
- || (!info->shared
- && !h->pointer_equality_needed)
- || htab->sgot == NULL)
- {
- /* Use .got.plt. */
- h->got.offset = (bfd_vma) -1;
- }
- else
- {
- h->got.offset = htab->sgot->size;
- htab->sgot->size += 4;
- if (info->shared)
- htab->srelgot->size += sizeof (Elf32_External_Rel);
- }
-
- return TRUE;
- }