* elf-m10300.c (mn10300_elf_check_relocs): Delete dead code.
[deliverable/binutils-gdb.git] / bfd / elfxx-mips.c
index e4ddb37cd42e381ef2140342cbd3316513700752..b2fcc9c50673281bef596d01bae65e217a22b1d7 100644 (file)
@@ -13,7 +13,7 @@
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
+   the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.
 
    This program is distributed in the hope that it will be useful,
@@ -23,7 +23,9 @@
 
    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
-   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
+   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+   MA 02110-1301, USA.  */
+
 
 /* This file handles functionality common to the different MIPS ABI's.  */
 
@@ -321,8 +323,12 @@ struct mips_elf_link_hash_table
   bfd_vma rld_value;
   /* This is set if we see any mips16 stub sections.  */
   bfd_boolean mips16_stubs_seen;
+  /* True if we've computed the size of the GOT.  */
+  bfd_boolean computed_got_sizes;
   /* True if we're generating code for VxWorks.  */
   bfd_boolean is_vxworks;
+  /* True if we already reported the small-data section overflow.  */
+  bfd_boolean small_data_overflow_reported;
   /* Shortcuts to some dynamic sections, or NULL if they are not
      being used.  */
   asection *srelbss;
@@ -2687,7 +2693,7 @@ mips_elf_create_local_got_entry (bfd *abfd, struct bfd_link_info *info,
 
   memcpy (*loc, &entry, sizeof entry);
 
-  if (g->assigned_gotno >= g->local_gotno)
+  if (g->assigned_gotno > g->local_gotno)
     {
       (*loc)->gotidx = -1;
       /* We didn't allocate enough space in the GOT.  */
@@ -2872,11 +2878,15 @@ mips_elf_record_global_got_symbol (struct elf_link_hash_entry *h,
   if (h->got.offset != MINUS_ONE)
     return TRUE;
 
-  /* By setting this to a value other than -1, we are indicating that
-     there needs to be a GOT entry for H.  Avoid using zero, as the
-     generic ELF copy_indirect_symbol tests for <= 0.  */
   if (tls_flag == 0)
-    h->got.offset = 1;
+    {
+      /* By setting this to a value other than -1, we are indicating that
+        there needs to be a GOT entry for H.  Avoid using zero, as the
+        generic ELF copy_indirect_symbol tests for <= 0.  */
+      h->got.offset = 1;
+      if (h->forced_local)
+       g->local_gotno++;
+    }
 
   return TRUE;
 }
@@ -3186,6 +3196,7 @@ mips_elf_initialize_tls_index (void **entryp, void *p)
   struct mips_got_entry *entry = (struct mips_got_entry *)*entryp;
   struct mips_got_info *g = p;
   bfd_vma next_index;
+  unsigned char tls_type;
 
   /* We're only interested in TLS symbols.  */
   if (entry->tls_type == 0)
@@ -3201,6 +3212,7 @@ mips_elf_initialize_tls_index (void **entryp, void *p)
        return 1;
       entry->d.h->tls_type |= GOT_TLS_OFFSET_DONE;
       entry->d.h->tls_got_offset = next_index;
+      tls_type = entry->d.h->tls_type;
     }
   else
     {
@@ -3217,12 +3229,13 @@ mips_elf_initialize_tls_index (void **entryp, void *p)
          g->tls_ldm_offset = next_index;
        }
       entry->gotidx = next_index;
+      tls_type = entry->tls_type;
     }
 
   /* Account for the entries we've just allocated.  */
-  if (entry->tls_type & (GOT_TLS_GD | GOT_TLS_LDM))
+  if (tls_type & (GOT_TLS_GD | GOT_TLS_LDM))
     g->tls_assigned_gotno += 2;
-  if (entry->tls_type & GOT_TLS_IE)
+  if (tls_type & GOT_TLS_IE)
     g->tls_assigned_gotno += 1;
 
   return 1;
@@ -4089,8 +4102,7 @@ mips_elf_calculate_relocation (bfd *abfd, bfd *input_bfd,
   /* If this is a 16-bit call to a 32- or 64-bit function with a stub, we
      need to redirect the call to the stub.  */
   else if (r_type == R_MIPS16_26 && !info->relocatable
-          && h != NULL
-          && ((h->call_stub != NULL || h->call_fp_stub != NULL)
+          && ((h != NULL && (h->call_stub != NULL || h->call_fp_stub != NULL))
               || (local_p
                   && elf_tdata (input_bfd)->local_call_stubs != NULL
                   && elf_tdata (input_bfd)->local_call_stubs[r_symndx] != NULL))
@@ -4353,6 +4365,8 @@ mips_elf_calculate_relocation (bfd *abfd, bfd *input_bfd,
       break;
 
     case R_MIPS_TLS_DTPREL_LO16:
+    case R_MIPS_TLS_DTPREL32:
+    case R_MIPS_TLS_DTPREL64:
       value = (symbol + addend - dtprel_base (info)) & howto->dst_mask;
       break;
 
@@ -6520,7 +6534,7 @@ _bfd_mips_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
              /* VxWorks call relocations point the function's .got.plt
                 entry, which will be allocated by adjust_dynamic_symbol.
                 Otherwise, this symbol requires a global GOT entry.  */
-             if (!htab->is_vxworks
+             if ((!htab->is_vxworks || h->forced_local)
                  && !mips_elf_record_global_got_symbol (h, abfd, info, g, 0))
                return FALSE;
 
@@ -6695,7 +6709,9 @@ _bfd_mips_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
          /* This relocation describes which C++ vtable entries are actually
             used.  Record for later use during GC.  */
        case R_MIPS_GNU_VTENTRY:
-         if (!bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_offset))
+         BFD_ASSERT (h != NULL);
+         if (h != NULL
+             && !bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_offset))
            return FALSE;
          break;
 
@@ -7304,6 +7320,7 @@ _bfd_mips_elf_always_size_sections (bfd *output_bfd,
       g->tls_assigned_gotno = g->global_gotno + g->local_gotno;
       htab_traverse (g->got_entries, mips_elf_initialize_tls_index, g);
     }
+  htab->computed_got_sizes = TRUE;
 
   return TRUE;
 }
@@ -8026,7 +8043,21 @@ _bfd_mips_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
            ;
          else
            {
+             struct mips_elf_link_hash_table *htab;
+
+             htab = mips_elf_hash_table (info);
              BFD_ASSERT (name != NULL);
+             if (!htab->small_data_overflow_reported
+                 && (howto->type == R_MIPS_GPREL16
+                     || howto->type == R_MIPS_LITERAL))
+               {
+                 const char *msg =
+                   _("small-data section exceeds 64KB;"
+                     " lower small-data size limit (see option -G)");
+
+                 htab->small_data_overflow_reported = TRUE;
+                 (*info->callbacks->einfo) ("%P: %s\n", msg);
+               }
              if (! ((*info->callbacks->reloc_overflow)
                     (info, NULL, name, howto->name, (bfd_vma) 0,
                      input_bfd, input_section, rel->r_offset)))
@@ -8879,7 +8910,8 @@ _bfd_mips_elf_finish_dynamic_sections (bfd *output_bfd,
        memset (b - dyn_skipped, 0, dyn_skipped);
     }
 
-  if (sgot != NULL && sgot->size > 0)
+  if (sgot != NULL && sgot->size > 0
+      && !bfd_is_abs_section (sgot->output_section))
     {
       if (htab->is_vxworks)
        {
@@ -9649,6 +9681,7 @@ _bfd_mips_elf_hide_symbol (struct bfd_link_info *info,
   asection *got;
   struct mips_got_info *g;
   struct mips_elf_link_hash_entry *h;
+  struct mips_elf_link_hash_table *htab;
 
   h = (struct mips_elf_link_hash_entry *) entry;
   if (h->forced_local)
@@ -9656,6 +9689,7 @@ _bfd_mips_elf_hide_symbol (struct bfd_link_info *info,
   h->forced_local = force_local;
 
   dynobj = elf_hash_table (info)->dynobj;
+  htab = mips_elf_hash_table (info);
   if (dynobj != NULL && force_local && h->root.type != STT_TLS
       && (got = mips_elf_got_section (dynobj, TRUE)) != NULL
       && (g = mips_elf_section_data (got)->u.got_info) != NULL)
@@ -9693,20 +9727,30 @@ _bfd_mips_elf_hide_symbol (struct bfd_link_info *info,
              gg->assigned_gotno--;
            }
        }
-      else if (g->global_gotno == 0 && g->global_gotsym == NULL)
-       /* If we haven't got through GOT allocation yet, just bump up the
-          number of local entries, as this symbol won't be counted as
-          global.  */
-       g->local_gotno++;
       else if (h->root.got.offset == 1)
        {
-         /* If we're past non-multi-GOT allocation and this symbol had
-            been marked for a global got entry, give it a local entry
-            instead.  */
-         BFD_ASSERT (g->global_gotno > 0);
+         /* check_relocs didn't know that this symbol would be
+            forced-local, so add an extra local got entry.  */
          g->local_gotno++;
-         g->global_gotno--;
+         if (htab->computed_got_sizes)
+           {
+             /* We'll have treated this symbol as global rather
+                than local.  */
+             BFD_ASSERT (g->global_gotno > 0);
+             g->global_gotno--;
+           }
        }
+      else if (htab->is_vxworks && h->root.needs_plt)
+       {
+         /* check_relocs didn't know that this symbol would be
+            forced-local, so add an extra local got entry.  */
+         g->local_gotno++;
+         if (htab->computed_got_sizes)
+           /* The symbol is only used in call relocations, so we'll
+              have assumed it only needs a .got.plt entry.  Increase
+              the size of .got accordingly.  */
+           got->size += MIPS_ELF_GOT_SIZE (dynobj);
+        }
     }
 
   _bfd_elf_link_hash_hide_symbol (info, &h->root, force_local);
@@ -10167,7 +10211,9 @@ _bfd_mips_elf_link_hash_table_create (bfd *abfd)
   ret->use_rld_obj_head = FALSE;
   ret->rld_value = 0;
   ret->mips16_stubs_seen = FALSE;
+  ret->computed_got_sizes = FALSE;
   ret->is_vxworks = FALSE;
+  ret->small_data_overflow_reported = FALSE;
   ret->srelbss = NULL;
   ret->sdynbss = NULL;
   ret->srelplt = NULL;
@@ -10958,6 +11004,112 @@ mips_32bit_flags_p (flagword flags)
 }
 
 
+/* Merge object attributes from IBFD into OBFD.  Raise an error if
+   there are conflicting attributes.  */
+static bfd_boolean
+mips_elf_merge_obj_attributes (bfd *ibfd, bfd *obfd)
+{
+  obj_attribute *in_attr;
+  obj_attribute *out_attr;
+
+  if (!elf_known_obj_attributes_proc (obfd)[0].i)
+    {
+      /* This is the first object.  Copy the attributes.  */
+      _bfd_elf_copy_obj_attributes (ibfd, obfd);
+
+      /* Use the Tag_null value to indicate the attributes have been
+        initialized.  */
+      elf_known_obj_attributes_proc (obfd)[0].i = 1;
+
+      return TRUE;
+    }
+
+  /* Check for conflicting Tag_GNU_MIPS_ABI_FP attributes and merge
+     non-conflicting ones.  */
+  in_attr = elf_known_obj_attributes (ibfd)[OBJ_ATTR_GNU];
+  out_attr = elf_known_obj_attributes (obfd)[OBJ_ATTR_GNU];
+  if (in_attr[Tag_GNU_MIPS_ABI_FP].i != out_attr[Tag_GNU_MIPS_ABI_FP].i)
+    {
+      out_attr[Tag_GNU_MIPS_ABI_FP].type = 1;
+      if (out_attr[Tag_GNU_MIPS_ABI_FP].i == 0)
+       out_attr[Tag_GNU_MIPS_ABI_FP].i = in_attr[Tag_GNU_MIPS_ABI_FP].i;
+      else if (in_attr[Tag_GNU_MIPS_ABI_FP].i == 0)
+       ;
+      else if (in_attr[Tag_GNU_MIPS_ABI_FP].i > 3)
+       _bfd_error_handler
+         (_("Warning: %B uses unknown floating point ABI %d"), ibfd,
+          in_attr[Tag_GNU_MIPS_ABI_FP].i);
+      else if (out_attr[Tag_GNU_MIPS_ABI_FP].i > 3)
+       _bfd_error_handler
+         (_("Warning: %B uses unknown floating point ABI %d"), obfd,
+          out_attr[Tag_GNU_MIPS_ABI_FP].i);
+      else
+       switch (out_attr[Tag_GNU_MIPS_ABI_FP].i)
+         {
+         case 1:
+           switch (in_attr[Tag_GNU_MIPS_ABI_FP].i)
+             {
+             case 2:
+               _bfd_error_handler
+                 (_("Warning: %B uses -msingle-float, %B uses -mdouble-float"),
+                  obfd, ibfd);
+
+             case 3:
+               _bfd_error_handler
+                 (_("Warning: %B uses hard float, %B uses soft float"),
+                  obfd, ibfd);
+               break;
+
+             default:
+               abort ();
+             }
+           break;
+
+         case 2:
+           switch (in_attr[Tag_GNU_MIPS_ABI_FP].i)
+             {
+             case 1:
+               _bfd_error_handler
+                 (_("Warning: %B uses -msingle-float, %B uses -mdouble-float"),
+                  ibfd, obfd);
+
+             case 3:
+               _bfd_error_handler
+                 (_("Warning: %B uses hard float, %B uses soft float"),
+                  obfd, ibfd);
+               break;
+
+             default:
+               abort ();
+             }
+           break;
+
+         case 3:
+           switch (in_attr[Tag_GNU_MIPS_ABI_FP].i)
+             {
+             case 1:
+             case 2:
+               _bfd_error_handler
+                 (_("Warning: %B uses hard float, %B uses soft float"),
+                  ibfd, obfd);
+               break;
+
+             default:
+               abort ();
+             }
+           break;
+
+         default:
+           abort ();
+         }
+    }
+
+  /* Merge Tag_compatibility attributes and any common GNU ones.  */
+  _bfd_elf_merge_object_attributes (ibfd, obfd);
+
+  return TRUE;
+}
+
 /* Merge backend specific data from an object file to the output
    object file when linking.  */
 
@@ -10991,6 +11143,9 @@ _bfd_mips_elf_merge_private_bfd_data (bfd *ibfd, bfd *obfd)
       return FALSE;
     }
 
+  if (!mips_elf_merge_obj_attributes (ibfd, obfd))
+    return FALSE;
+
   new_flags = elf_elfheader (ibfd)->e_flags;
   elf_elfheader (obfd)->e_flags |= new_flags & EF_MIPS_NOREORDER;
   old_flags = elf_elfheader (obfd)->e_flags;
This page took 0.029883 seconds and 4 git commands to generate.