daily update
[deliverable/binutils-gdb.git] / bfd / elfxx-mips.c
index 45917811a40571ac8b2df265cb653eb933d08920..cdc81a229d5bf770c1d998a5d4c207e120dd193d 100644 (file)
@@ -335,6 +335,8 @@ struct mips_elf_link_hash_table
   bfd_vma plt_header_size;
   /* The size of a PLT entry in bytes (VxWorks only).  */
   bfd_vma plt_entry_size;
+  /* The size of a function stub entry in bytes.  */
+  bfd_vma function_stub_size;
 };
 
 #define TLS_RELOC_P(r_type) \
@@ -633,16 +635,15 @@ static bfd *reldyn_sorting_bfd;
      : 0x03e07821))                            /* addu t7,ra */
 #define STUB_LUI(VAL) (0x3c180000 + (VAL))     /* lui t8,VAL */
 #define STUB_JALR 0x0320f809                   /* jalr t9,ra */
-#define STUB_LI16U(VAL) (0x34180000 + (VAL))   /* ori t8,zero,VAL unsigned*/
+#define STUB_ORI(VAL) (0x37180000 + (VAL))     /* ori t8,t8,VAL */
+#define STUB_LI16U(VAL) (0x34180000 + (VAL))   /* ori t8,zero,VAL unsigned */
 #define STUB_LI16S(abfd, VAL)                                          \
    ((ABI_64_P (abfd)                                                   \
     ? (0x64180000 + (VAL))     /* daddiu t8,zero,VAL sign extended */  \
     : (0x24180000 + (VAL))))   /* addiu t8,zero,VAL sign extended */
 
-#define MIPS_FUNCTION_STUB_SIZE(INFO) \
-  (elf_hash_table (INFO)->dynsymcount > 65536 ? 20 : 16)
-
-#define MIPS_FUNCTION_STUB_MAX_SIZE 20
+#define MIPS_FUNCTION_STUB_NORMAL_SIZE 16
+#define MIPS_FUNCTION_STUB_BIG_SIZE 20
 
 /* The name of the dynamic interpreter.  This is put in the .interp
    section.  */
@@ -3582,9 +3583,12 @@ mips_elf_next_relocation (bfd *abfd ATTRIBUTE_UNUSED, unsigned int r_type,
                          const Elf_Internal_Rela *relocation,
                          const Elf_Internal_Rela *relend)
 {
+  unsigned long r_symndx = ELF_R_SYM (abfd, relocation->r_info);
+
   while (relocation < relend)
     {
-      if (ELF_R_TYPE (abfd, relocation->r_info) == r_type)
+      if (ELF_R_TYPE (abfd, relocation->r_info) == r_type
+         && ELF_R_SYM (abfd, relocation->r_info) == r_symndx)
        return relocation;
 
       ++relocation;
@@ -4074,6 +4078,8 @@ mips_elf_calculate_relocation (bfd *abfd, bfd *input_bfd,
        }
 
       symbol = sec->output_section->vma + sec->output_offset;
+      /* The target is 16-bit, but the stub isn't.  */
+      target_is_16_bit_code_p = FALSE;
     }
   /* 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.  */
@@ -4468,7 +4474,8 @@ mips_elf_calculate_relocation (bfd *abfd, bfd *input_bfd,
     case R_MIPS_GNU_REL16_S2:
       value = symbol + _bfd_mips_elf_sign_extend (addend, 18) - p;
       overflowed_p = mips_elf_overflow_p (value, 18);
-      value = (value >> 2) & howto->dst_mask;
+      value >>= howto->rightshift;
+      value &= howto->dst_mask;
       break;
 
     case R_MIPS_GOT_HI16:
@@ -5088,6 +5095,7 @@ _bfd_mips_elf_symbol_processing (bfd *abfd, asymbol *asym)
       /* Common symbols less than the GP size are automatically
         treated as SHN_MIPS_SCOMMON symbols on IRIX5.  */
       if (asym->value > elf_gp_size (abfd)
+         || ELF_ST_TYPE (elfsym->internal_elf_sym.st_info) == STT_TLS
          || IRIX_COMPAT (abfd) == ict_irix6)
        break;
       /* Fall through.  */
@@ -5728,6 +5736,7 @@ _bfd_mips_elf_add_symbol_hook (bfd *abfd, struct bfd_link_info *info,
       /* Common symbols less than the GP size are automatically
         treated as SHN_MIPS_SCOMMON symbols.  */
       if (sym->st_size > elf_gp_size (abfd)
+         || ELF_ST_TYPE (sym->st_info) == STT_TLS
          || IRIX_COMPAT (abfd) == ict_irix6)
        break;
       /* Fall through.  */
@@ -6830,7 +6839,9 @@ _bfd_mips_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
   bfd *dynobj;
   struct mips_elf_link_hash_entry *hmips;
   asection *s;
+  struct mips_elf_link_hash_table *htab;
 
+  htab = mips_elf_hash_table (info);
   dynobj = elf_hash_table (info)->dynobj;
 
   /* Make sure we know what is going on here.  */
@@ -6883,7 +6894,7 @@ _bfd_mips_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
          h->plt.offset = s->size;
 
          /* Make room for this stub code.  */
-         s->size += MIPS_FUNCTION_STUB_SIZE (info);
+         s->size += htab->function_stub_size;
 
          /* The last half word of the stub will be filled with the index
             of this symbol in .dynsym section.  */
@@ -7071,6 +7082,32 @@ _bfd_mips_vxworks_adjust_dynamic_symbol (struct bfd_link_info *info,
   return TRUE;
 }
 \f
+/* Return the number of dynamic section symbols required by OUTPUT_BFD.
+   The number might be exact or a worst-case estimate, depending on how
+   much information is available to elf_backend_omit_section_dynsym at
+   the current linking stage.  */
+
+static bfd_size_type
+count_section_dynsyms (bfd *output_bfd, struct bfd_link_info *info)
+{
+  bfd_size_type count;
+
+  count = 0;
+  if (info->shared || elf_hash_table (info)->is_relocatable_executable)
+    {
+      asection *p;
+      const struct elf_backend_data *bed;
+
+      bed = get_elf_backend_data (output_bfd);
+      for (p = output_bfd->sections; p ; p = p->next)
+       if ((p->flags & SEC_EXCLUDE) == 0
+           && (p->flags & SEC_ALLOC) != 0
+           && !(*bed->elf_backend_omit_section_dynsym) (output_bfd, info, p))
+         ++count;
+    }
+  return count;
+}
+
 /* This function is called after all the input files have been read,
    and the input sections have been assigned to output sections.  We
    check for any mips16 stub sections that we can discard.  */
@@ -7087,6 +7124,7 @@ _bfd_mips_elf_always_size_sections (bfd *output_bfd,
   int i;
   bfd_size_type loadable_size = 0;
   bfd_size_type local_gotno;
+  bfd_size_type dynsymcount;
   bfd *sub;
   struct mips_elf_count_tls_arg count_tls_arg;
   struct mips_elf_link_hash_table *htab;
@@ -7145,10 +7183,22 @@ _bfd_mips_elf_always_size_sections (bfd *output_bfd,
        relocations, then GLOBAL_GOTSYM will be NULL.  */
     i = 0;
 
+  /* Get a worst-case estimate of the number of dynamic symbols needed.
+     At this point, dynsymcount does not account for section symbols
+     and count_section_dynsyms may overestimate the number that will
+     be needed.  */
+  dynsymcount = (elf_hash_table (info)->dynsymcount
+                + count_section_dynsyms (output_bfd, info));
+
+  /* Determine the size of one stub entry.  */
+  htab->function_stub_size = (dynsymcount > 0x10000
+                             ? MIPS_FUNCTION_STUB_BIG_SIZE
+                             : MIPS_FUNCTION_STUB_NORMAL_SIZE);
+
   /* In the worst case, we'll get one stub per dynamic symbol, plus
      one to account for the dummy entry at the end required by IRIX
      rld.  */
-  loadable_size += MIPS_FUNCTION_STUB_SIZE (info) * (i + 1);
+  loadable_size += htab->function_stub_size * (i + 1);
 
   if (htab->is_vxworks)
     /* There's no need to allocate page entries for VxWorks; R_MIPS_GOT16
@@ -7365,14 +7415,14 @@ _bfd_mips_elf_size_dynamic_sections (bfd *output_bfd,
       else if (strcmp (name, MIPS_ELF_STUB_SECTION_NAME (output_bfd)) == 0)
        {
          /* IRIX rld assumes that the function stub isn't at the end
-            of .text section. So put a dummy. XXX  */
-         s->size += MIPS_FUNCTION_STUB_SIZE (info);
+            of .text section.  So put a dummy.  XXX  */
+         s->size += htab->function_stub_size;
        }
       else if (! info->shared
               && ! mips_elf_hash_table (info)->use_rld_obj_head
               && strncmp (name, ".rld_map", 8) == 0)
        {
-         /* We add a room for __rld_map. It will be filled in by the
+         /* We add a room for __rld_map.  It will be filled in by the
             rtld to contain a pointer to the _r_debug structure.  */
          s->size += 4;
        }
@@ -8004,13 +8054,15 @@ _bfd_mips_elf_finish_dynamic_symbol (bfd *output_bfd,
   struct mips_got_info *g, *gg;
   const char *name;
   int idx;
+  struct mips_elf_link_hash_table *htab;
 
+  htab = mips_elf_hash_table (info);
   dynobj = elf_hash_table (info)->dynobj;
 
   if (h->plt.offset != MINUS_ONE)
     {
       asection *s;
-      bfd_byte stub[MIPS_FUNCTION_STUB_MAX_SIZE];
+      bfd_byte stub[MIPS_FUNCTION_STUB_BIG_SIZE];
 
       /* This symbol has a stub.  Set it up.  */
 
@@ -8020,13 +8072,13 @@ _bfd_mips_elf_finish_dynamic_symbol (bfd *output_bfd,
                                   MIPS_ELF_STUB_SECTION_NAME (dynobj));
       BFD_ASSERT (s != NULL);
 
-      BFD_ASSERT ((MIPS_FUNCTION_STUB_SIZE (info) == 20)
-                  || (h->dynindx <= 65536));
+      BFD_ASSERT ((htab->function_stub_size == MIPS_FUNCTION_STUB_BIG_SIZE)
+                  || (h->dynindx <= 0xffff));
 
       /* Values up to 2^31 - 1 are allowed.  Larger values would cause
-         sign extension at runtime in the stub, resulting in a
-         negative index value.  */
-      if (h->dynindx & 0x80000000)
+        sign extension at runtime in the stub, resulting in a negative
+        index value.  */
+      if (h->dynindx & ~0x7fffffff)
        return FALSE;
 
       /* Fill the stub.  */
@@ -8035,9 +8087,9 @@ _bfd_mips_elf_finish_dynamic_symbol (bfd *output_bfd,
       idx += 4;
       bfd_put_32 (output_bfd, STUB_MOVE (output_bfd), stub + idx);
       idx += 4;
-      if (MIPS_FUNCTION_STUB_SIZE (info) == 20)
+      if (htab->function_stub_size == MIPS_FUNCTION_STUB_BIG_SIZE)
         {
-          bfd_put_32 (output_bfd, STUB_LUI ((h->dynindx >> 16 ) & 0xffff),
+          bfd_put_32 (output_bfd, STUB_LUI ((h->dynindx >> 16) & 0x7fff),
                       stub + idx);
           idx += 4;
         }
@@ -8046,15 +8098,16 @@ _bfd_mips_elf_finish_dynamic_symbol (bfd *output_bfd,
 
       /* If a large stub is not required and sign extension is not a
          problem, then use legacy code in the stub.  */
-      if ((MIPS_FUNCTION_STUB_SIZE (info) == 20) || (h->dynindx & 0xffff8000))
+      if (htab->function_stub_size == MIPS_FUNCTION_STUB_BIG_SIZE)
+       bfd_put_32 (output_bfd, STUB_ORI (h->dynindx & 0xffff), stub + idx);
+      else if (h->dynindx & ~0x7fff)
         bfd_put_32 (output_bfd, STUB_LI16U (h->dynindx & 0xffff), stub + idx);
       else
-        bfd_put_32 (output_bfd,
-                    STUB_LI16S (output_bfd, h->dynindx & 0xffff), stub + idx);
-        
+        bfd_put_32 (output_bfd, STUB_LI16S (output_bfd, h->dynindx),
+                   stub + idx);
+
       BFD_ASSERT (h->plt.offset <= s->size);
-      memcpy (s->contents + h->plt.offset,
-              stub, MIPS_FUNCTION_STUB_SIZE (info));
+      memcpy (s->contents + h->plt.offset, stub, htab->function_stub_size);
 
       /* Mark the symbol as undefined.  plt.offset != -1 occurs
         only for the referenced symbol.  */
@@ -8738,11 +8791,10 @@ _bfd_mips_elf_finish_dynamic_sections (bfd *output_bfd,
          MIPS_ELF_PUT_WORD (output_bfd, (bfd_vma) 0x80000000,
                             sgot->contents + MIPS_ELF_GOT_SIZE (output_bfd));
        }
-    }
 
-  if (sgot != NULL)
-    elf_section_data (sgot->output_section)->this_hdr.sh_entsize
-      = MIPS_ELF_GOT_SIZE (output_bfd);
+      elf_section_data (sgot->output_section)->this_hdr.sh_entsize
+        = MIPS_ELF_GOT_SIZE (output_bfd);
+    }
 
   /* Generate dynamic relocations for the non-primary gots.  */
   if (gg != NULL && gg->next)
@@ -8857,10 +8909,10 @@ _bfd_mips_elf_finish_dynamic_sections (bfd *output_bfd,
              {
                file_ptr dummy_offset;
 
-               BFD_ASSERT (s->size >= MIPS_FUNCTION_STUB_SIZE (info));
-               dummy_offset = s->size - MIPS_FUNCTION_STUB_SIZE (info);
+               BFD_ASSERT (s->size >= htab->function_stub_size);
+               dummy_offset = s->size - htab->function_stub_size;
                memset (s->contents + dummy_offset, 0,
-                       MIPS_FUNCTION_STUB_SIZE (info));
+                       htab->function_stub_size);
              }
          }
       }
@@ -9091,7 +9143,8 @@ _bfd_mips_elf_final_write_processing (bfd *abfd,
    segments.  */
 
 int
-_bfd_mips_elf_additional_program_headers (bfd *abfd)
+_bfd_mips_elf_additional_program_headers (bfd *abfd,
+                                         struct bfd_link_info *info ATTRIBUTE_UNUSED)
 {
   asection *s;
   int ret = 0;
@@ -9182,15 +9235,18 @@ _bfd_mips_elf_modify_segment_map (bfd *abfd,
                     || (*pm)->p_type == PT_INTERP))
            pm = &(*pm)->next;
 
-         amt = sizeof (struct elf_segment_map);
-         options_segment = bfd_zalloc (abfd, amt);
-         options_segment->next = *pm;
-         options_segment->p_type = PT_MIPS_OPTIONS;
-         options_segment->p_flags = PF_R;
-         options_segment->p_flags_valid = TRUE;
-         options_segment->count = 1;
-         options_segment->sections[0] = s;
-         *pm = options_segment;
+         if (*pm == NULL || (*pm)->p_type != PT_MIPS_OPTIONS)
+           {
+             amt = sizeof (struct elf_segment_map);
+             options_segment = bfd_zalloc (abfd, amt);
+             options_segment->next = *pm;
+             options_segment->p_type = PT_MIPS_OPTIONS;
+             options_segment->p_flags = PF_R;
+             options_segment->p_flags_valid = TRUE;
+             options_segment->count = 1;
+             options_segment->sections[0] = s;
+             *pm = options_segment;
+           }
        }
     }
   else
@@ -9972,6 +10028,7 @@ _bfd_mips_elf_link_hash_table_create (bfd *abfd)
   ret->splt = NULL;
   ret->plt_header_size = 0;
   ret->plt_entry_size = 0;
+  ret->function_stub_size = 0;
 
   return &ret->root.root;
 }
@@ -10047,18 +10104,7 @@ _bfd_mips_elf_final_link (bfd *abfd, struct bfd_link_info *info)
         we count the sections after (possibly) removing the .options
         section above.  */
 
-      dynsecsymcount = 0;
-      if (info->shared)
-       {
-         asection * p;
-
-         for (p = abfd->sections; p ; p = p->next)
-           if ((p->flags & SEC_EXCLUDE) == 0
-               && (p->flags & SEC_ALLOC) != 0
-               && !(*bed->elf_backend_omit_section_dynsym) (abfd, info, p))
-             ++ dynsecsymcount;
-       }
-
+      dynsecsymcount = count_section_dynsyms (abfd, info);
       if (! mips_elf_sort_hash_table (info, dynsecsymcount + 1))
        return FALSE;
 
@@ -10809,7 +10855,9 @@ _bfd_mips_elf_merge_private_bfd_data (bfd *ibfd, bfd *obfd)
        = elf_elfheader (ibfd)->e_ident[EI_CLASS];
 
       if (bfd_get_arch (obfd) == bfd_get_arch (ibfd)
-         && bfd_get_arch_info (obfd)->the_default)
+         && (bfd_get_arch_info (obfd)->the_default
+             || mips_mach_extends_p (bfd_get_mach (obfd), 
+                                     bfd_get_mach (ibfd))))
        {
          if (! bfd_set_arch_mach (obfd, bfd_get_arch (ibfd),
                                   bfd_get_mach (ibfd)))
@@ -11067,15 +11115,25 @@ const struct bfd_elf_special_section _bfd_mips_elf_special_sections[] =
   { NULL,      0,  0, 0,              0 }
 };
 
-/* Ensure that the STO_OPTIONAL flag is copied into h->other,
-   even if this is not a defintion of the symbol.  */
+/* Merge non visibility st_other attributes.  Ensure that the
+   STO_OPTIONAL flag is copied into h->other, even if this is not a
+   definiton of the symbol.  */
 void
 _bfd_mips_elf_merge_symbol_attribute (struct elf_link_hash_entry *h,
                                      const Elf_Internal_Sym *isym,
                                      bfd_boolean definition,
                                      bfd_boolean dynamic ATTRIBUTE_UNUSED)
 {
-  if (! definition
+  if ((isym->st_other & ~ELF_ST_VISIBILITY (-1)) != 0)
+    {
+      unsigned char other;
+
+      other = (definition ? isym->st_other : h->other);
+      other &= ~ELF_ST_VISIBILITY (-1);
+      h->other = other | ELF_ST_VISIBILITY (h->other);
+    }
+
+  if (!definition
       && ELF_MIPS_IS_OPTIONAL (isym->st_other))
     h->other |= STO_OPTIONAL;
 }
@@ -11087,3 +11145,11 @@ _bfd_mips_elf_ignore_undef_symbol (struct elf_link_hash_entry *h)
 {
   return ELF_MIPS_IS_OPTIONAL (h->other) ? TRUE : FALSE;
 }
+
+bfd_boolean
+_bfd_mips_elf_common_definition (Elf_Internal_Sym *sym)
+{
+  return (sym->st_shndx == SHN_COMMON
+         || sym->st_shndx == SHN_MIPS_ACOMMON
+         || sym->st_shndx == SHN_MIPS_SCOMMON);
+}
This page took 0.033475 seconds and 4 git commands to generate.