if (use_plt_got
&& h != NULL
&& h->plt.refcount > 0
- && h->got.refcount > 0
+ && (((info->flags & DF_BIND_NOW) && !h->pointer_equality_needed)
+ || h->got.refcount > 0)
&& htab->plt_got == NULL)
{
/* Create the GOT procedure linkage table. */
else if (htab->elf.dynamic_sections_created
&& (h->plt.refcount > 0 || eh->plt_got.refcount > 0))
{
- bfd_boolean use_plt_got = eh->plt_got.refcount > 0;
+ bfd_boolean use_plt_got;
+
+ if ((info->flags & DF_BIND_NOW) && !h->pointer_equality_needed)
+ {
+ /* Don't use the regular PLT for DF_BIND_NOW. */
+ h->plt.offset = (bfd_vma) -1;
+
+ /* Use the GOT PLT. */
+ h->got.refcount = 1;
+ eh->plt_got.refcount = 1;
+ }
+
+ use_plt_got = eh->plt_got.refcount > 0;
/* Make sure this symbol is output as a dynamic symbol.
Undefined weak syms won't yet be marked as dynamic. */
asection *bnd_s = htab->plt_bnd;
asection *got_s = htab->plt_got;
- /* If this is the first .plt entry, make room for the special
- first entry. */
- if (s->size == 0)
- s->size = plt_entry_size;
-
if (use_plt_got)
eh->plt_got.offset = got_s->size;
else
{
+ /* If this is the first .plt entry, make room for the
+ special first entry. */
+ if (s->size == 0)
+ s->size = plt_entry_size;
h->plt.offset = s->size;
if (bnd_s)
eh->plt_bnd.offset = bnd_s->size;
/* STT_GNU_IFUNC must keep R_X86_64_GOTPCREL relocation. */
if (ELF_ST_TYPE (isym->st_info) != STT_GNU_IFUNC
&& irel->r_offset >= 2
- && bfd_get_8 (input_bfd,
- contents + irel->r_offset - 2) == 0x8b)
+ && bfd_get_8 (abfd, contents + irel->r_offset - 2) == 0x8b)
{
- bfd_put_8 (output_bfd, 0x8d,
- contents + irel->r_offset - 2);
+ bfd_put_8 (abfd, 0x8d, contents + irel->r_offset - 2);
irel->r_info = htab->r_info (r_symndx, R_X86_64_PC32);
if (local_got_refcounts != NULL
&& local_got_refcounts[r_symndx] > 0)
&& h != htab->elf.hdynamic
&& SYMBOL_REFERENCES_LOCAL (link_info, h)
&& irel->r_offset >= 2
- && bfd_get_8 (input_bfd,
- contents + irel->r_offset - 2) == 0x8b)
+ && bfd_get_8 (abfd, contents + irel->r_offset - 2) == 0x8b)
{
- bfd_put_8 (output_bfd, 0x8d,
- contents + irel->r_offset - 2);
+ bfd_put_8 (abfd, 0x8d, contents + irel->r_offset - 2);
irel->r_info = htab->r_info (r_symndx, R_X86_64_PC32);
if (h->got.refcount > 0)
h->got.refcount -= 1;
/* Relocation is relative to the start of the global offset
table. */
- /* Check to make sure it isn't a protected function symbol
- for shared library since it may not be local when used
- as function address. */
- if (!info->executable
- && h
- && !SYMBOLIC_BIND (info, h)
- && h->def_regular
- && h->type == STT_FUNC
- && ELF_ST_VISIBILITY (h->other) == STV_PROTECTED)
+ /* Check to make sure it isn't a protected function or data
+ symbol for shared library since it may not be local when
+ used as function address or with copy relocation. We also
+ need to make sure that a symbol is referenced locally. */
+ if (info->shared && h)
{
- (*_bfd_error_handler)
- (_("%B: relocation R_X86_64_GOTOFF64 against protected function `%s' can not be used when making a shared object"),
- input_bfd, h->root.root.string);
- bfd_set_error (bfd_error_bad_value);
+ if (!h->def_regular)
+ {
+ const char *v;
+
+ switch (ELF_ST_VISIBILITY (h->other))
+ {
+ case STV_HIDDEN:
+ v = _("hidden symbol");
+ break;
+ case STV_INTERNAL:
+ v = _("internal symbol");
+ break;
+ case STV_PROTECTED:
+ v = _("protected symbol");
+ break;
+ default:
+ v = _("symbol");
+ break;
+ }
+
+ (*_bfd_error_handler)
+ (_("%B: relocation R_X86_64_GOTOFF64 against undefined %s `%s' can not be used when making a shared object"),
+ input_bfd, v, h->root.root.string);
+ bfd_set_error (bfd_error_bad_value);
+ return FALSE;
+ }
+ else if (!info->executable
+ && !SYMBOL_REFERENCES_LOCAL (info, h)
+ && (h->type == STT_FUNC
+ || h->type == STT_OBJECT)
+ && ELF_ST_VISIBILITY (h->other) == STV_PROTECTED)
+ {
+ (*_bfd_error_handler)
+ (_("%B: relocation R_X86_64_GOTOFF64 against protected %s `%s' can not be used when making a shared object"),
+ input_bfd,
+ h->type == STT_FUNC ? "function" : "data",
+ h->root.root.string);
+ bfd_set_error (bfd_error_bad_value);
return FALSE;
+ }
}
/* Note that sgot is not involved in this
else
plt_sym_val[reloc_index] = plt->vma + plt_offset;
plt_offset += bed->plt_entry_size;
+
+ /* PR binutils/18437: Skip extra relocations in the .rela.plt
+ section. */
+ if (plt_offset >= plt->size)
+ break;
}
free (plt_contents);