|| (EH)->has_non_got_reloc \
|| !(INFO)->dynamic_undefined_weak))))
+/* Should copy relocation be generated for a symbol. Don't generate
+ copy relocation against a protected symbol defined in a shared
+ object with GNU_PROPERTY_NO_COPY_ON_PROTECTED. */
+#define SYMBOL_NO_COPYRELOC(INFO, EH) \
+ ((EH)->def_protected \
+ && ((EH)->elf.root.type == bfd_link_hash_defined \
+ || (EH)->elf.root.type == bfd_link_hash_defweak) \
+ && elf_has_no_copy_on_protected ((EH)->elf.root.u.def.section->owner) \
+ && ((EH)->elf.root.u.def.section->owner->flags & DYNAMIC) != 0 \
+ && ((EH)->elf.root.u.def.section->flags & SEC_CODE) == 0)
+
+
/* i386 ELF linker hash entry. */
struct elf_i386_link_hash_entry
/* Don't call finish_dynamic_symbol on this symbol. */
unsigned int no_finish_dynamic_symbol : 1;
- /* TRUE if symbol symbol is __tls_get_addr. */
+ /* TRUE if symbol is __tls_get_addr. */
unsigned int tls_get_addr : 1;
+ /* TRUE if symbol is defined as a protected symbol. */
+ unsigned int def_protected : 1;
+
/* Reference count of C/C++ function pointer relocations in read-write
section which can be resolved at run-time. */
bfd_signed_vma func_pointer_refcount;
eh->has_non_got_reloc = 0;
eh->no_finish_dynamic_symbol = 0;
eh->tls_get_addr = 0;
+ eh->def_protected = 0;
eh->func_pointer_refcount = 0;
eh->plt_got.offset = (bfd_vma) -1;
eh->tlsdesc_got = (bfd_vma) -1;
the link may change h->type. So fix it now. */
h->plt.offset = (bfd_vma) -1;
+ eh = (struct elf_i386_link_hash_entry *) h;
+
/* If this is a weak symbol, and there is a real definition, the
processor independent code will have arranged for us to see the
real definition first, and we can just use the same value. */
|| h->u.weakdef->root.type == bfd_link_hash_defweak);
h->root.u.def.section = h->u.weakdef->root.u.def.section;
h->root.u.def.value = h->u.weakdef->root.u.def.value;
- if (ELIMINATE_COPY_RELOCS || info->nocopyreloc)
+ if (ELIMINATE_COPY_RELOCS
+ || info->nocopyreloc
+ || SYMBOL_NO_COPYRELOC (info, eh))
h->non_got_ref = h->u.weakdef->non_got_ref;
return TRUE;
}
/* If there are no references to this symbol that do not use the
GOT nor R_386_GOTOFF relocation, we don't need to generate a copy
reloc. */
- eh = (struct elf_i386_link_hash_entry *) h;
if (!h->non_got_ref && !eh->gotoff_ref)
return TRUE;
/* If -z nocopyreloc was given, we won't generate them either. */
- if (info->nocopyreloc)
+ if (info->nocopyreloc || SYMBOL_NO_COPYRELOC (info, eh))
{
h->non_got_ref = 0;
return TRUE;
if (relsize <= 0)
return -1;
- dynrelbuf = (arelent **) bfd_malloc (relsize);
- if (dynrelbuf == NULL)
- return -1;
-
- dynrelcount = bfd_canonicalize_dynamic_reloc (abfd, dynrelbuf,
- dynsyms);
-
- /* Sort the relocs by address. */
- qsort (dynrelbuf, dynrelcount, sizeof (arelent *), compare_relocs);
-
non_lazy_plt = NULL;
/* Silence GCC 6. */
lazy_plt = NULL;
for (j = 0; plts[j].name != NULL; j++)
{
plt = bfd_get_section_by_name (abfd, plts[j].name);
- if (plt == NULL)
+ if (plt == NULL || plt->size == 0)
continue;
/* Get the PLT section contents. */
/* Check what kind of PLT it is. */
plt_type = plt_unknown;
- if (plts[j].type == plt_unknown)
+ if (plts[j].type == plt_unknown
+ && (plt->size >= (lazy_plt->plt0_entry_size
+ + lazy_plt->plt_entry_size)))
{
/* Match lazy PLT first. */
if (memcmp (plt_contents, lazy_plt->plt0_entry,
/* The fist entry in the lazy IBT PLT is the same as the
normal lazy PLT. */
if (lazy_ibt_plt != NULL
- && (memcmp (plt_contents + lazy_ibt_plt->plt_entry_size,
+ && (memcmp (plt_contents + lazy_ibt_plt->plt0_entry_size,
lazy_ibt_plt->plt_entry,
lazy_ibt_plt->plt_got_offset) == 0))
plt_type = plt_lazy | plt_second;
/* The fist entry in the PIC lazy IBT PLT is the same as
the normal PIC lazy PLT. */
if (lazy_ibt_plt != NULL
- && (memcmp (plt_contents + lazy_ibt_plt->plt_entry_size,
+ && (memcmp (plt_contents + lazy_ibt_plt->plt0_entry_size,
lazy_ibt_plt->pic_plt_entry,
lazy_ibt_plt->plt_got_offset) == 0))
plt_type = plt_lazy | plt_pic | plt_second;
}
if (non_lazy_plt != NULL
- && (plt_type == plt_unknown || plt_type == plt_non_lazy))
+ && (plt_type == plt_unknown || plt_type == plt_non_lazy)
+ && plt->size >= non_lazy_plt->plt_entry_size)
{
/* Match non-lazy PLT. */
if (memcmp (plt_contents, non_lazy_plt->plt_entry,
}
if ((non_lazy_ibt_plt != NULL)
- && (plt_type == plt_unknown || plt_type == plt_second))
+ && (plt_type == plt_unknown || plt_type == plt_second)
+ && plt->size >= non_lazy_ibt_plt->plt_entry_size)
{
if (memcmp (plt_contents,
non_lazy_ibt_plt->plt_entry,
}
if (plt_type == plt_unknown)
- continue;
+ {
+ free (plt_contents);
+ continue;
+ }
plts[j].sec = plt;
plts[j].type = plt_type;
got_addr = (bfd_vma) -1;
}
+ if (count == 0)
+ return -1;
+
+ dynrelbuf = (arelent **) bfd_malloc (relsize);
+ if (dynrelbuf == NULL)
+ return -1;
+
+ dynrelcount = bfd_canonicalize_dynamic_reloc (abfd, dynrelbuf,
+ dynsyms);
+
+ /* Sort the relocs by address. */
+ qsort (dynrelbuf, dynrelcount, sizeof (arelent *), compare_relocs);
+
size = count * sizeof (asymbol);
/* Allocate space for @plt suffixes. */
break;
}
- if (ebfd != NULL)
+ if (ebfd != NULL && features)
{
- if (features)
+ /* If features is set, add GNU_PROPERTY_X86_FEATURE_1_IBT and
+ GNU_PROPERTY_X86_FEATURE_1_SHSTK. */
+ prop = _bfd_elf_get_property (ebfd,
+ GNU_PROPERTY_X86_FEATURE_1_AND,
+ 4);
+ prop->u.number |= features;
+ prop->pr_kind = property_number;
+
+ /* Create the GNU property note section if needed. */
+ if (pbfd == NULL)
{
- /* If features is set, add GNU_PROPERTY_X86_FEATURE_1_IBT and
- GNU_PROPERTY_X86_FEATURE_1_SHSTK. */
- prop = _bfd_elf_get_property (ebfd,
- GNU_PROPERTY_X86_FEATURE_1_AND,
- 4);
- prop->u.number |= features;
- prop->pr_kind = property_number;
-
- /* Create the GNU property note section if needed. */
- if (pbfd == NULL)
- {
- sec = bfd_make_section_with_flags (ebfd,
- NOTE_GNU_PROPERTY_SECTION_NAME,
- (SEC_ALLOC
- | SEC_LOAD
- | SEC_IN_MEMORY
- | SEC_READONLY
- | SEC_HAS_CONTENTS
- | SEC_DATA));
- if (sec == NULL)
- info->callbacks->einfo (_("%F: failed to create GNU property section\n"));
+ sec = bfd_make_section_with_flags (ebfd,
+ NOTE_GNU_PROPERTY_SECTION_NAME,
+ (SEC_ALLOC
+ | SEC_LOAD
+ | SEC_IN_MEMORY
+ | SEC_READONLY
+ | SEC_HAS_CONTENTS
+ | SEC_DATA));
+ if (sec == NULL)
+ info->callbacks->einfo (_("%F: failed to create GNU property section\n"));
- if (!bfd_set_section_alignment (ebfd, sec, 2))
- {
+ if (!bfd_set_section_alignment (ebfd, sec, 2))
+ {
error_alignment:
- info->callbacks->einfo (_("%F%A: failed to align section\n"),
- sec);
- }
-
- elf_section_type (sec) = SHT_NOTE;
+ info->callbacks->einfo (_("%F%A: failed to align section\n"),
+ sec);
}
- }
-
- /* Check GNU_PROPERTY_NO_COPY_ON_PROTECTED. */
- for (; pbfd != NULL; pbfd = pbfd->link.next)
- if (bfd_get_flavour (pbfd) == bfd_target_elf_flavour
- && (pbfd->flags
- & (DYNAMIC | BFD_LINKER_CREATED | BFD_PLUGIN)) == 0)
- {
- elf_property_list *p;
- /* The property list is sorted in order of type. */
- for (p = elf_properties (pbfd); p != NULL; p = p->next)
- {
- if (GNU_PROPERTY_NO_COPY_ON_PROTECTED
- == p->property.pr_type)
- {
- /* Clear extern_protected_data if
- GNU_PROPERTY_NO_COPY_ON_PROTECTED is
- set on any input relocatable file. */
- info->extern_protected_data = FALSE;
- break;
- }
- else if (GNU_PROPERTY_NO_COPY_ON_PROTECTED
- < p->property.pr_type)
- break;
- }
- }
+ elf_section_type (sec) = SHT_NOTE;
+ }
}
pbfd = _bfd_elf_link_setup_gnu_properties (info);
return _bfd_elf_link_check_relocs (abfd, info);
}
+static void
+elf_i386_merge_symbol_attribute (struct elf_link_hash_entry *h,
+ const Elf_Internal_Sym *isym,
+ bfd_boolean definition,
+ bfd_boolean dynamic ATTRIBUTE_UNUSED)
+{
+ if (definition)
+ {
+ struct elf_i386_link_hash_entry *eh
+ = (struct elf_i386_link_hash_entry *) h;
+ eh->def_protected = (ELF_ST_VISIBILITY (isym->st_other)
+ == STV_PROTECTED);
+ }
+}
+
#define TARGET_LITTLE_SYM i386_elf32_vec
#define TARGET_LITTLE_NAME "elf32-i386"
#define ELF_ARCH bfd_arch_i386
#define elf_backend_parse_gnu_properties elf_i386_parse_gnu_properties
#define elf_backend_merge_gnu_properties elf_i386_merge_gnu_properties
#define elf_backend_setup_gnu_properties elf_i386_link_setup_gnu_properties
+#define elf_backend_merge_symbol_attribute elf_i386_merge_symbol_attribute
#include "elf32-target.h"