x86: Simplify bad return in get_synthetic_symtab
[deliverable/binutils-gdb.git] / bfd / elf32-i386.c
index d66281654810b09a080348523058749ca35587f9..2826272e0648866c905db8c22c119a9311fd0a6d 100644 (file)
@@ -945,14 +945,28 @@ static const struct elf_i386_backend_data elf_i386_arch_bed =
    it isn't dynamic and
    1. Has non-GOT/non-PLT relocations in text section.  Or
    2. Has no GOT/PLT relocation.
+   Local undefined weak symbol is always resolved to 0.
  */
 #define UNDEFINED_WEAK_RESOLVED_TO_ZERO(INFO, GOT_RELOC, EH)   \
   ((EH)->elf.root.type == bfd_link_hash_undefweak              \
-   && bfd_link_executable (INFO)                               \
-   && (elf_i386_hash_table (INFO)->interp == NULL              \
-       || !(GOT_RELOC)                                         \
-       || (EH)->has_non_got_reloc                              \
-       || !(INFO)->dynamic_undefined_weak))
+   && ((EH)->elf.forced_local                                  \
+       || (bfd_link_executable (INFO)                          \
+          && (elf_i386_hash_table (INFO)->interp == NULL       \
+              || !(GOT_RELOC)                                  \
+              || (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.  */
 
@@ -993,10 +1007,11 @@ struct elf_i386_link_hash_entry
   /* Don't call finish_dynamic_symbol on this symbol.  */
   unsigned int no_finish_dynamic_symbol : 1;
 
-  /* 0: symbol isn't ___tls_get_addr.
-     1: symbol is ___tls_get_addr.
-     2: symbol is unknown.  */
-  unsigned int tls_get_addr : 2;
+  /* 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.  */
@@ -1147,7 +1162,8 @@ elf_i386_link_hash_newfunc (struct bfd_hash_entry *entry,
       eh->has_got_reloc = 0;
       eh->has_non_got_reloc = 0;
       eh->no_finish_dynamic_symbol = 0;
-      eh->tls_get_addr = 2;
+      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;
@@ -1376,7 +1392,7 @@ elf_i386_check_tls_transition (asection *sec,
   struct elf_link_hash_entry *h;
   bfd_vma offset;
   bfd_byte *call;
-  bfd_boolean indirect_call, tls_get_addr;
+  bfd_boolean indirect_call;
 
   offset = rel->r_offset;
   switch (r_type)
@@ -1481,29 +1497,9 @@ elf_i386_check_tls_transition (asection *sec,
       if (r_symndx < symtab_hdr->sh_info)
        return FALSE;
 
-      tls_get_addr = FALSE;
       h = sym_hashes[r_symndx - symtab_hdr->sh_info];
-      if (h != NULL && h->root.root.string != NULL)
-       {
-         struct elf_i386_link_hash_entry *eh
-           = (struct elf_i386_link_hash_entry *) h;
-         tls_get_addr = eh->tls_get_addr == 1;
-         if (eh->tls_get_addr > 1)
-           {
-             /* Use strncmp to check ___tls_get_addr since
-                ___tls_get_addr may be versioned.  */
-             if (strncmp (h->root.root.string, "___tls_get_addr", 15)
-                 == 0)
-               {
-                 eh->tls_get_addr = 1;
-                 tls_get_addr = TRUE;
-               }
-             else
-               eh->tls_get_addr = 0;
-           }
-       }
-
-      if (!tls_get_addr)
+      if (h == NULL
+         || !((struct elf_i386_link_hash_entry *) h)->tls_get_addr)
        return FALSE;
       else if (indirect_call)
        return (ELF32_R_TYPE (rel[1].r_info) == R_386_GOT32X);
@@ -1706,10 +1702,10 @@ elf_i386_tls_transition (struct bfd_link_info *info, bfd *abfd,
 
       _bfd_error_handler
        /* xgettext:c-format */
-       (_("%B: TLS transition from %s to %s against `%s' at 0x%lx "
+       (_("%B: TLS transition from %s to %s against `%s' at %#Lx "
           "in section `%A' failed"),
         abfd, from->name, to->name, name,
-        (unsigned long) rel->r_offset, sec);
+        rel->r_offset, sec);
       bfd_set_error (bfd_error_bad_value);
       return FALSE;
     }
@@ -1861,7 +1857,7 @@ convert_branch:
              modrm = 0xe8;
              /* To support TLS optimization, always use addr32 prefix
                 for "call *___tls_get_addr@GOT(%reg)".  */
-             if (eh && eh->tls_get_addr == 1)
+             if (eh && eh->tls_get_addr)
                {
                  nop = 0x67;
                  nop_offset = irel->r_offset - 2;
@@ -2035,7 +2031,7 @@ elf_i386_check_relocs (bfd *abfd,
   for (rel = relocs; rel < rel_end; rel++)
     {
       unsigned int r_type;
-      unsigned long r_symndx;
+      unsigned int r_symndx;
       struct elf_link_hash_entry *h;
       struct elf_i386_link_hash_entry *eh;
       Elf_Internal_Sym *isym;
@@ -2610,6 +2606,8 @@ elf_i386_adjust_dynamic_symbol (struct bfd_link_info *info,
        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.  */
@@ -2619,7 +2617,9 @@ elf_i386_adjust_dynamic_symbol (struct bfd_link_info *info,
                  || 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;
     }
@@ -2637,12 +2637,11 @@ elf_i386_adjust_dynamic_symbol (struct bfd_link_info *info,
   /* 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;
@@ -3937,14 +3936,8 @@ elf_i386_relocate_section (bfd *output_bfd,
              >= R_386_ext - R_386_standard)
          && ((indx = r_type - R_386_tls_offset) - R_386_ext
              >= R_386_ext2 - R_386_ext))
-       {
-         _bfd_error_handler
-           /* xgettext:c-format */
-           (_("%B: unrecognized relocation (0x%x) in section `%A'"),
-            input_bfd, r_type, input_section);
-         bfd_set_error (bfd_error_bad_value);
-         return FALSE;
-       }
+       return _bfd_unrecognized_reloc (input_bfd, input_section, r_type);
+
       howto = elf_howto_table + indx;
 
       r_symndx = ELF32_R_SYM (rel->r_info);
@@ -5367,10 +5360,10 @@ disallow_got32:
        {
          _bfd_error_handler
            /* xgettext:c-format */
-           (_("%B(%A+0x%lx): unresolvable %s relocation against symbol `%s'"),
+           (_("%B(%A+%#Lx): unresolvable %s relocation against symbol `%s'"),
             input_bfd,
             input_section,
-            (long) rel->r_offset,
+            rel->r_offset,
             howto->name,
             h->root.root.string);
          return FALSE;
@@ -5407,9 +5400,9 @@ check_relocation_error:
            {
              _bfd_error_handler
                /* xgettext:c-format */
-               (_("%B(%A+0x%lx): reloc against `%s': error %d"),
+               (_("%B(%A+%#Lx): reloc against `%s': error %d"),
                 input_bfd, input_section,
-                (long) rel->r_offset, name, (int) r);
+                rel->r_offset, name, (int) r);
              return FALSE;
            }
        }
@@ -6298,13 +6291,13 @@ elf_i386_get_synthetic_symtab (bfd *abfd,
                               asymbol **dynsyms,
                               asymbol **ret)
 {
-  long size, count, i, n;
+  long size, count, i, n, len;
   int j;
   unsigned int plt_got_offset, plt_entry_size;
   asymbol *s;
   bfd_byte *plt_contents;
   long dynrelcount, relsize;
-  arelent **dynrelbuf;
+  arelent **dynrelbuf, *p;
   const struct elf_i386_lazy_plt_layout *lazy_plt;
   const struct elf_i386_non_lazy_plt_layout *non_lazy_plt;
   const struct elf_i386_lazy_plt_layout *lazy_ibt_plt;
@@ -6333,16 +6326,6 @@ elf_i386_get_synthetic_symtab (bfd *abfd,
   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;
@@ -6369,7 +6352,7 @@ elf_i386_get_synthetic_symtab (bfd *abfd,
   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.  */
@@ -6385,7 +6368,9 @@ elf_i386_get_synthetic_symtab (bfd *abfd,
 
       /* 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,
@@ -6394,7 +6379,7 @@ elf_i386_get_synthetic_symtab (bfd *abfd,
              /* 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;
@@ -6407,7 +6392,7 @@ elf_i386_get_synthetic_symtab (bfd *abfd,
              /* 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;
@@ -6417,7 +6402,8 @@ elf_i386_get_synthetic_symtab (bfd *abfd,
        }
 
       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,
@@ -6429,7 +6415,8 @@ elf_i386_get_synthetic_symtab (bfd *abfd,
        }
 
       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,
@@ -6450,7 +6437,10 @@ elf_i386_get_synthetic_symtab (bfd *abfd,
        }
 
       if (plt_type == plt_unknown)
-       continue;
+       {
+         free (plt_contents);
+         continue;
+       }
 
       plts[j].sec = plt;
       plts[j].type = plt_type;
@@ -6487,18 +6477,35 @@ elf_i386_get_synthetic_symtab (bfd *abfd,
        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);
-  s = *ret = (asymbol *) bfd_zmalloc (size);
-  if (s == NULL)
+
+  /* Allocate space for @plt suffixes.  */
+  n = 0;
+  for (i = 0; i < dynrelcount; i++)
     {
-bad_return:
-      for (j = 0; plts[j].name != NULL; j++)
-       if (plts[j].contents != NULL)
-         free (plts[j].contents);
-      free (dynrelbuf);
-      return -1;
+      p = dynrelbuf[i];
+      size += strlen ((*p->sym_ptr_ptr)->name) + sizeof ("@plt");
+      if (p->addend != 0)
+       size += sizeof ("+0x") - 1 + 8;
     }
 
+  s = *ret = (asymbol *) bfd_zmalloc (size);
+  if (s == NULL)
+    goto bad_return;
+
   if (got_addr)
     {
       /* Check .got.plt and then .got to get the _GLOBAL_OFFSET_TABLE_
@@ -6518,6 +6525,7 @@ bad_return:
     }
 
   /* Check for each PLT section.  */
+  names = (char *) (s + count);
   size = 0;
   n = 0;
   for (j = 0; plts[j].name != NULL; j++)
@@ -6549,7 +6557,6 @@ bad_return:
            int off;
            bfd_vma got_vma;
            long min, max, mid;
-           arelent *p;
 
            /* Get the GOT offset, a signed 32-bit integer.  */
            off = H_GET_32 (abfd, (plt_contents + offset
@@ -6596,12 +6603,26 @@ bad_return:
                s->section = plt;
                s->the_bfd = plt->owner;
                s->value = offset;
-               /* Store relocation for later use.  */
-               s->udata.p = p;
-               /* Add @plt to function name later.  */
-               size += strlen (s->name) + sizeof ("@plt");
+               s->udata.p = NULL;
+               s->name = names;
+               len = strlen ((*p->sym_ptr_ptr)->name);
+               memcpy (names, (*p->sym_ptr_ptr)->name, len);
+               names += len;
                if (p->addend != 0)
-                 size += sizeof ("+0x") - 1 + 8;
+                 {
+                   char buf[30], *a;
+
+                   memcpy (names, "+0x", sizeof ("+0x") - 1);
+                   names += sizeof ("+0x") - 1;
+                   bfd_sprintf_vma (abfd, buf, p->addend);
+                   for (a = buf; *a == '0'; ++a)
+                     ;
+                   size = strlen (a);
+                   memcpy (names, a, size);
+                   names += size;
+                 }
+               memcpy (names, "@plt", sizeof ("@plt"));
+               names += sizeof ("@plt");
                n++;
                s++;
              }
@@ -6611,43 +6632,12 @@ bad_return:
 
   /* PLT entries with R_386_TLS_DESC relocations are skipped.  */
   if (n == 0)
-    goto bad_return;
-
-  count = n;
-
-  /* Allocate space for @plt suffixes.  */
-  names = (char *) bfd_malloc (size);
-  if (s == NULL)
-    goto bad_return;
-
-  s = *ret;
-  for (i = 0; i < count; i++)
     {
-      /* Add @plt to function name.  */
-      arelent *p = (arelent *) s->udata.p;
-      /* Clear it now.  */
-      s->udata.p = NULL;
-      size = strlen (s->name);
-      memcpy (names, s->name, size);
-      s->name = names;
-      names += size;
-      if (p->addend != 0)
-       {
-         char buf[30], *a;
-
-         memcpy (names, "+0x", sizeof ("+0x") - 1);
-         names += sizeof ("+0x") - 1;
-         bfd_sprintf_vma (abfd, buf, p->addend);
-         for (a = buf; *a == '0'; ++a)
-           ;
-         size = strlen (a);
-         memcpy (names, a, size);
-         names += size;
-       }
-      memcpy (names, "@plt", sizeof ("@plt"));
-      names += sizeof ("@plt");
-      s++;
+bad_return:
+      count = -1;
     }
+  else
+    count = n;
 
   for (j = 0; plts[j].name != NULL; j++)
     if (plts[j].contents != NULL)
@@ -6751,8 +6741,11 @@ elf_i386_merge_gnu_properties (struct bfd_link_info *info,
          features = 0;
          if (info->ibt)
            features = GNU_PROPERTY_X86_FEATURE_1_IBT;
+         if (info->shstk)
+           features |= GNU_PROPERTY_X86_FEATURE_1_SHSTK;
          number = aprop->u.number;
-         /* Add GNU_PROPERTY_X86_FEATURE_1_IBT.  */
+         /* Add GNU_PROPERTY_X86_FEATURE_1_IBT and
+            GNU_PROPERTY_X86_FEATURE_1_SHSTK.  */
          aprop->u.number = (number & bprop->u.number) | features;
          updated = number != (unsigned int) aprop->u.number;
          /* Remove the property if all feature bits are cleared.  */
@@ -6764,9 +6757,12 @@ elf_i386_merge_gnu_properties (struct bfd_link_info *info,
          features = 0;
          if (info->ibt)
            features = GNU_PROPERTY_X86_FEATURE_1_IBT;
+         if (info->shstk)
+           features |= GNU_PROPERTY_X86_FEATURE_1_SHSTK;
          if (features)
            {
-             /* Add GNU_PROPERTY_X86_FEATURE_1_IBT.  */
+             /* Add GNU_PROPERTY_X86_FEATURE_1_IBT and
+                GNU_PROPERTY_X86_FEATURE_1_SHSTK.  */
              if (aprop != NULL)
                {
                  number = aprop->u.number;
@@ -6809,46 +6805,41 @@ elf_i386_link_setup_gnu_properties (struct bfd_link_info *info)
   unsigned int plt_alignment, features;
   struct elf_i386_link_hash_table *htab;
   bfd *pbfd;
+  bfd *ebfd = NULL;
+  elf_property *prop;
 
   features = 0;
   if (info->ibt)
     features = GNU_PROPERTY_X86_FEATURE_1_IBT;
-  if (features)
-    {
-      /* Turn on GNU_PROPERTY_X86_FEATURE_1_IBT.  */
-      bfd *ebfd = NULL;
-      elf_property *prop;
-
-      for (pbfd = info->input_bfds;
-          pbfd != NULL;
-          pbfd = pbfd->link.next)
-       if (bfd_get_flavour (pbfd) == bfd_target_elf_flavour
-           && bfd_count_sections (pbfd) != 0)
-         {
-           ebfd = pbfd;
+  if (info->shstk)
+    features |= GNU_PROPERTY_X86_FEATURE_1_SHSTK;
+
+  /* Find a normal input file with GNU property note.  */
+  for (pbfd = info->input_bfds;
+       pbfd != NULL;
+       pbfd = pbfd->link.next)
+    if (bfd_get_flavour (pbfd) == bfd_target_elf_flavour
+       && bfd_count_sections (pbfd) != 0)
+      {
+       ebfd = pbfd;
 
-           if (elf_properties (pbfd) != NULL)
-             {
-               /* Find a normal input file with GNU property note.  */
-               prop = _bfd_elf_get_property (pbfd,
-                                             GNU_PROPERTY_X86_FEATURE_1_AND,
-                                             4);
-               /* Add GNU_PROPERTY_X86_FEATURE_1_IBT.  */
-               prop->u.number |= features;
-               prop->pr_kind = property_number;
-               break;
-             }
-         }
+       if (elf_properties (pbfd) != NULL)
+         break;
+      }
 
-      if (pbfd == NULL && ebfd != NULL)
-       {
-         /* Create GNU_PROPERTY_X86_FEATURE_1_IBT if needed.  */
-         prop = _bfd_elf_get_property (ebfd,
-                                       GNU_PROPERTY_X86_FEATURE_1_AND,
-                                       4);
-         prop->u.number = features;
-         prop->pr_kind = property_number;
+  if (ebfd != NULL && 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)
+       {
          sec = bfd_make_section_with_flags (ebfd,
                                             NOTE_GNU_PROPERTY_SECTION_NAME,
                                             (SEC_ALLOC
@@ -6861,7 +6852,11 @@ elf_i386_link_setup_gnu_properties (struct bfd_link_info *info)
            info->callbacks->einfo (_("%F: failed to create GNU property section\n"));
 
          if (!bfd_set_section_alignment (ebfd, sec, 2))
-           goto error_alignment;
+           {
+error_alignment:
+             info->callbacks->einfo (_("%F%A: failed to align section\n"),
+                                     sec);
+           }
 
          elf_section_type (sec) = SHT_NOTE;
        }
@@ -6902,20 +6897,29 @@ elf_i386_link_setup_gnu_properties (struct bfd_link_info *info)
      set it in check_relocs.  */
   if (dynobj == NULL)
     {
-      bfd *abfd;
-
-      /* Find a normal input file to hold linker created
-        sections.  */
-      for (abfd = info->input_bfds;
-          abfd != NULL;
-          abfd = abfd->link.next)
-       if ((abfd->flags
-            & (DYNAMIC | BFD_LINKER_CREATED | BFD_PLUGIN)) == 0)
-         {
-           htab->elf.dynobj = abfd;
-           dynobj = abfd;
-           break;
-         }
+      if (pbfd != NULL)
+       {
+         htab->elf.dynobj = pbfd;
+         dynobj = pbfd;
+       }
+      else
+       {
+         bfd *abfd;
+
+         /* Find a normal input file to hold linker created
+            sections.  */
+         for (abfd = info->input_bfds;
+              abfd != NULL;
+              abfd = abfd->link.next)
+           if (bfd_get_flavour (abfd) == bfd_target_elf_flavour
+               && (abfd->flags
+                   & (DYNAMIC | BFD_LINKER_CREATED | BFD_PLUGIN)) == 0)
+             {
+               htab->elf.dynobj = abfd;
+               dynobj = abfd;
+               break;
+             }
+       }
     }
 
   /* Even when lazy binding is disabled by "-z now", the PLT0 entry may
@@ -7007,7 +7011,7 @@ elf_i386_link_setup_gnu_properties (struct bfd_link_info *info)
     return pbfd;
 
   /* Since create_dynamic_sections isn't always called, but GOT
-     relocations need GOT relocations, create them here so that we
+     relocations need GOT sections, create them here so that we
      don't need to do it in check_relocs.  */
   if (htab->elf.sgot == NULL
       && !_bfd_elf_create_got_section (dynobj, info))
@@ -7132,16 +7136,44 @@ elf_i386_link_setup_gnu_properties (struct bfd_link_info *info)
       if (sec != NULL
          && !bfd_set_section_alignment (sec->owner, sec,
                                         plt_alignment))
-       {
-error_alignment:
-         info->callbacks->einfo (_("%F%A: failed to align section\n"),
-                                 sec);
-       }
+       goto error_alignment;
     }
 
   return pbfd;
 }
 
+static bfd_boolean
+elf_i386_link_check_relocs (bfd *abfd, struct bfd_link_info *info)
+{
+  if (!bfd_link_relocatable (info))
+    {
+      /* Check for ___tls_get_addr reference.  */
+      struct elf_link_hash_entry *h;
+      h = elf_link_hash_lookup (elf_hash_table (info), "___tls_get_addr",
+                               FALSE, FALSE, FALSE);
+      if (h != NULL)
+       ((struct elf_i386_link_hash_entry *) h)->tls_get_addr = 1;
+    }
+
+  /* Invoke the regular ELF backend linker to do all the work.  */
+  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
@@ -7172,6 +7204,7 @@ error_alignment:
 #define bfd_elf32_bfd_reloc_type_lookup              elf_i386_reloc_type_lookup
 #define bfd_elf32_bfd_reloc_name_lookup              elf_i386_reloc_name_lookup
 #define bfd_elf32_get_synthetic_symtab       elf_i386_get_synthetic_symtab
+#define bfd_elf32_bfd_link_check_relocs              elf_i386_link_check_relocs
 
 #define elf_backend_adjust_dynamic_symbol     elf_i386_adjust_dynamic_symbol
 #define elf_backend_relocs_compatible        _bfd_elf_relocs_compatible
@@ -7196,6 +7229,7 @@ error_alignment:
 #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"
 
This page took 0.032834 seconds and 4 git commands to generate.